Angular.js: Conditionally show elements (using directives)


Directives are powerful tools which should be used for all dom manipulations. A common problem is to hide a text input field when somebody toggles a checkbox. This small example shows how you can deal with that.

NOTE: thanks to @olov I have learned about the ng-show and ng-hide directives. They do pretty much the same as I do below. My post can be considered obsolete but I will leave it online as an example to work with directives and $watch.

Let’s assume the following HTML:

<input type="text" hideon="mymodel" />
<input type="checkbox" ng-model="mymodel" /> Hide Inputfield?

As you can guess from this snipped, we want to create a directive which is called “hideon”. As parameter it should take the name of the model which is listened to. In other terms, if the Angular model “mymodel” changes to true, the input field must hide.

Here is the directive:

directives.directive('hideon', function() {
    return function(scope, element, attrs) {
        scope.$watch(attrs.hideon, function(value, oldValue) {
            if(value) {
            } else {
        }, true);

The directive is called “hideon”, as expected. In this example i use the $watch method from the scope. It does observe a model and call a listener when it changes. In my case i want it to listen to the attribute of hideon. It can be found in attrs. hideon and will return “mymodel”.

Please mind the third parameter “true” in the $watch method. By default Angular.js compares objects by reference and not by its content. This might result in an update to the content of an object but without firing the listener. Only if you replace the whole object you would fire the listener.

In my case it is not desired and I want my directive to listen when a value has changed. Therefore I set “true” as third parameter and we are done.

The listener is pretty easy. Arguments are the new value and the old value. I use only the new one. If it is true i call hide on the element and show if not. hide() and show() are methods from plain jQuery and yes, “element” is a jQuery object. Exactly the one on which this directive is running.

Please note: of course you need an enclosing controller which holds your scope. I dismissed it here, assuming already have worked out the basics of Angular.js.

Tags: #AngularJS #JavaScript #jQuery