3

Angular newbie here. Trying to wrap my head around directives, scopes, transclusions, and what not.

Here's what I'm trying to achieve -- each table in a cell needs to be color-coded (change in bgcolor OR addition of a specific CSS class) based on the value inside that cell. The complication is that the cell does not have a bare value - it has other bits & baubles along with it. Therefore, within the cell, I would like to have the ability to add custom HTML.

Here's what my template looks like:

<span color-codify="{'max' : object.max, 'value' : object.value}" ng-transclude>
  {{ object.value }}
  <a href="#">Edit</a> | <a href="#">Delete</a>
</span>

Here's what my directive looks like:

myModule.directive('colorCodify', function() {
  return {
    restrict: 'A',
    transclude: 'true',
    'link' : function(scope, element, attrs, controller) {
      var opts = scope.$eval(attrs.colorCodify);
      console.log(opts); // THIS DISPLAYs {max: undefined, value: undefined} 
    }
  }
});

The surprising part is, that even though {{ object.value }} within the <span> element renders correctly, it is not being passed down to the directive properly. However, if I refer to $parent it works properly. Example:

<span color-codify="{'max' : $parent.object.max, 'value' : $parent.object.value}" ng-transclude></span>

What's going on?

Saurabh Nanda
  • 6,373
  • 5
  • 31
  • 60

1 Answers1

4
<span color-codify="{'max' : object.max, 'value' : object.value}" ng-transclude>
  {{ object.value }}
  <a href="#">Edit</a> | <a href="#">Delete</a>
</span>

.

myModule.directive('colorCodify', function() {
  return {
    restrict: 'A',
    transclude: 'true',
    scope: {getOpts: "&colorCodify"},
    'link' : function(scope, element, attrs, controller) {
      var opts = scope.getOpts();
      console.log(opts);
    }
  }
});

For more info, check out directive definition object part in http://docs.angularjs.org/guide/directive

Edit about $parent:

I suppose you need to read more about how scopes work in angular (how do they inherit from one another and how do they override those inherited properties). This would be one of the most important aspects in angularjs. I suggest you to follow the links and read them again and again until you get it.

ngScope Documentation Reference
Developer Guide
Bonus (video from angularjs team, discussing angularjs' best practises):
Youtube

Umur Kontacı
  • 35,403
  • 8
  • 73
  • 96
  • It this what you're referring to? "& or &attr - provides a way to execute an expression in the context of the parent scope." – Saurabh Nanda Jan 22 '13 at 09:09
  • Also, could you explain to me why, in my example, why `color-codify="{'max' : $parent.object.max, 'value' : $parent.object.value}"` works while `color-codify="{'max' : object.max, 'value' : object.value}"` doesn't? – Saurabh Nanda Jan 22 '13 at 09:10
  • Yes. It does return a function wrapper to be called in the parent context. – Umur Kontacı Jan 22 '13 at 09:11
  • 1
    It means you are creating a new child scope, where you cannot access object without jumping to parent. a full jsfiddle might help.ç – Umur Kontacı Jan 22 '13 at 09:19
  • I don't fully understand what's going on here, especially wrt the change in behaviour with using `$parent`, but your answer seems to have solved my problem. Marking it as accepted. – Saurabh Nanda Jan 26 '13 at 06:02
  • I have provided more links as reference points to understand how angularjs' scopes work. You might want to read them. – Umur Kontacı Jan 26 '13 at 08:16
  • Confused by http://docs.angularjs.org/api/ng.$rootScope.Scope (Inheritance section). If `$parent.object.max` works as expected, `object.max` should also work as expected. UNLESS the scope created for the directive is NOT inherited from the outer scope, but simply has a reference to the outer scope via `$parent`. But, in that case `scope.getOpts()` from within the `link` function should not work as well. Aargh! – Saurabh Nanda Jan 26 '13 at 11:40
  • I cannot say anymore from limited source code. All I can say is, if you can't reach a scopes property normally but with parent. An isolated scope has been created somewhere. In my example, I intentionally created an isolate scope and passed a single readonly reference. – Umur Kontacı Jan 26 '13 at 11:50
  • 1
    Thank you fastreload for taking the time to post this answer and the comments. I'm going through the Angular developer guide and the best practices video right now. Hope it gives me a clearer picture. – Saurabh Nanda Jan 26 '13 at 11:52
  • @Saurabh, for more on scopes see http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs – Mark Rajcok Feb 01 '13 at 16:27