I am trying to pass a $scope\'s variable to a directive, but its not working. I am catching the variable in the template function:
app.directive(\'customdir\', f
First of all, what is a template
function? It should be a link
function. Second, you're overloading the link function incorrectly, order matters here, its always scope, element, attrs
.Third, pass the variable in an isolate scope:
app.directive('customdir', function ($compile) {
return {
restrict: 'E',
scope:{
filterby:'='
},
link: function(scope,element, attrs) {
console.log(scope.filterby);
switch (scope.filterby) {
case 'World':
return '<input type="checkbox">';
}
return '<input type="text" />';
}
};
});
or if you insist on attributes then:
app.directive('customdir', function ($compile) {
return {
restrict: 'E',
link: function(scope,element, attrs) {
console.log(attrs.filterby);
switch (attrs.filterby) {
case 'World':
return '<input type="checkbox">';
}
return '<input type="text" />';
}
};
});
but in your html:
<customdir filterby="{{name}}"></customdir>
To ensure the variables value gets evaluated first. Finally you should not be manipulating the DOM like that, in fact that link function won't render html as you'd expect. You have a static template and your link function will act as something to set variable values on the template.
Or like this
app.directive('customdir', function ($compile) {
var getTemplate = function(filter) {
switch (filter) {
case 'World': return '<input type="checkbox" ng-model="filterby">';
default: return '<input type="text" ng-model="filterby" />';
}
}
return {
restrict: 'E',
scope: {
filterby: "="
},
link: function(scope, element, attrs) {
var el = $compile(getTemplate(scope.filterby))(scope);
element.replaceWith(el);
}
};
});
http://plnkr.co/edit/yPopi0mYdViElCKrQAq9?p=preview
Template should not contain logic because template is view. Template should only contain binding directives to make the view updated based on changes of the scope (model). Something like this:
app.directive('customdir', function ($compile) {
return {
restrict: 'E',
scope:{
filterby:"="
},
link:function (scope, element) {
scope.$watch("filterby",function(newValue){ //logic is out of template
if (newValue == "World"){
scope.showCheckBox = true;
}
else {
scope.showCheckBox = false;
}
});
},
template: function(element, attrs) {
//View should be passive and only listens to changes of model to update it accordingly.
return '<input type="checkbox" ng-show="showCheckBox" / ><input type="text" ng-show="!showCheckBox" />';
}
};
});
With this approach, you could even change the input at runtime and the view is updated to reflect the changes.
DEMO
If you want to make a decision on which template to use based on some configuration, you should configure it via a normal property, should not access though scope's propery. Simply like this:
app.directive('customdir', function ($compile) {
return {
restrict: 'E',
scope: {
filterby:"=" //filterby is a separate field used for data binding
},
template: function(element, attrs) {
switch (attrs.type) { //view selection configuration should be obtained from the element
case 'checkbox':
return '<input type="checkbox">';
}
return '<input type="text" />';
}
};
});
Configure it by passing a normal value:
<customdir type="checkbox" filterby="name"></customdir>
DEMO