5

我有一个在该视图中使用父范围的指令。该指令有一个使用隔离范围的子指令。我试图让父指令观察对子指令的 ngModel 所做的任何更改,并在进行更改时更新其自己的模式。这是一个可能解释得更好的 jsfiddle:http: //jsfiddle.net/Alien_time/CnDKN/

这是代码:

   <div ng-app="app">
        <div ng-controller="MyController">

            <form name="someForm">
                <div this-directive ng-model="theModel"></div>
            </form>

         </div>
    </div>

Javascript:

    var app = angular.module('app', []);
app.controller('MyController', function() {

});

app.directive('thisDirective', function($compile, $timeout) {

    return {
        scope: false,

        link: function(scope, element, attrs) {
            var ngModel = attrs.ngModel;
            var htmlText = '<input type="text" ng-model="'+ ngModel + '" />' +
                           '<div child-directive ng-model="'+ ngModel + '"></div>';

            $compile(htmlText)(scope, function(_element, _scope) {
                element.replaceWith(_element);                
            });

            // Not sure how to watch changes in childDirective's ngModel ???????

        }, // end link
    } // end return

});

app.directive('childDirective', function($compile, $timeout) {
    return {
            scope: {
                ngModel: '='            
        },  

        link: function(scope, element, attrs, ngModel) {
            var htmlText = '<input type="text" ng-model="ngModel" />';

            $compile(htmlText)(scope, function(_element, _scope) {
                element.replaceWith(_element);                
            });   

            // Here the directive text field updates after some server side process
            scope.ngModel = scope.dbInsertId;

            scope.$watch('dbInsertId', function(newValue, oldValue) {
                if (newValue)
                    console.log("I see a data change!");  // Delete this later
                    scope.ngModel = scope.imageId;
            }, true);

        },

    } // end return
});

在示例中,您可以看到在父指令及其子指令中都有一个文本输入。如果您在每个模型中键入,则另一个模型会更新,因为它们是由ngmodel. 但是,子指令的文本输入会在服务器连接后更新。发生这种情况时,父指令中的文本输入不会更新。所以我认为我需要观察子指令中的 ngModel 是否有任何变化。我怎样才能做到这一点?是否有意义?

4

1 回答 1

13

正如@shaunhusain 提到的,您必须使用 ngModelController 与 ngModel 进行交互。在 ngModelController 上,您可以在 上设置监视,$modelValue并且可以通过调用来更改模型中的值$setViewValue。请记住,要使用 ngModelController,您需要在require: "ngModel"指令定义对象中添加一个。

当您从 Angular 之外(例如从您的数据库中)获取一个值并且您又想使用该值来更改模型值时,您需要将该代码包装在scope.$apply()

app.directive('thisDirective', function($compile, $timeout, $log) {

    return {
        scope: false,
        require: 'ngModel',

        link: function(scope, element, attrs, ngModel) {
            ...

            scope.$watch(
                function(){
                    return ngModel.$modelValue;
                }, function(newValue, oldValue){
                    $log.info('in *thisDirective* model value changed...', newValue, oldValue);
                }, true);

        }, // end link
    } // end return

});

app.directive('childDirective', function($compile, $timeout, $log) {
    return {
        scope: {
            ngModel: '='
        },
        require: 'ngModel',

        link: function(scope, element, attrs, ngModel) {
            ...

            scope.$watch(
                function(){
                    return ngModel.$modelValue;
                }, function(newValue, oldValue){
                    $log.info('in *childDirective* model value changed...', newValue, oldValue);
                }, true);

            // make believe change by server
            setTimeout(function() {
                scope.$apply(function() {
                    ngModel.$setViewValue('set from the server...');
                };
            },5000);


        },

    } // end return
});

相关的jsfiddle http://jsfiddle.net/CnDKN/2/

我认为这不是真正正确的$setViewValue. 根据文档,这应该用于更新 UI 上显示的值,不一定是模型值。

实际上还有另一种制作这项工作的方法,我认为它更直接且更易于使用。只需用于设置要在和 中=attr使用的属性的双向绑定。然后你可以在你的指令中设置 ng-model 属性设置,当你第一次使用它时,你甚至不需要知道它在下面使用 ng-model。thisDirectivechildDirective

这是向您展示我的意思的代码:

app.directive('thisDirective', function($compile, $timeout, $log) {

    return {
        scope: {
            thisval: '='
        },

        link: function(scope, element, attrs) {

            var htmlText = '<input type="text" ng-model="thisval" />' +
                           '<div child-directive childval="thisval"></div>';

            $compile(htmlText)(scope, function(_element, _scope) {
                element.replaceWith(_element);                
            });

            scope.$watch('thisval',function(newVal,oldVal){
                $log.info('in *thisDirective* thisval changed...',
                          newVal, oldVal);
            });


        }, // end link
    } // end return

});

app.directive('childDirective', function($compile, $timeout, $log) {
    return {
        scope: {
            childval: '='
        },

        link: function(scope, element, attrs) {
            var htmlText = '<input type="text" ng-model="childval" />';

            $compile(htmlText)(scope, function(_element, _scope) {
                element.replaceWith(_element);                
            });

            scope.$watch('childval',function(newVal,oldVal){
                $log.info('in *childDirective* childval changed...',
                          newVal, oldVal);
            });

            // make believe change that gets called outside of angular
            setTimeout(function() {
                // need to wrap the setting of values in the scope 
                // inside of an $apply so that a digest cycle will be 
                // started and have all of the watches on the value called
                scope.$apply(function(){
                    scope.childval = "set outside of angular...";
                });
            },5000);

        },

    } // end return
});

更新了 jsfiddle 示例:http: //jsfiddle.net/CnDKN/3/

于 2014-04-03T15:02:30.393 回答