1

I have got the following directive:

app.directive('ngAvatar', function() {
  return {
    restrict: 'E',
    replace: true,
    template: '<img class="avatar-medium" ng-src="{{url}}" />',
    link: function(scope, elem, attrs) {
      console.log(attrs);
      var aType = attrs.avatarType;
      var aId = attrs.avatarId;
      console.log("Type: "+ aType);
      console.log("Character ID:"+ aId);
      var baseUrl = "http://api-character.com/";
      switch(aType){
        case "character":
          scope.url = baseUrl + "Character/"+aId+"_256.jpg";
      }
    }
  }
});

Unfortunately the directive is not picking up the avatar_id inside of the directive. As you can see I am console logging the attributes:

console.log("Type: "+ aType);
console.log("Character ID:"+ aId);

In my view I am using this directive like so:

<ng-avatar avatar_type="character" avatar_id="{{character.character_id}}"></ng-avatar>

The following is the output of my console in Chrome. As you can see the avatar_id is showing as blank but on inspection of the attrs you can see that the attribute is there but just not showing in the directive code.

Chrome Console:

enter image description here

Does anyone have any idea why it would not work?

Thanks

10
  • avatar_type is working fine as you can see from the console output. avatar_id is not being picked up though. Commented Jan 22, 2015 at 1:55
  • Your console shows both the values. What is the issue? avatar_id is see populated with number Commented Jan 22, 2015 at 1:56
  • You need to use - not _. You can see it in the console probably because it is normalized to avatar_type not avatarType. Commented Jan 22, 2015 at 1:58
  • Ok. I will change it but as you can see from this line console.log("Type: "+ aType); it outputs the correct data. However the line console.log("Character ID:"+ aId); is not outputting the data. The issue is with console.log("Character ID:"+ aId); not console.log("Type: "+ aType); Commented Jan 22, 2015 at 1:58
  • 1
    Just setup a one time watch. Commented Jan 22, 2015 at 2:11

1 Answer 1

1

There could be many ways to solve this problem.

using one time watch - you could also consider using two-way bound isolated scoped directive

   link: function(scope, elem, attrs) { 
      //Set up watch
      var unWatch = scope.$watch(attrs.avatarId, function(v){
        if(v){
          unWatch();
          init();
        }
      });
     function init(){
       //initialize here
     }
   }

and bind it as:

   <ng-avatar avatar-type="character" avatar-id="character.character_id"></ng-avatar>

Use attribute observe

  link: function(scope, elem, attrs) { 
      //Set up watch
      var unWatch = attrs.$observe(attrs.avatarId, function(v){
        if(v){
          unWatch();
          init();
        }
      });
     function init(){
       //initialize here
     }
  }

and use it with

 <ng-avatar avatar-type="character" avatar-id="{{character.character_id}}"></ng-avatar>

Bind promise/data

  app.directive('ngAvatar', function($q) {
   //...
   link: function(scope, elem, attrs) { 
      //Set up watch
     $q.when(scope.$eval(attrs.character)).then(init); 

     function init(character){
       var id = character.id;
       //initialize here
     }
    }
  } 

and bind it as

 <ng-avatar avatar-type="character" avatar-id="characterPromiseOrCharObject"></ng-avatar>

Event bus

Just use angular event bus and broadcast an event from the controller which sets the data say char_loaded, listen for the event in the directive using scope.$on and once you get it initialize.

Sign up to request clarification or add additional context in comments.

1 Comment

Awesome answer, provided a solution to my problem and gave more insight into $watch! Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.