В документации по angular опущены многие интересные моменты не очевидные для новичков. Один из таких - как правильно передать функцию обратного вызова в директиву.
Предположим что у вас есть директива которая отображает список элементов:
<op-items items="items"></op-items>
Определение директивы выглядит так:
angular.module('myModule').directive('opItems', () => {
return {
restrict: 'E'
scope: {
items: '='
},
template: `<ul>
<li ng-repeat="item in items">{{item.title}}</li>
</ul>`
};
});
Теперь мы хотим чтобы элементы в списке можно было удалять. Для этого в шаблон opItems добавим соответствующую кнопку.
<li ng-repeat="item in items">
{{item.title}}
<button ng-click="onDelete({item: item})">×</button>
</li>
Теперь можно в контроллер директивы добавить метод onDelete и удалять элемент из списка. Но такой подход приводит к плохим последствиям. Более правильно нотифицировать того кто предоставил список о том что нужно удалить элемент.
Для этого в параметры директивы добавим еще один параметр с типом expression:
scope: {
items: '=',
onDelete: '&'
}
И изменим родительский шаблон:
<op-items items="items" on-delete="onDelete(item)"></op-items>
Теперь можно в родительском контроллере добавить метод onDelete в котором обработать событие удаления элемента. Обратите внимание что в директиве opItems методу передается объект куда вложен item onDelete({item: item})
. Этот объект становится скоупом для метода onDelete(item)
когда тот выполняется.
Таким образом мы сделали функцию обратного вызова не написав лишнего кода и не нагрузили директиву лишними знаниями о том как удалять элементы из списка. А с angular 1.5 можно заменить тип связывания параметра items с двунаправленного на однонаправленное. Это более четко обозначит интерфейс директивы и улучшит производительность.