user1943020
user1943020

Reputation:

How can I add a class to an input if the input is changed with AngularJS?

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

Answers (3)

EpokK
EpokK

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

Michelle Tilley
Michelle Tilley

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 modified
  • ng-dirty - the input has been modified

So, 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

yanhan
yanhan

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:

  • template - the html that replaces the watch-row-title tag. we dont need this here
  • scope - Here we make use of an isolated scope. Basically, the '=' establishes a 2-way data binding between between scope.title inside the watch-row-title directive and the $scope.row.title value inside the MyCtrl controller.
  • restrict - We give it a value of 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>
  • link - this is the link function, where the interesting stuff happens. In here, we use 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

Related Questions