gpt4 book ai didi

angularjs - ngChange 在 value 超出隔离范围之前触发

转载 作者:行者123 更新时间:2023-12-04 05:37:29 25 4
gpt4 key购买 nike

//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>

这是一个简化的指令来说明。当我输入输入时,我期望 console.logloadResults准确地注销我已经输入的内容。它实际上记录了一个字符,因为 loadResultssearchFilter 之前运行主 Controller 中的 var 正在接收来自指令的新值。然而,在指令中登录,一切都按预期工作。为什么会这样?

我的解决方案

在我的简单示例中了解了 ngChange 发生的情况后,我意识到我的实际问题更加复杂,因为我实际传入的 ngModel 是一个对象,我正在更改其属性,而且我我正在使用带有此指令的表单验证作为输入之一。我发现在指令中使用 $timeout 和 $eval 解决了我所有的问题:
//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>

最佳答案

正如另一个答案中正确指出的那样,这种行为的原因是双向绑定(bind)没有机会更改外部 searchFilter到时候searchChange() ,因此,loadResults()被调用。

然而,由于两个原因,该解决方案非常棘手。

第一,调用者(指令的用户)不需要知道 $timeout 的这些变通方法。 .如果不出意外,$timeout应该在指令中而不是在 View Controller 中完成。

还有两个 - OP 也犯了一个错误 - 是使用 ng-model带有此类指令的用户的其他“期望”。有ng-model意味着其他指令,如验证器、解析器、格式化程序和 View 更改监听器(如 ng-change )可以与它一起使用。要正确支持它,需要require: "ngModel" , 而不是通过 scope: {} 绑定(bind)到它的表达式.否则,事情将无法按预期进行。

下面是它的完成方式 - 另一个例子,见 the official documentation用于创建自定义输入控件。

scope: true, // could also be {}, but I would avoid scope: false here
template: '<input ng-model="innerModel" ng-change="onChange()">',
require: "ngModel",
link: function(scope, element, attrs, ctrls){
var ngModel = ctrls; // ngModelController

// from model -> view
ngModel.$render = function(){
scope.innerModel = ngModel.$viewValue;
}

// from view -> model
scope.onChange = function(){
ngModel.$setViewValue(scope.innerModel);
}
}

然后, ng-change只是自动工作,其他支持 ngModel 的指令也是如此,如 ng-required .

关于angularjs - ngChange 在 value 超出隔离范围之前触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33178205/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com