Anish V
Anish V

Reputation: 683

How to watch a property of an html tag in directive?

I need to watch a property of one of my inner html elements (li tag) inside a directive. I have tried it, but not able to get that. My html is as given below:

<div id="notificationsTile">
    <div class="blue">
       <div class="step">
            <ul ng-repeat="item in Model.DisplayNotifications">
                <li itemPriority = {{item.Priority}}>
                    <h3>{{ item.EndDate | date: 'dd MMMM' }}</h3>
                    <p>{{ item.NotificationName }}</p>
                </li>
            </ul>
        </div>
    </div>
</div>

I need to watch the itemPriority. The watch is as given below:

scope.$watch("itemPriority", function(newVal, oldVal){
                debugger;
            });

My directive is as given below:

notificationsTileModule.directive('spNotificationsTile', function (spNotificationsService, spSessionStorageService) {
    return {
        restrict: 'E',
        replace: true,
    scope: {
            priority: '=itemPriority'   
        },
        templateUrl: '/_catalogs/masterpage/SPDP.Portal/Views/NotificationTile/NotificationTile.html',
        link: function (scope, element, attrs) {

            var model = scope.Model = {
                DisplayNotifications: []        

            };

            //model.Priority = scope.itemPriority;

            scope.$watch('priority', function(newVal, oldVal){
                debugger;
            });
}
});

Where am I going wrong?

Upvotes: 0

Views: 555

Answers (3)

j.wittwer
j.wittwer

Reputation: 9497

Your directive can access the same array of items that ng-repeat uses to make the list.

<div sp-notifications-tile items="Model.DisplayNotifications" class="alert">
  <ul>
    <li ng-repeat="item in Model.DisplayNotifications">
...

Then, you can watch those items, and modify classes accordingly via the element parameter of the link function. You indicated that you will base the class on just one of the item's priority. In this example, I am simply taking the first item.

app.directive('spNotificationsTile', function() {
  return {
    restrict: 'A',
    scope: {
      items: '='
    },
    link: function(scope, element, attr) {
      scope.$watch('items', function() {
        var firstItem = element.find('li')[0];
        var firstPriority = angular.element(firstItem).scope().item.priority;

        if (firstPriority > 3)
          element.addClass('alert-warning');
        else
          element.removeClass('alert-warning');
      }, true);
    }
  }
})

Here is a demo: http://plnkr.co/zrPEFSNXGDENB6MEQo8i. You can try changing the first priority value to see changes to the class applied to the notification tile.

Upvotes: 1

j.wittwer
j.wittwer

Reputation: 9497

You don't need to use interpolation to set the value of the item-priority attribute:

<ul ng-repeat="item in Model.DisplayNotifications">
    <li item-priority="item.priority">{{item.priority}}
    </li>
</ul>

Notice that I wrote the directive's name using lower case, dash-delimited format. Angular will convert this to itemPriority in the directive link function. From there, you can watch the attribute value like this:

app.directive('itemPriority', function() {
  return {
    restrict: 'A', 
    scope: {
      priority: '=itemPriority'
    },
    link: function(scope, element, attr) {
      scope.$watch('priority', function() {
        console.log(scope.priority);
      });
    }
  }
});

Here is a working demo: http://plnkr.co/edit/ty1bJoxqd8ZBIV7CqUEI?p=preview

Update
You are not adding your directive anywhere in the html (there are no sp-notifications-tile elements). But you would have trouble even if you did include the element, because it is replacing its content, and you would lose the list items generated by ng-repeat.

If all you need is to add a class to list items by priority, use ng-class as follows:

<ul ng-repeat="item in Model.DisplayNotifications">
  <li>
    <div ng-class="{'alert-danger': item.priority < 2, 
        'alert-warning': item.priority >= 2 && item.priority < 4, 
        'alert-info': item.priority >= 4}">
      {{item.priority}}
    </div>
  </li>
</ul>

Here is an updated demo using ng-class: http://plnkr.co/oR6eBPOsdHqqGiF0U7Zs

Upvotes: 1

Prashobh
Prashobh

Reputation: 9542

Try this

$scope.itemPriority = item.Priority ;


scope.$watch('itemPriority ', function( status )
  {
   console.log(status);
 });

Upvotes: 0

Related Questions