//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.log
ています。メインコントローラーの var がディレクティブから新しい値を受け取る直前に実行さloadResults
れているため、実際には 1 文字遅れてログに記録されます。ただし、ディレクティブ内にログインすると、すべてが期待どおりに機能します。なぜこうなった?loadResults
searchFilter
私の解決策
私の単純な例で ngChange で何が起こっているかを理解した後、私が実際に渡している ngModel がオブジェクトであり、そのプロパティが変更されているという事実によって、実際の問題がもう少し複雑であることに気付きました。このディレクティブを入力の 1 つとしてフォーム検証を使用しています。ディレクティブ内で $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>