问题
I am trying to load conditional template urls via attributes, my directives is as follows.
The directive is in a ng-repeate and when box.key == 'experiences' the expression is returning education-form.php and not experiences-form.php.
<div multiple-form
directive-data='directiveData'
template-url="box.key == 'experiences'? 'experiences-form.php':'education-form.php'"
item="item"
forms="forms"
form-name="{{box.key}}{{item._id}}"
onsave="updateMultipleUser(box.key, item._id, $data)"
onreset="formAction($formName, 'reset')"
cancel="formAction($formName, 'cancel')"
>
</div>
Directive DDO
{
restrict: 'A',
replace: true,
scope: {
directiveData: '=',
onsave: '&',
onreset: '&',
cancel: '&',
formName: '@',
forms: '=',
item: '='
},
controller: controller,
templateUrl: function(tElement, tAttrs) {
return $rootScope.$eval(tAttrs.templateUrl);
}
}
attempting using link function
<div multiple-form
directive-data='directiveData'
template-map="{
experiences:'experiences-form.php',
courses:'education-form.php'
}"
box="box"
item="item"
forms="forms"
form-name="{{box.key}}{{item._id}}"
onsave="updateMultipleUser(box.key, item._id, $data)"
onreset="formAction($formName, 'reset')"
cancel="formAction($formName, 'cancel')"
>
</div>
controller: controller,
link: function(scope, element, attrs) {
// shows correct template url ... now what?
console.log(scope.templateMap[scope.box.key]);
},
templateUrl: function(tElement, tAttrs) {
return 'experiences-form.php';
}
回答1:
Markup
<div multiple-form
directive-data='directiveData'
ng-attr-template-url="{{box.key == 'experiences'? 'experiences-form.php':'education-form.php'}}"
item="item"
forms="forms"
form-name="{{box.key}}{{item._id}}"
onsave="updateMultipleUser(box.key, item._id, $data)"
onreset="formAction($formName, 'reset')"
cancel="formAction($formName, 'cancel')"
>
</div>
Then your templateUrl function would be
templateUrl: function(tElement, tAttrs) {
$timeout(function(){ //wait until the ng-attr evaluates a value.
return tAttrs.templateUrl;
})
}
Not sure it will work or not.
Update
Another obivious way would be loading template from the link function and append it from there it self rather than having call template through templateUrl
HTML
<div multiple-form
directive-data='directiveData'
template-path="{{box.key == 'experiences'? 'experiences-form.php':'education-form.php'}}"
item="item"
forms="forms"
form-name="{{box.key}}{{item._id}}"
onsave="updateMultipleUser(box.key, item._id, $data)"
onreset="formAction($formName, 'reset')"
cancel="formAction($formName, 'cancel')">
</div>
Directive
{
restrict: 'A',
replace: true,
scope: {
directiveData: '=',
onsave: '&',
onreset: '&',
cancel: '&',
formName: '@',
forms: '=',
item: '=',
templatePath: '@'
},
controller: controller,
link: function(scope, element, attrs){
//here you will have template path in your scope.templatePath variable
//you can load template using it.
var template = getTemplate(); //this can be done by below mentioned way
element.append($compile(template)(scope));//addding compiled element
}
}
Inside your link function you could append directive template by loading template on demand, there are several way to load template from directive
Using $templateCache
While using $templateCache
you need to put that template in angular $templateCache
at the run phase,
app.run(function($templateCache){
$templateCache.put('myTemplate.html', '<div>myTemplate</div>')
})
After doing this you could eaisily access that template in directive just by adding $templateCache.get('myTemplate.html')
Another way of adding template in $templateCache
would be using script
tag with type="text/ng-template"
<script type="text/ng-template" id="myTemplate.html">
<div>myTemplate</div>
</script>
Using $http.get
You could do get the template by using $http.get('myTemplate.html')
in success of it you will get data that is nothing but html content that file. You could compile and append that html to your directive element.
Using ng-include
You could use ng-include directive here. You need to do create a dummy div that will have an ng-include directive with desired template-path
like <div ng-include="templatePath"></div>
,it will load a template in that div. If you don't want to use div then you could use <ng-include src="templatePath"></ng-include>
. But this is not much preferable way of doing code. because it does create child scope like ng-repeat does.
来源:https://stackoverflow.com/questions/30672809/angularjs-custom-directive-conditional-templateurl-via-attribute