Reputation: 8925
I have seen the ability to have a dynamic templateUrl
within a Directive in Angular but while researching I have yet to see a dynamic template.
.directive('col', function () {
var template = '<div class="one" ng-transclude></div>';
return {
restrict: 'E',
scope: {},
transclude: true,
replace: true,
template: template,
link: function (scope, ele, attrs) {
if (attrs.two !== undefined) {
template = '<div class="two" ng-transclude></div>';
} else if (attrs.three !== undefined) {
template = '<div class="three" ng-transclude></div>';
} else {
template = '<div class="one" ng-transclude></div>';
}
console.log(template);
}
};
})
HTML:
<col three>Three</col>
<col two>Two</col>
<col>Nothing</col>
The console shows appropriately:
<div class="three" ng-transclude></div>
<div class="two" ng-transclude></div>
<div class="one" ng-transclude></div>
However the output shows the default / initial <div class="one" ng-transclude></div>
Upvotes: 1
Views: 3952
Reputation: 416
If the template is dynamically constructed based on the attributes then you can just supply a template function passing in the attributes
.directive('col', function () {
return {
restrict: 'E',
scope: {},
transclude: true,
replace: true,
template: function(element, attrs) {
var template = null;
if (attrs.two !== undefined) {
template = '<div class="two" ng-transclude></div>';
} else if (attrs.three !== undefined) {
template = '<div class="three" ng-transclude></div>';
} else {
template = '<div class="one" ng-transclude></div>';
}
return template;
},
link: function (scope, element, attrs) {
}
};
})
If the template is dynamically constructed based on the model then it's bit more involved. Note that the transclusion is done explicitly rather than using the ng-transclude directive.
.directive('col', function () {
return {
restrict: 'E',
scope: {
myVariable: '='
},
transclude: true,
replace: true,
link: function (scope, element, attrs, nullController, transclude) {
var template = null;
if (scope.myVariable == 'two') {
template = '<div class="two"></div>';
} else if (scope.myVariable == 'three') {
template = '<div class="three"></div>';
} else {
template = '<div class="one"></div>';
}
element.html(template);
$compile(element.contents())(scope);
transclude(scope.$parent, function(clone, scope) {
element.children().append(clone);
});
}
};
})
Upvotes: 0
Reputation: 29234
When you say 'template = 'xxx' in your link function it is referencing your template variable, not the property on the returned object. Try this:
.directive('col', function () {
var result = {
restrict: 'E',
scope: {},
transclude: true,
replace: true,
template: template,
link: function (scope, ele, attrs) {
if (attrs.two !== undefined) {
result.template = '<div class="two" ng-transclude></div>';
} else if (attrs.three !== undefined) {
result.template = '<div class="three" ng-transclude></div>';
} else {
result.template = '<div class="one" ng-transclude></div>';
}
console.log(result.template);
}
};
return result;
})
Upvotes: 0
Reputation: 20209
This is because the template is collected before the link
function is fired, if your only trying to change the classes then just do something like this.
.directive('col', function () {
var template = '<div class="{{class}}" ng-transclude></div>';
return {
restrict: 'E',
scope: {},
transclude: true,
replace: true,
template: template,
link: function (scope, ele, attrs) {
$scope.class = attrs.three ? 'three' : attrs.two ?'two' : attrs.one ? 'one' : '';
}
};
});
Other than that I don't know how else you would accomplish it.
Upvotes: 2