I have two elements and will have more looking like these:
<chart type="type-one" legend="true"></chart>
<chart type="type-two" legend="true"></chart>
Each element is supposed to be processed by its own directive put in a separate file.
How can I make these directives look for both element name to be chart and type attribute to be present to be processed?
Update: @vittore, thanks for the extended answer! My issue is I want to have different types of chart that are processed by directives from different files, resulting in not having one giant file that processes chart elements with inner functions running for each type of chart, but rather more modularized files that are in charge for processing each chart type.
Now I do it like this:
app.directive('chart', function () {
return {
restrict: 'E',
require: 'ngModel',
scope: {
'ngModel': '=',
'showGrouped': '='
},
link: function (scope, element, attrs, ctrl) {
if (attrs.type != 'type-one') {return}
render()
}
}
});
So I check for the type attribute and if it's not some value, return, otherwise run respective rendering code. I have this piece of code in each directive file that does specific chart type rendering. I am sure there is something wrong in this approach.
Please advise!
Use scoped parameters
angular.module('myModule',[])
.directive('chart', function() {
return {
templateUrl:'chart.html',
replace:true,
restrict: 'E',
scope: {
type:'=',
legend:'='
}
}
})
and chart.html
<div> {{type}} {{legend}} </div>
Update:
In order to make attributes truly required, you can throw an exception from either link or compile function of directive when invalid values are provided or some values not provided at all.
Update 2:
There are 3 types of attribute scope binding: =, &, @. And you should use them appropriately.
If you want to just pass strings into directive you might use @ binding:
.directive('chart', function() {
return {
templateUrl:'chart.html',
replace:true,
restrict: 'E',
scope: {
type:'@',
legend:'@'
}
}
})
This way your parameters will be treated as a string:
scope.type='true'
scope.legend='type-one'
Or you may want to bind them to scope fields:
<chart type="myModel.type" legend="myModel.legend" />
Having = scope declarations:
.directive('chart', function() {
return {
templateUrl:'chart.html',
replace:true,
restrict: 'E',
scope: {
type:'=',
legend:'='
}
}
})
Will create two-way binding between directive's scope properties and parent scope properties:
scope.type = $parent.myModel.type
scope.legend = $parent.myModel.legend
After that you can change both properties in the parent scope and in directive scope as well.
Most complicated & binding, which allow you to provide method with parameters on parent scope to be called from directive:
app.directive("chart", function() {
return {
scope: {
details: "&"
},
template: '<input type="text" ng-model="value">' +
'<div class="button" ng-click="details({legend:value})">Show Details</div>'
}
})
and markup
<chart details='showDetails(legend)'></chart>
For details on each type of scope binding, please see excellent videos from egghead.io:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With