【问题标题】:In Angularjs can a controller nested inside a directive set the ng-model of the directive?在 Angularjs 中,嵌套在指令中的控制器可以设置指令的 ng-model 吗?
【发布时间】:2013-06-16 16:33:16
【问题描述】:

我有一个指令,它使用 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?
  }

}

【问题讨论】:

  • nestedInDirController 已经可以访问在myController 的范围内定义的属性,因为范围原型继承。在您的nestedInDirController 中,这有效:console.log($scope.viewModel),这也是:$scope.viewModel.foo.bar = "testing";

标签: javascript web-applications angularjs angularjs-directive


【解决方案1】:

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'");
    });
}

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

【讨论】:

    【解决方案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";
        }
    
    }
    

    【讨论】:

    • 哈哈,你阻止了我犯一个过于复杂的错误。
    猜你喜欢
    • 1970-01-01
    • 2012-10-23
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多