Reputation: 18875
I am trying to create a directive named availableTo
that can switch between two different templates depending on some message. For example, if the field is an input
with the ng-model
directive, I would first need to change it to read-only using the <span>
tag. So far, my code can switch the view to read-only, but I cannot seem to switch it back to input
:
var directive = {
restrict: 'A',
require: '?ngModel',
link: linkerFn,
replace: true
};
function linkerFn(scope, element, attrs, ngModelCtrl) {
var clonedElement = angular.copy(element);
var preOuterHTML = clonedElement[0].outerHTML; //this can save the <input> field html code
scope.$on('mode_changed', function() {
var curUserRole = userservices.getUserRole();
if (attrs.availableTo == curUserRole) {
var e = $compile(preOuterHTML)(scope);
element.replaceWith(e);
} else {
var template = '<span>' + ngModelCtrl.$viewValue + '</span>';
var e = $compile(template)(scope);
element.replaceWith(e);
}
}); //scope.$on
} //linkerFn
For an input
field:
<input name="test1" class="form-control" ng-model="name" placeholder="Name 1" available-to="ADMIN"/>
I also noticed that once I change the template in the else
block above, the element re-renders, and the preOuterHTML
does not contain the original element html any more. This seems to be mission impossible to me, but I would like to hear some expert opinions. Thanks
Upvotes: 0
Views: 1445
Reputation: 21475
element.replaceWith(e);
Don't do that. In Angular, if you find yourself attempting to modify the DOM directly, you are by definition doing it wrong. You gotta sit back and let Angular do the work.
If you need to replace a directive's entire template, a fairly straightforward approach is to use ng-include with a scope variable containing the desired conditional templateUrl
, e.g.
var directive = {
// ...
template: '<div ng-include="myTemplateUrl"></div>',
link: function(scope, el) {
if (/* whatever */) {
scope.myTemplateUrl="templates/foo.html";
} else {
//...etc
}
},
};
(This does add an extra DOM node to the tree, but that's generally harmless.)
It sounds like in your case you may not need to go that far, though; a simple ng-if
inside your template is probably enough to swap between your read-only <span>
and <input>
.
Upvotes: 3