2016-04-28 4 views
2

При привязке функции обратного вызова к директиве важно выполнить эту функцию с правильным контекстом. Теперь, если директива имеет изолированную сферу это не проблемасвязывать обратный вызов с директивой без изолированного объема

<bar-foo callback="mycontroller.callback()"></bar-foo> 

и директива:

... 
scope:{ 
    callback: '&' 
}, 
... 

Без изолированной сферы извлечь обратный вызов от $ ATTRS attrubute

$scope.callback = $parse($attrs.callback)($scope); 

Но теперь я не могу сделать

<bar-foo callback="mycontroller.callback()"></bar-foo> 

Потому что он выполнит обратный вызов напрямую. Каким будет предпочтительный способ решить эту проблему?

DEMO

ответ

2

Сначала создайте функцию в контроллере, который явно устанавливает значение this внутри этой функции:

this.exportableCallback = this.callback.bind(this); 

где this.callback является тот, который вы используете для изолированной области.

Второй шаг устанавливает его как атрибут

<hello-world callback="mycontroller.exportableCallback"></hello-world> 

где вы сделать не вызова функции, как вы делали с изолированной области.

См. fiddle.

Другой вариант (если вы удалите this.callback из контроллера) является

this.exportableCallback = function() { 
    console.log(this.test); 
}.bind(this); 

Если вы хотите, чтобы передать аргументы этой функции:

this.exportableCallback = function() { 
    console.log(arguments); 
}.bind(this); 
+1

Я видел этот ответ: :), но я надеялся на что-то подобное, как в случае изолированного объема. Thnx! –

+1

@JeanlucaScaljeri выделенные области делают аналогичную вещь :) Они просто скрывают это от наших глаз – smnbbrv

0

Поскольку эта сфера не изолирована не просто случай призвать то, что вы хотите?

.directive('helloWorld', function() { 
    return { 
     restrict: 'E', 
     template: '<button ng-click="mycontroller.callback()">Not isolated</button>', 
    } 
}); 

а затем просто назовите свою директиву?

<hello-world></hello-world> 

Или я чего-то не хватает? Также желательно указать контроллер с атрибутом require.

+0

Что делать, если вы хотите повторно использовать директиву? – smnbbrv

+0

Вам нужно будет убедиться, что контроллер доступен с требованием, но я бы не рекомендовал этот способ делать что-то. Это был пример ответа на этот пример. На мой взгляд, лучше иметь собственный контроллер и называть вещи изолированным способом, тогда это можно использовать повторно. – PeterS

0

В вашей директиве без рамки, просто нажмите mycontroller.callback() в шаблоне директивы.

.directive('helloWorld', function() { 
    return { 
     restrict: 'E', 
     scope: false, 
     //Use THIS 
     template: '<button ng-click="mycontroller.callback()">Not isolated</button>', 
     //NOT this     
     //template: '<button ng-click="callback()">Not isolated</button>', 
     controller: function ($attrs, $scope, $parse) { 
       //$scope.callback = $parse($attrs.callback)($scope); 
     } 
    } 
}); 

Поскольку directice не имеет сферу своей собственной, шаблон имеет прямой доступ к контроллеру, который был реализованным с ng-controller="MyCtrl as mycontroller".


что, если вы хотите использовать директиву?

В этом случае привяжите обработчик кликов к элементу.

.directive('helloWorld', function() { 
    return { 
     restrict: 'E', 
     scope: false, 
     template: '<button>Not isolated</button>', 
     link: function (scope, elem, attrs) { 
      elem.on("click", function(e) { 
       scope.$eval(attrs.callback, {$event: e}); 
      }); 
     } 
    } 
}); 

Когда элемент Директивы щелкает Угловое выражение, определенное с помощью атрибута callback будет оцениваться с объектом события открывшимся в $event.

Дополнительную информацию о $event см. AngularJS Developer Guide -- $event.

+0

Что делать, если вы хотите повторно использовать директиву? – smnbbrv

Смежные вопросы