admin管理员组文章数量:1289876
I want to create a directive that organizes a displays data grouped by date. I also want to be able to specify a directive that will display the individual rows. In a perfect world it would look something like this (but nice and pretty)
Friday, Oct 28
[some directive html]
[some directive html]
[some directive html]
Saturday, Oct 29
[some directive html]
Sunday, Oct 30
[some directive html]
[some directive html]
...
This obviously doesn't work, so if you have a better approach please tell me, but I was hoping to be able to do something along these lines:
app.directive('dateOrganized', [function(){
return {
template:
'<div>' +
'<div ng-repeat="organizedDate in organizedDate">' +
'<div>{{organizedDate.date | date}}</div>' +
'<div ng-repeat="item in organizedDate.items">' +
'{{rowDirectiveHtml}}' +
'</div>' +
'</div>' +
'</div>',
scope: {
organizedDates: '=',
rowDirectiveHtml: '='
}
...
};
}])
app.directive('itemRow', [function(){
return {
template: '<div>{{item.data}}</div>',
scope: {
item: '='
}
};
}]);
then use it like this:
<div data-organized organized-dates="stuff" row-directive-html="<div item-row item=\"item\" />" />
I know this is super ugly (and doesn't work, but I'm sure I could get it working with a few tweaks) so what I am really asking, is there a better way to do this?
I want to create a directive that organizes a displays data grouped by date. I also want to be able to specify a directive that will display the individual rows. In a perfect world it would look something like this (but nice and pretty)
Friday, Oct 28
[some directive html]
[some directive html]
[some directive html]
Saturday, Oct 29
[some directive html]
Sunday, Oct 30
[some directive html]
[some directive html]
...
This obviously doesn't work, so if you have a better approach please tell me, but I was hoping to be able to do something along these lines:
app.directive('dateOrganized', [function(){
return {
template:
'<div>' +
'<div ng-repeat="organizedDate in organizedDate">' +
'<div>{{organizedDate.date | date}}</div>' +
'<div ng-repeat="item in organizedDate.items">' +
'{{rowDirectiveHtml}}' +
'</div>' +
'</div>' +
'</div>',
scope: {
organizedDates: '=',
rowDirectiveHtml: '='
}
...
};
}])
app.directive('itemRow', [function(){
return {
template: '<div>{{item.data}}</div>',
scope: {
item: '='
}
};
}]);
then use it like this:
<div data-organized organized-dates="stuff" row-directive-html="<div item-row item=\"item\" />" />
I know this is super ugly (and doesn't work, but I'm sure I could get it working with a few tweaks) so what I am really asking, is there a better way to do this?
Share Improve this question asked Aug 31, 2015 at 3:13 jensengarjensengar 6,16719 gold badges60 silver badges94 bronze badges 5-
1
Why do you want to pass the html in the
row-directive-html
? Will it change? – Subash Commented Aug 31, 2015 at 3:21 -
1
You should look into
$transclude
function - injected into a controller or a 5th paramter to thelink
function. You should also consider passing a template (which is what it is) as a child element rather than an attribute. But overall, a good answer to this question will need to touch on a number of concepts, so, it's better to be familiar with these fundamental concepts first. – New Dev Commented Aug 31, 2015 at 3:44 - Yes the rows will change so I need it to be flexible. @new dev thanks for the tip. I'll look into it. – jensengar Commented Aug 31, 2015 at 4:14
- @new dev, I've used simple transcluding before, but is it possible to pass my item into the transcluded directive? And wouldn't that end up being a sibling scope rather than a child scope? – jensengar Commented Aug 31, 2015 at 4:16
-
1
@CodesLikeA_Mokey, you need to use a manual transclude, rather than
<ng-transclude>
, which allows you to specify whatever scope you want to link the transcluded content against. Also, since the template is actually a template forng-repeat
, you might need to manually$pile
the directive inner template rather than usingtemplate
property... Like I said, it's a bit of a plex question – New Dev Commented Aug 31, 2015 at 4:43
1 Answer
Reset to default 12This question is more plicated than might appear, so let's break it down.
What you are building is a directive that accepts a partial template - <div item-row item="item" />
- and that template uses (or linked against a scope with) an inner variable - item
- that is not defined in the outer scope by the user; its meaning is defined by your directive and your user "discovers" it by reading the documentation of your directive. I typically name such "magic" variables with a prefixed $
, e.g. $item
.
Step 1
Instead of passing a template as an HTML-as-string via attribute binding, pass it as contents and transclude that content. Transcluding allows you to bind the transcluded content against an arbitrary scope:
<foo>
<div>my item is: {{$item}}</div>
</foo>
.directive("foo", function(){
return {
scope: {},
transclude: true,
template: "<h1>I am foo</h1><placeholder></placeholder>",
link: function(scope, element, attrs, ctrls, transclude){
scope.$item = "magic variable";
transclude(scope, function(clonedContent){
element.find("placeholder").replaceWith(clonedContent);
});
}
};
});
The above will place the template <div>my item is: {{$item}}</div>
(could be any template you specify) where the directive foo
decides, and will link against a scope that has $item
defined.
Step 2
But the added plexity of your directive is that it uses ng-repeat
, which by itself accepts a template, and the template your directive receives needs to be used as a template of ng-repeat
.
With just the approach above, this would not work, since by the time link
runs, ng-repeat
will have already transcluded its own content before you had a chance to apply yours.
One way to address that is to manually $pile
the template of foo
instead of using the template
property. Prior to piling, we will have a chance to place the intended template where needed:
.directive("foo", function($pile){
return {
scope: {},
transclude: true,
link: function(scope, element, attrs, ctrls, transclude){
scope.items = [1, 2, 3, 4];
var template = '<h1>I am foo</h1>\
<div ng-repeat="$item in items">\
<placeholder></placeholder>\
</div>';
var templateEl = angular.element(template);
transclude(scope, function(clonedContent){
templateEl.find("placeholder").replaceWith(clonedContent);
$pile(templateEl)(scope, function(clonedTemplate){
element.append(clonedTemplate);
});
});
}
};
});
Demo
本文标签: javascriptPass data to transcluded elementStack Overflow
版权声明:本文标题:javascript - Pass data to transcluded element - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741487842a2381486.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论