Reputation: 113
I'm pretty new to Angular, so maybe this isn't the best way to approach a problem. I'm trying to access a factory called Devices
from a directive, called topDevices
, scope.
topDevices.js
:
app.directive('topDevices', function() {
return {
restrict: 'E',
scope: {
count: '@',
sortKey: '@',
devices: Devices.sortByKey(this.count, this.sortKey)
},
templateUrl: 'app/directives/topDevices.tpl.html'
}
});
Is this something not normally allowed or just bad practice/approach? Devices
contains a list of devices using Devices.all()
, but I also have a Devices.sortByKey(count, key)
function to return a limited set of devices sorted by a particular key.
EDIT: More info
The purpose of this is to create a template that could list, for example, the top 5 devices by some X metric. The template is this:
<h3>Top {{ count }} by {{ sortKey }}</h3>
<table class="table table-bordered table-condensed table-striped table-hover">
<tbody>
<tr ng-repeat="device in devices">
<td>{{ device.id }}</td>
<td>{{ device.name }}</td>
<td>{{ device[sortKey] }}</td>
</tr>
<tr ng-show="!devices.length">
<td colspan="3">No device info available</td>
</tr>
</tbody>
</table>
Upvotes: 1
Views: 148
Reputation: 3856
If this is an Angular factory you can pass it to the directive as a dependency:
app.directive('topDevices', function(Devices) {...})
This way you are decoupling from the concrete instance you are using
If on the other hand you want to be able to pass the sortByKey() method, and use it in the isolated scope of the directive you should defined a scope property with '&' or '=' value.
Using the ´=´ creates two way data binding, and it's the easiest to grasp:
app.directive('topDevices', function() {
return {
restrict: 'E',
scope: {
count: '@',
sortKey: '@',
sort: '='
},
templateUrl: 'app/directives/topDevices.tpl.html'
},
link: function(scope) {
scope.sort(scope.count, scope.sortKey);
}
});
the link
method of the directive is executed when it is created
Then where you use the directive:
<top-devices sort="ctrl.sortByKey"></top-devices>
ctrl is the controller from the controllerAs syntax, you can attach the factory's method to the controller like
// inside a controller
this.sortByKey = function(count, sortKey) {
return Device.sortByKey(count, sortKey);
}
I'll try to explain using the '&':
app.directive('topDevices', function() {
return {
restrict: 'E',
scope: {
count: '@',
sortKey: '@',
sort: '&'
},
templateUrl: 'app/directives/topDevices.tpl.html'
},
link: function(scope) {
scope.sort({
count: scope.count,
sortKey: scope.sortKey
});
}
});
As you can see the function is called in a different way -> passing an object which keys are the arguments names and their corresponding values
Then where you use the directive:
<top-devices sort="ctrl.sortByKey( count, sortKey)"></top-devices>
Note that this is not calling the function, because we used the '&' property definition
You can even use the sort function in the directive's html template:
topDevices.tpl.html
<div ng-show="sort({count: count, sortKey: sortKey})">
<a href="#" ng-repeat...>{{something}}</a>
</div>
Not the brightest example but you get the point
Also you can check out this relevant answer
There is another way to pass the function like this
<top-devices sort="ctrl.sortByKey"></top-devices>
Then in the ´link´ function you can use it like this
{
...
link: function(scope) {
var unwrapped = scope.sort();
unwrapped( scope.count, scope.sortKey);
}
}
Small side note - in your example you cannot access ´this.count´ and ´this.sortKey´ in the place you are using them:
1. They are not yet defined.
2. ´this´ doesn't refer the scope object.
Edit One way to achive you goal is by using a filter: check out this fiddle to see basic implementation. Or maybe there is already a built in filter that can help you do this. Filters can be combined:
<li ng-repeat="data in collection | filter1:arg | filter2:bar | filter1:foo></li>
Upvotes: 2