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 に答える