The reason for the behavior, as rightly pointed out in another answer, is that the two-way binding did not have the ability to change the external searchFilter to the time of searchChange() and therefore loadResults() was called.
The solution, however, is very hacks for two reasons.
First, the caller (directive user) should not be aware of these workarounds with $timeout . If nothing else, $timeout should have been done in the directive, not in the View controller.
And two - the mistake also made by OP - is that the use of ng-model accompanied by other "expectations" of users of such directives. The presence of ng-model means that other directives can be used next to it, such as validators, parsers, formatting elements and view-change-listeners (for example, ng-change ). To support it correctly, you need require: "ngModel" instead of binding to its expression through scope: {} . Otherwise, everything will not work as expected.
Here's how to do it - in another example, see the official documentation for creating a custom input control.
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); } }
Then ng-change just works, as well as other directives that support ngModel , like ng-required .
New dev
source share