Ответ 1
Наше лучшее предположение заключается в том, что установка старого == new предотвращает появление грязной проверки
Слушатель наблюдателя вызывается только тогда, когда значение выражения, которое он прослушивает, изменяется. Но так как вы изменили модель на прежнее значение, она не будет вызвана снова, потому что она как значение не изменилась вообще. Но будьте осторожны: изменение значения свойства внутри мониторинга наблюдателя, что одно и то же свойство может привести к бесконечному циклу.
Однако он не будет обновлять DOM (и то, что вы видите в браузере), пока я явно не вызову ngModel. $render() после установки нового значения.
Это правильно. $setViewValue
устанавливает значение модели, как если бы оно было обновлено в представлении, но вам нужно вызвать $render
, чтобы эффективно отображать представление на основе (новой) модели. Ознакомьтесь с этой дискуссией для получения дополнительной информации.
Наконец, я думаю, вы должны подойти к своей проблеме по-другому. Вы можете использовать свойство $parsers
для NgModelController
для проверки ввода пользователя вместо использования наблюдателя:
link: function (scope, element, attrs, ngModel) {
if (!ngModel) return;
ngModel.$parsers.unshift(function(viewValue) {
if(viewValue === 'foo') {
var currentValue = ngModel.$modelValue;
ngModel.$setViewValue(currentValue);
ngModel.$render();
return currentValue;
}
else
return viewValue;
});
}
Я использовал jsFiddle script, чтобы использовать приведенный выше код.
angular.module('myDirective', [])
.directive('myDirective', function () {
return {
restrict: 'A',
terminal: true,
require: "?ngModel",
link: function (scope, element, attrs, ngModel) {
if (!ngModel) return;
ngModel.$parsers.unshift(function(viewValue) {
if(viewValue === 'foo') {
var currentValue = ngModel.$modelValue;
ngModel.$setViewValue(currentValue);
ngModel.$render();
return currentValue;
}
else
return viewValue;
});
}
};
});
function x($scope) {
$scope.test = 'value here';
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<h1>Foo Fighter</h1>
I hate "foo", just try and type it in the box.
<div ng-app="myDirective" ng-controller="x">
<input type="text" ng-model="test" my-directive>
<br />
model: {{test}}
</div>