user1876246
user1876246

Reputation: 1229

Multiple Instances of AngularJS Directive with different data?

I have a directive that basically generates a label tag for inputs. It replaces the directive with my template as well as ensures the parent and next nodes have the correct attributes and classes I require.

.directive('placeHolder', function() {
    return {
    restrict: 'E',
    replace: true,
    template: '<label for="{{input}}" class="placeholder-label">{{label}}</label>',

    link: function ($scope, elem, attrs) {
      $scope.label = attrs.label;
      $scope.input = attrs.input;
      //check if the parent element is a div, then set the class to make it's position relative
      if(elem.parent().nodeName === 'DIV') {
        elem.parent().addClass('placeholder-parent');
      }

      //check if the next element is an input or textarea
      if(elem.next().nodeName === 'INPUT' || elem.next().nodeName === 'TEXTAREA') {
        //ensure the id of the input/textarea is the same as the for value in the label, else set it so
        if(elem.next().attr('id') === input) {
          return
        } else {
          elem.next().attr('id', input)
        }
      }
    }
  };

});

My problem is that I have 2 inputs on the same page, thus two instances of the same directive, and both instances result in the same label visible.

Here is a fiddle http://jsfiddle.net/HB7LU/11330/

Upvotes: 1

Views: 2329

Answers (1)

Mualki
Mualki

Reputation: 186

You need to use the scope attribute of the directive:

if the name of the attributes are the same:

    scope: {
      label: '@',
      input: '@'
    }

or you can define custom ones:

    scope: {
      myLabel: '=label',
      myInput: '=input'
    },

Your code sample modified:

app.directive('placeHolder', function() {
    return {
    restrict: 'E',
    replace: true,
    template: '<label for="{{input}}" class="placeholder-label">{{label}}</label>',
    scope: {
      label: '@',
      input: '@'
    },
    link: function ($scope, elem, attrs) {
      //check if the parent element is a div, then set the class to make it's position relative
      if(elem.parent().nodeName === 'DIV') {
        elem.parent().addClass('placeholder-parent');
      }

      //check if the next element is an input or textarea
      if(elem.next().nodeName === 'INPUT' || elem.next().nodeName === 'TEXTAREA') {
        //ensure the id of the input/textarea is the same as the for value in the label, else set it so
        if(elem.next().attr('id') === input) {
          return
        } else {
          elem.next().attr('id', input)
        }
      }
    }
  };

});

To use this modify your directive html to:

<place-holder label="labelText" input="inputId">

Refer to chapter 'Isolating the Scope of a Directive' In AngularJS directive documentation: https://docs.angularjs.org/guide/directive

Upvotes: 3

Related Questions