Reputation: 8031
I'm working on a project to render HTML taking a special XML as input. I succeed already with the basic case. For example:
<mybutton name="layla"></mybutton>
is converted to
<div class="btn">Layla</div>
using a directive like
.directive('mybutton', function() {
return {
restrict: 'E',
scope: {
name: '@'
},
templateUrl: 'uicomponents/uiButton.html'
}
})
The real XML input I'll receive is:
<ui type="back_button" x="10.0" y="630.0"/>
I'd like to avoid changing the XML syntax but it can be done if necessary.
all screen components are in <ui></ui>
tags. The type
attribute defines the component.
How would you write directives for this kind of tags? It doesn't seem smart to create one huge directive for <ui>
elements and having a long switch-case inside for the attribute.
Upvotes: 2
Views: 3065
Reputation: 18081
You could create a ui directive that transforms the element based on the type attribute and then recompiles the element - something like this:
app.directive('ui',function($compile){
return {
restrict:'E',
compile:function(tElement,tAttrs){
if(tAttrs.type){
tElement.attr(tAttrs.type,'');
tElement.removeAttr('type');
return function(scope,el){
$compile(el)(scope);
}
}
}
}
});
app.directive('backButton',function(){
return {
replace:true,
template:'<button ng-click="btnClick()">A back-button template</button>'
}
});
Edit: In my original example I made the mistake of compiling the template element - this will not work if the directive is being used in a ngRepeat. The fix is simple, compile the link element instead. I've updated the code and the example.
Check out this plnkr example.
Upvotes: 5
Reputation: 6018
I am not aware of a way of creating a directive bound on the value of an attribute, but maybe you could have a look at this previous SO answer: Custom Input Types
The idea is to create a different template according to the value of an attribute using the compile function of the directive. You could put in cache all your custom input templates at the beginning (not necessary).
angular.module('myapp', ['myapp.directives'])
.run(['$http', '$templateCache', function($http, $templateCache) {
$templateCache.put('span.html', '<span>text</span>');
$http.get('back_button.html', {cache:$templateCache});
}]);
And retrieve from the cache the input template according to the type attribute:
angular.module('myapp.directives', [])
.directive('ui', ['$templateCache', function($templateCache) {
return {
restrict: 'E',
compile: function(elem, attrs)
{
var type = attrs.type || 'span.html'; // default value ?
elem.replaceWith($templateCache.get(type));
}
}
}]);
This code wasn't tested.
EDIT: This could also work, i think, using the link function with $compile, without preloading the template, but still caching them:
angular.module('myapp.directives', [])
.directive('ui', ['$http', '$templateCache', '$compile', function($http, $templateCache, $compile) {
return {
restrict: 'E',
link: function(scope, elem, attrs)
{
var type = attrs.type || 'span.html'; // default value ?
$http.get('views/' + type + '.html', {cache: $templateCache}).then(function(result) {
elem.replaceWith($compile(result.data)(scope));
});
}
}
}]);
This code worked for me.
Upvotes: 2