在Angularjs中,嵌套在指令内的控制器是否可以设置指令的ng-model?

时间:2013-06-19 23:44:01

标签: javascript web-applications angularjs angularjs-directive

我有一个使用ng-model控制器的指令,并从里面的控制器“myController”获取模型值。我正在使用transclude = true和ng-transclude。这是一个通用指令,我希望允许我的同事重复使用。我想让消费者点击按钮,它将ngModel值设置为他们想要的任何值,但基本上总是一些对象。我该如何正确设置?我在指令中意识到我可以调用ngModel。$ setValue或$ setViewValue等...抱歉,我仍然是angularjs的新手,特别是指令。我也应该在指令中使用控制器吗?我知道指令的对象定义具有这种能力,尽管我真的不知道如何或何时利用它。最后是否可以将控制器转换为指令,就像在“nestedInDirController”中一样?感谢您提供任何提示,技巧,示例或建议。

jsfiddle here

<div ng-controller="myController">
    <div foo-directive="" ng-model="viewModel.foo">
        <div ng-controller="nestedInDirController">
           <various-controls-in-here />
        </div>
    </div>
 </div>

angular.module('myApp', [])
 .directive('fooDirective', function(){ 

    var template = '<div><div ng-transclude></div> <button ng-click="someFunc()">I want to update ng-model in the directive, which in turn will update myController $scope.viewModel.foo</button></div>';
   return {
      transclude: true,
      require: '?ngModel',
      template: template,
      compile: function(tElement, tAttrs, transclude){

         return function(scope, element, attrs, ngModel){

         }
      }
    };
 });

function myController($scope){

  $scope.viewModel = { foo : { bar: 'baz'}};   
 }

function nestedInDirController($scope){


  $scope.someFunc = function(){
      alert('I was called');
      //how can I set ng-model in foo-directive from this controller?
  }

}

2 个答案:

答案 0 :(得分:2)

http://jsfiddle.net/jSEba/

这是通过使用事件发射来满足您需求的一种方法。

即。让$broadcast事件的指令进入其子范围, 因此,被盗的子范围可以通过$on捕获以对此作出反应 按钮单击。

angular.module('myApp', [])
.directive('fooDirective', function(){ 
    var template = '<div><div ng-transclude></div> <button ng-click="someFunc()">I want to update ng-model in the directive, which in turn will update myController $scope.viewModel.foo</button></div>';
    return {
        transclude: true,
        template: template,
        link: function(scope, elem, attrs) {
            scope.someFunc = function() {
                scope.$broadcast('buttonclick', { valname: attrs.fooDirective });
            };
        }
    };
});

function myController($scope){
    $scope.viewModel = { foo : { bar: 'baz'}};   
}

function nestedInDirController($scope){
    $scope.$on('buttonclick', function(event, arg) {
        $scope.$eval( arg.valname + " = 'new value'");
    });
}

我怀疑可能有更好的方法。

答案 1 :(得分:2)

这是在指令和控制器之间使用共享服务的另一种解决方案。

(您可以创建一个更好的服务来强制执行在特定情况下控制器之间共享所需的数据结构,而不是一般示例。)

这是一个jsfiddle http://jsfiddle.net/PguFh/15/(在我编写下面的代码后稍微更新一下)。

<强>的index.html

<div ng-controller="myController">
    <div foo-directive="" ng-model="viewModel.foo">
        <div ng-controller="nestedInDirController">
            <pre>{{viewModel.foo|json}}</pre>
        </div>
    </div>
</div>

<强> app.js

angular.module('myApp', [])

.factory('Shared', function() {
    var shared = {};

    return {
        set: function(value) {
            shared = value;
        },
        get: function() {
            return shared;   
       }
    }
})

.directive('fooDirective', function(Shared){ 

    var template = '<div><div ng-transclude></div> <button ng-click="shared.someFunc()">I want to update ng-model in the directive, which in turn will update myController $scope.viewModel.foo</button></div>';
    return {
        transclude: true,
        require: '?ngModel',
        template: template,
        compile: function(tElement, tAttrs, transclude){

            return function(scope, element, attrs, ngModel) {
                scope.shared = Shared.get();
            }
        }
    };
});

function myController($scope, Shared){

    $scope.viewModel = { foo : { bar: 'baz'}};  
    Shared.set({
        viewModel: $scope.viewModel,
        someFunc: function() { alert('default?'); }
    });
}

function nestedInDirController($scope, Shared){
    var shared = Shared.get();
    shared.someFunc = function(){
        alert('I was called');
        //how can I set ng-model in foo-directive from this controller?
        shared.viewModel.foo.bar = "baz.modified";
    }

}