ngChange在值超出隔离范围之前触发 [英] ngChange fires before value makes it out of isolate scope

查看:99
本文介绍了ngChange在值超出隔离范围之前触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

//main controller
angular.module('myApp')
.controller('mainCtrl', function ($scope){
    $scope.loadResults = function (){
        console.log($scope.searchFilter);
    };
});

// directive
angular.module('myApp')
.directive('customSearch', function () {
    return {
        scope: {
            searchModel: '=ngModel',
            searchChange: '&ngChange',
        },
        require: 'ngModel',
        template: '<input type="text" ng-model="searchModel" ng-change="searchChange()"/>',
        restrict: 'E'
    };
});

// html
<custom-search ng-model="searchFilter" ng-change="loadResults()"></custom-search>

这里是一个简化的指令来说明。当我输入内容时,我希望 loadResults 中的 console.log 完全注销我已经输入的内容。它实际上记录了一个字符,因为 loadResults 正运行在主控制器中的 searchFilter 变量即将接收到新值之前从指令。但是在指令内部登录,一切都会按预期进行。为什么会发生这种情况?

Here is a simplified directive to illustrate. When I type into the input, I expect the console.log in loadResults to log out exactly what I have already typed. It actually logs one character behind because loadResults is running just before the searchFilter var in the main controller is receiving the new value from the directive. Logging inside the directive however, everything works as expected. Why is this happening?

我的解决方案

了解了什么之后在我的简单示例中发生了ngChange时,我意识到我实际传递的ngModel是一个对象,而我正在更改的属性使我的实际问题更加复杂了,而且我正在为此使用表单验证指令作为输入之一。我发现在指令中使用$ timeout和$ eval解决了我所有的问题:

After getting an understanding of what was happening with ngChange in my simple example, I realized my actual problem was complicated a bit more by the fact that the ngModel I am actually passing in is an object, whose properties i am changing, and also that I am using form validation with this directive as one of the inputs. I found that using $timeout and $eval inside the directive solved all of my problems:

//main controller
angular.module('myApp')
.controller('mainCtrl', function ($scope){
    $scope.loadResults = function (){
        console.log($scope.searchFilter);
    };
});

// directive
angular.module('myApp')
.directive('customSearch', function ($timeout) {
    return {
        scope: {
            searchModel: '=ngModel'
        },
        require: 'ngModel',
        template: '<input type="text" ng-model="searchModel.subProp" ng-change="valueChange()"/>',
        restrict: 'E',
        link: function ($scope, $element, $attrs, ngModel)
        {
            $scope.valueChange = function()
            {
                $timeout(function()
                {
                    if ($attrs.ngChange) $scope.$parent.$eval($attrs.ngChange);
                }, 0);
            };
        }
    };
});

// html
<custom-search ng-model="searchFilter" ng-change="loadResults()"></custom-search>


推荐答案

您在标题中回答了自己的问题! '='被观看,而'&'未被观看

You answered your own question in the title! '=' is watched while '&' is not


  • 某个角度之外的地方:

  • Somewhere outside angular:

输入视图值变化

下一摘要循环:

ng模型值更改并触发 ng -change()

ng-change添加一个$ viewChangeListener,并且被称为同一循环。
请参阅:
ngModel.js#L714 ngChange.js 实现。

ng-change adds a $viewChangeListener and is called this same cycle. See: ngModel.js#L714 and ngChange.js implementation.

当时 $ scope.searchFilter 尚未更新。 Console.log的旧值

At that time $scope.searchFilter hasn't been updated. Console.log's old value

更新:仅作为POC,您需要1个额外的周期才能传播值,您可以执行以下操作。请参见另一个anwser(@NewDev,这是一种更清洁的方法)。

UPDATE: Only as a POC that you need 1 extra cycle for the value to propagate you can do the following. See the other anwser (@NewDev for a cleaner approach).

.controller('mainCtrl', function ($scope, $timeout){
    $scope.loadResults = function (){
        $timeout(function(){
           console.log($scope.searchFilter);
        });
    };
});

这篇关于ngChange在值超出隔离范围之前触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆