Reputation: 11628
so I have a directive:
angular.module('mymodule').directive('myNote', function() {
var fnLink = function(scope, element, attrs){
console.log('in directive', arguments);
};
return {
restrict: 'E',
template: [
'<div class="note" data-id="{{note._id}}">',
'<span>{{note.content}}</span> ',
'</div>'
].join('\n'),
link: fnLink
};
});
and, in another directive, that manages the container where these "notes" will appear:
Note.find({
user: $scope.global.user._id,
module: $scope.module._id
}).then(function(response) {
$scope.notes = response;
angular.forEach($scope.notes, function(note){
$scope.note = note;
element.append($('<my-note>'));
});
$compile(element)($scope);
});
Right now the HTML is being rendered as it should; I have two problems:
Update the way the code is set up, every note rendered will be bound to the last note in the $scope.notes array. How can I make them individual?
am I approaching this completely wrong?
Thank you
Upvotes: 2
Views: 173
Reputation: 11628
After many hours investigating, I came to the solution to this problem;
this talk helped me a lot.
I need to use Angular Directive's Isolated Scope. Here's how it works:
//READER Directive
var initNotes = function($scope, Note, element, $compile){
Note.find({
user: $scope.global.user._id,
module: $scope.module._id
}).then(function(response) {
$scope.notes = response;
angular.forEach($scope.notes, function(note){
var highlighted = element.find('span.highlighted');
var html = '<my-note _id="'+note._id+'" content="'+note.content+'"></my-note>';
highlighted.after($compile(html)($scope));
});
});
};
//NOTES Directive
angular.module('oowli').directive('myNote', function() {
var fnLink = function($scope, element, attrs){
element.on('keydown', '.note span', noteKeyDown($scope));
element.on('click', '.edit', editClick($scope));
element.on('click', '.remove', removeClick($scope));
};
return {
restrict: 'E',
template: [
'<div class="note" data-id="{{id}}">',
'<div class="note-buttons">',
'<a href="#" class="glyphicon glyphicon-pencil edit"></a>',
'<a href="#" class="glyphicon glyphicon-remove remove"></a>',
'</div>',
'<span>{{content}}</span> ',
'</div>'
].join('\n'),
scope: {
id: '=_id',
content: '@content'
},
link: fnLink
};
});
What I pass as attributes of the directive are mapped to the scope in the myNote directive.
Upvotes: 0
Reputation: 108501
You need to $compile
the element to wire up the directives. And pass a $scope to it:
$compile(element)($scope);
I wrote a blog entry a while back on how $compile works, but basically it does this:
am I approaching this completely wrong?
Well. Honestly? Maybe? It's hard to say without seeing more code.
From what I've read, it seems like you have nested directives that "manage notes". Generally speaking this is probably the wrong approach.
Quick run down of Controllers, Services and Directives and what they're used for (VERY general):
Directives are more of the "inner workings" of Angular. You can do a lot of stuff in directives and it's very easy to muddle up your concerns in a directive. It's best to try to keep them simple and to the point. A reusable partial that's just a template and a controller, for example. Or a binding directive that is just a linking function.
You should probably be managing the "notes" between your directives on a service. You can even inject that service into your directives, but it will allow you to separate that concern from your directives to make everything more testable.
Let me annotate your own code with what concerns are represented in it:
//In a directive, so DOM and model
// Data Access
Note.find({
// Model
user: $scope.global.user._id,
module: $scope.module._id
}).then(function(response) {
// Model
$scope.notes = response;
// DOM Manipulation
angular.forEach($scope.notes, function(note){
// Model
$scope.note = note;
// Manual DOM manipulation
element.append($('<oowli-note>'));
});
// Manual call to $compile
$compile(element)($scope);
});
.. All in a directive, which as I mentioned above should limit it's concerns. So basically, if you go to test this directive, you are going to be dealing with
You might be better off with a repeater?
<oowli-note ng-repeat="note in notes"/>
Then get notes in a controller from a service call?
app.controller('NoteCtrl', function($scope, Note) {
Note.find($scope.x, $scope.y).then(function(notes) {
$scope.notes = notes;
});
});
But, I have no idea what you're actually trying to accomplish... so I'm just giving this advice in hopes that it helps.
Upvotes: 2