Reputation: 1288
I created a directive that check if an input is valid based on some criteria. In this form I have a button that is ng-disabled="form.$invalid"
. The problem is that, even if it seems like the valid state is populated, my button is not enabled when my custom directive change the validity state of the input.
Here is a simple example:
<div ng-app="app">
<div ng-controller="fooController">
<form name="fooForm">
<input type="text" ng-model="foo" foo>
<input type="submit" value="send" ng-disabled="fooForm.$invalid">
</form>
</div>
</div>
JS (CoffeeScript):
app = angular.module 'app', []
app.directive 'foo', ->
restrict: 'A'
require: 'ngModel'
link: (scope, element, attrs, controller) ->
element.bind 'keyup', ->
if controller.$viewValue isnt 'foo'
controller.$setValidity 'foo', false
else
controller.$setValidity 'foo', true
app.controller 'fooController', ($scope) ->
$scope.foo = 'bar'
In short, this directive check if the input's value === 'foo'. If it's not it sets the validity 'foo' to false, otherwise to true.
Here is a jsfiddle (javascript) : http://jsfiddle.net/owwLwqbk/
I found a solution involving $apply: http://jsfiddle.net/owwLwqbk/1/
But I wonder if there's not an other, a better way of doing it? Isn't the state supposed to populate?
Upvotes: 0
Views: 898
Reputation: 16498
Please see demo below
var app;
app = angular.module('app', []);
app.directive('foo', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
ctrl.$parsers.unshift(function(val) {
console.log(val);
if (val == "bar") {
ctrl.$setValidity('foo', true);
} else {
ctrl.$setValidity('foo', false);
}
});
}
};
});
app.controller('fooController', function($scope) {
$scope.foo = 'bar';
});
.ng-invalid-foo {
outline: none;
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="fooController">
[Only "bar" is valid value] <br/>
<form name="fooForm">
<input type="text" ng-model="foo" foo="">
<input type="submit" value="send" ng-disabled="fooForm.$invalid" />
</form>
</div>
</div>
Upvotes: 1
Reputation: 37520
The jqLite event handler runs outside the context of Angular, that's why you needed the scope.$apply()
before it would work.
Another option is to use a watch...
link: function(scope, element, attrs, controller) {
scope.$watch(function () {
return controller.$viewValue;
}, function (newValue) {
controller.$setValidity('foo', newValue === 'foo');
});
}
Upvotes: 1