Reputation:
I coded the following in my form:
<td><input type="text" ng-model="row.title" /></td>
When I look at my DOM with Chrome developer tools I see the following:
<input type="text" ng-model="row.title" class="ng-pristine ng-valid">
How can I make it so that when there is a change made to the input that the input has a class added to it?
Upvotes: 4
Views: 15973
Reputation: 38092
HTML
<input type="text" id="inputTitle" ng-model="row.title" />
JS
$scope.$watch('row.title', function(newValue) {
// Add CSS class on input
$('#inputTitle').addClass('YourCSSClass');
}, true);
Upvotes: 0
Reputation: 159145
There are two good ways to approach this problem:
1. Use the built-in ng-dirty
class that Angular puts on the element.
When you change an input managed by Angular, it adds some CSS classes to the input for various states. These include:
ng-pristine
- the input has not been modifiedng-dirty
- the input has been modifiedSo, if you can modify your CSS to be based off the .ng-dirty
class, you're good to go.
2. Use a form
directive with the $dirty
flag.
When you use a form
element, Angular assigns a FormController
instance on the scope with the same name as the name
attribute on the form; each input inside the form gets attached to that FormController instance as a property, again with the same name as the name
attribute on the input. For example,
<form name="myForm">
<input type="text" name="myInput">
</form>
gives you
$scope.myForm.myInput
Each input property has some of its own properties on it, including $pristine
and $dirty
; these work just like the CSS classes listed above. Thus, you can check for the $dirty
flag on the input and use ng-class
to conditionally apply a class to the element. An example:
<div ng-controller="MainController">
<form name="myForm">
<input name="myInput" ng-model="model" ng-maxlength="3"
ng-class="{changed: myForm.myInput.$dirty}">
</form>
</div>
You can find a working example here: http://jsfiddle.net/BinaryMuse/BDB5b/
Upvotes: 12
Reputation: 3537
Take a look at this jsfiddle: http://jsfiddle.net/hNrEV/2/
The main idea is using $scope.$watch
to watch for changes to the input box. I gave it an id of rowTitle
, and used a directive called watchRowTitle
that watches for changes to $scope.row.title
, and adds a class 'red' that colors the text red whenever the text in the input box is equal to 'wrong title'.
It is probably good practice to do DOM manipulation in directives. Here, the watchRowTitle
directive returns an object with 4 keys:
watch-row-title
tag. we dont need this herescope.title
inside the watch-row-title
directive and the $scope.row.title
value inside the MyCtrl
controller.E
, which stands for element. So this restricts the use of the watch-row-title
directive within html tags, in other words: <watch-row-title></watch-row-title>
scope.$watch
on title
. We have to supply a function with 2 parameters newValue
and oldValue
(you can name them to something else, but naming them this way is more meaningful), that holds the new and old values of the variable being watched. Whenever the scope.title
variable becomes the string 'wrong title', it adds the CSS class 'red' to the input box with id rowTitle
(notice how the text in the input box turns red). Otherwise, it removes that CSS class. This portion is done using JQuery.HTML:
<div ng-app="myApp" ng-controller="MyCtrl">
<input id="rowTitle" type="text" ng-model="row.title" class="ng-pristine ng-valid" />
<watch-row-title title="row.title"></watch-row-title>
</div>
CSS:
.red {
color: red;
}
JavaScript:
angular.module('myApp', [])
.controller('MyCtrl', [
'$scope',
function ($scope) {
$scope.row = {};
}
])
.directive('watchRowTitle', [
function () {
return {
template: '',
scope: {
title: '='
},
restrict: 'E',
link: function(scope, element, attr) {
scope.$watch('title', function(newValue, oldValue) {
if (newValue === 'wrong title') {
$('#rowTitle').addClass('red');
} else {
$('#rowTitle').removeClass('red');
}
});
}
};
}
]);
Upvotes: 1