I'm absolutely stumped. I started thinking I knew what I was doing, and have now tried so many variations, I have no idea what the issue might be.
I'm creating a directive called "mylist" that I'd like to hand off some data to (in this case, a number):
<span ng-repeat="node in [1,2,3,4,5]">
<mylist counter="{{node}}"></mylist>
</span>
So far, so good ... creating my directive works fine.
var myApp = angular.module('myApp', []);
myApp.directive('mylist', function() {
return {
restrict: "E",
template: "<P>You counted to: '{{inTemplate}}'.</P>",
replace: true,
controller: MyCtrl,
scope: { inTemplate: "@counter" }
}
});
Now, when I add in my controller, I don't have any idea where to find the counter
(or inTemplate
) variable.
function MyCtrl($scope, $http, $attrs, $element) {
$scope.inTemplate = "blah blah" + $attrs.counter;
}
As always, appreciate any insight. It might just be that Angular is too much for me :)
Thanks much,
Nate
The counter is part of the directive's scope, you can see this in detail with batarang.
You should be able to reach it through $scope.inTemplate. I've meddled with your fiddle and got it working three ways:
With an attribute http://jsfiddle.net/PCfZV/46/ :
<mylist node="{{node}}"></mylist>
template: "<P>You counted to: '{{countTo()}}'.</P>",
replace: true,
controller: MyCtrl,
scope: {node: '@'}
function MyCtrl($scope, $http, $attrs, $element) {
$scope.countTo = function(){return "blah blah" + $scope.node};
}
With a link to the parent scope http://jsfiddle.net/PCfZV/47/ :
<mylist is-counter="node"></mylist>
template: "<P>You counted to: '{{inTemplate}}'.</P>",
replace: true,
controller: MyCtrl,
scope: {
"isCounter": "="
}
With an expression http://jsfiddle.net/PCfZV/48/ :
<mylist is-counter="'bla bla' + node"></mylist>
template: "<P>You counted to: '{{isCounter()}}'.</P>",
scope: {
"isCounter": "&"
}
Look also at the console.log to get some insight in the value of the attribute when the controller is instantiated.
In your post, the directive creates an "isolate scope" -- because of the line scope: { ... }
. (Isolate scopes do not prototypically inherit from their parent scopes. If you want to learn more about what that means, including a picture of what an isolate scope looks like in relation to its parent scope, see What are the nuances of scope prototypal / prototypical inheritance in AngularJS?, section directives).
In your working fiddle (that you mention in the comment to @iwein), the directive does not create a new scope, but it defines a controller, so the controller and the directive are using the same scope -- so they can both see any properties that either defines on the scope. In your fiddle, is-counter="{{node}}"
is not doing anything, so it can be removed and it will still work.
Also of note, for each array item/node, you are creating a separate MyCtrl controller (I'm not sure if that is intentional or not.), since the directive has the line controller: MyCtrl
. Angular takes MyCtrl
as the constructor function and creates a controller each time it encounters the mylist
directive in the HTML (which is 5 times, due to the ng-repeat).
Normally, you'll want to specify where the controller has dominion in the HTML:
<div ng-controller="MyCtrl">
<span ng-repeat="node in [1,2,7,6,5]">
...
</span>
</div>
(There are times you might want a controller instantiated for each directive, but that is less common.)
If you use ng-controller, you don't need to specify a controller in your directive -- the directive will (by default) use the parent scope -- i.e., the same scope as the controller.
I'm not exactly sure what you are trying to do in the controller, but I would just define a property on the controller scope to hold your extra text,
$scope.extraText= "blah blah";
and then use it in the template:
template: "<P>You counted to: {{extraText}} '{{node}}'.</P>",
It might just be that Angular is too much for me :)
For me, the learning curve for AngularJS was rather steep (and I'm still learning). Don't give up on it. I think it is a fantastic framework.