В Angularjs может ли контроллер, вложенный внутри директивы, установить ng-модель директивы?

У меня есть директива, которая использует контроллер ng-model и получает значение модели от контроллера, который находится внутри, «myController». Я использую transclude = true и ng-transclude. Это директива общего назначения, которую я хочу разрешить моим коллегам повторно использовать. Я хочу, чтобы потребитель щелкнул кнопку, и он установил значение ngModel на любое значение, которое они хотят, но в основном всегда какой-то объект. Как мне это правильно настроить? Я понимаю, что внутри директивы я могу вызвать ngModel. $ SetValue или $ setViewValue и т.д. Извините, я все еще новичок в angularjs, в частности директивах. Также я должен использовать контроллер внутри директивы? Я знаю, что определение объекта для директив имеет такую ​​возможность, хотя на самом деле не знаю, как и когда использовать это. Наконец, можно ли включать контроллеры в директивы, как в "nestedInDirController"? Спасибо за любые советы, уловки, примеры или советы.

jsfiddle здесь

<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?
  }

}

person Hcabnettek    schedule 19.06.2013    source источник
comment
nestedInDirController уже имеет доступ к свойствам, определенным в области myController, потому что область прототипически наследуется. Внутри вашего nestedInDirController это работает: console.log($scope.viewModel) и то же самое: $scope.viewModel.foo.bar = "testing";   -  person Mark Rajcok    schedule 21.06.2013


Ответы (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'");
    });
}

Я подозреваю, что есть способ получше.

person Tosh    schedule 20.06.2013

Это еще одно решение, использующее общую службу между директивой и контроллерами.

(Вы могли бы создать лучшую службу, чтобы обеспечить совместное использование необходимой структуры данных между контроллерами в этом конкретном случае, а не в общем примере.)

Вот 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";
    }

}
person jpmorin    schedule 06.10.2013
comment
Лол, ты помешал мне сделать слишком сложную ошибку. - person Michael J. Calkins; 13.01.2014