Reputation: 33079
I'm confused about using '&'
with the isolate scope's rowClick
. Take a look at the code below. In a code review I was told that this, below, is an anti-pattern and that '&'
should be used instead, but I didn't get an example of how to do that.
<div ng-controller="tableController as table">
<row ng-repeat="row in table.rows" row-data="row" row-click="table.updateChart">
</row>
</div>
.controller('tableController', [function() {
this.rows = [
{ id: 'foobar', values: ['Chris', 'Kayti'] }
];
this.updateChart = function(row) {
alert('TODO: update row ' + row.id);
};
}])
.directive('row', [function() {
return {
restrict: 'E',
scope: {
rowData: '=',
rowClick: '='
},
template: '<div class="row" ng-click="rowClick(rowData)">' +
'<span ng-repeat="cell in rowData.values">{{ cell }}</span>' +
'</div>'
};
}])
(See http://plnkr.co/edit/ZofcUQcPKQp4zeSNvoOe?p=preview)
I'm reading about it but still confused. Can someone give me an example of how this code could be refactored to use '&'
, please?
Upvotes: 0
Views: 254
Reputation: 123739
It is a weird syntax and probably not well documented on how to pass the arguments. You would need to make some changes:-
In the template set &
binding and pass the argument as value of the key with a name, say row
i.e ng-click="rowClick({row: rowData})">
:
return {
restrict: 'E',
scope: {
rowData: '=',
rowClick: '&'
},
template: '<div class="row" ng-click="rowClick({row: rowData})">' +
'<span ng-repeat="cell in rowData.values">{{ cell }}</span>' +
'</div>'
};
When consuming the directive set up the name of the argument which should be inline with what your directive defines internally, i.e say row
:
row-click="table.updateChart(row)"
Demo
angular.module('app', []).controller('tableController', [
function() {
this.rows = [{
id: 'foobar',
values: ['Chris', 'Kayti']
}];
this.updateChart = function(row) {
alert('TODO: update row ' + row.id);
};
}
])
.directive('row', [
function() {
return {
restrict: 'E',
scope: {
rowData: '=',
rowClick: '&'
},
template: '<div class="row" ng-click="rowClick({row:rowData})">' +
'<span ng-repeat="cell in rowData.values">{{ cell }}</span>' +
'</div>'
};
}
])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="tableController as table">
<row ng-repeat="row in table.rows" row-data="row" row-click="table.updateChart(row)">
</row>
</div>
Upvotes: 1
Reputation: 40298
From the caller of the directive, pass the row-click
attribute as function call:
<row ng-repeat="row in table.rows" row-data="row" row-click="table.updateChart(row)"></row>
Of course change the scope definition:
scope: {
rowData: '=',
rowClick: '&'
},
And the tough part: when calling the &
function, give it an object where each "formal" argument from the calling site is a property. I cannot express it better, sorry :) For this case:
template: '<div class="row" ng-click="rowClick({row:rowData})">' +
'<span ng-repeat="cell in rowData.values">{{ cell }}</span>' +
'</div>'
If, for instance, the call was: row-click="table.updateChart(x,y,z)"
and you actually wanted to do: row-click="table.updateChart(1,2,3)"
, you should call the scope &
function as: scope.rowClick({x:1, y:2, z:3})
.
And a forked plunk: http://plnkr.co/edit/9xVWXJmMLP8A2OgGTv7R?p=preview
Upvotes: 1