0

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?

Anish V
  • 673
  • 3
  • 17
  • 38

3 Answers3

1

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

j.wittwer
  • 9,497
  • 3
  • 30
  • 32
  • I'm getting attrs as undefined! – Anish V Apr 08 '14 at 06:47
  • it must match the link function signature, which is usually: `(scope, element, attrs)` but usage varies widely. – j.wittwer Apr 08 '14 at 06:49
  • I'm also using the same. The watch hits only once when we load the page and its value is undefined. After that initial hit, watch is not getting executed! – Anish V Apr 08 '14 at 06:51
  • Why not just 'priority' for watchExpression ? – gkalpak Apr 08 '14 at 07:12
  • Ha! That works too, thanks @ExpertSystem. I am up way too late. – j.wittwer Apr 08 '14 at 07:13
  • Hm... the no1 guy in AngularJS answerers in the last 30 days can't watch a scope property properly. How alarming :P – gkalpak Apr 08 '14 at 07:26
  • I have updated the question with my directive. Please have a look. Still I'm not getting that. (I'm new to angular. Thanks a lot for your help.) – Anish V Apr 08 '14 at 08:05
  • What I'm trying to achieve is to change the background color based on priority. FYI.. – Anish V Apr 08 '14 at 08:09
  • See ngclass. Custom directive not needed – j.wittwer Apr 08 '14 at 12:22
  • Is it possible to add the class to the outer most div ? For eg, in this case:
    or
    ? I may need to apply that class to that whole div.
    – Anish V Apr 09 '14 at 06:37
  • but there can by multiple notifications in the list. do you want to apply multiple classes to the parent? one for each list item? i don't think that makes sense. – j.wittwer Apr 09 '14 at 06:41
  • I will show only one notification at a time. Based on the priority of that notification, I need to change the background color of the entire tile. How can I do that? I need to get that priority to set the parent div's class, rt ? – Anish V Apr 09 '14 at 08:34
  • Is it possible to call a function with priority as argument, so that I can change the background color in directive ? – Anish V Apr 09 '14 at 08:39
1

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.

j.wittwer
  • 9,497
  • 3
  • 30
  • 32
  • Is it possible to set the class using ng-class for that outer div? For that, we need to get the priority outside this directive. Is it possible to get that to the outer div ? OR do we need to watch ? Is it possible to watch a model object in directive from its parent ? – Anish V Apr 11 '14 at 06:29
0

Try this

$scope.itemPriority = item.Priority ;


scope.$watch('itemPriority ', function( status )
  {
   console.log(status);
 });
Prashobh
  • 9,216
  • 15
  • 61
  • 91
  • Where should I set this $scope.itemPriority = item.Priority ; ? I'm setting it as property in the ng-repeat now. – Anish V Apr 08 '14 at 06:03
  • try in your controller – Prashobh Apr 08 '14 at 06:03
  • I'm not using a controller for this. This is done in a directive. I cannot get a single value of an item here, rt ? Using the ng-repeat, we are getting each items, where I need to set it to a property and watch it.. How is it possible ? – Anish V Apr 08 '14 at 06:07