Вызов функции контроллера из директивы без изолированной области в AngularJS
Я не могу найти способ вызвать функцию в родительской области из директивы без использования изолированной области. Я знаю, что если я использую изолированную область, я могу просто использовать "&" в изолированной для доступа к функции в родительской области, но использование изолированной области, когда это не нужно, имеет последствия. Рассмотрим следующий HTML:
<button ng-hide="hideButton()" confirm="Are you sure?" confirm-action="doIt()">Do It</button>
в этом простом примере я хочу показать диалог подтверждения JavaScript и вызвать doIt() только если они нажмут "OK" в подтверждении диалог. Это просто с помощью изолированной области. Директива будет выглядеть так:
.directive('confirm', function () {
return {
restrict: 'A',
scope: {
confirm: '@',
confirmAction: '&'
},
link: function (scope, element, attrs) {
element.bind('click', function (e) {
if (confirm(scope.confirm)) {
scope.confirmAction();
}
});
}
};
})
но проблема в том, что, поскольку я использую изолированную область, ng-hide в приведенном выше примере больше не выполняется против родительской области, но скорее в изолированной области (поскольку использование изолированной области в любой директиве приводит к тому, что все директивы этого элемента используют изолированную область). вот jsFiddle из приведенного выше примера, где ng-hide не работает. (Отмечать что в этой скрипке кнопка должна скрываться, когда вы вводите "да" в поле ввода.)
альтернативой было бы Не использовать изолированную область, что на самом деле является тем, что я действительно хочу здесь, так как нет необходимости изолировать область действия этой директивы. Единственная проблема у меня есть, как я могу вызвать метод в родительской области, если я не передаю его в изолированную область?
вот jsfiddle где я не использую изолированные scope и ng-hide работают нормально, но, конечно, вызов confirmAction() не работает, и я не знаю, как заставить его работать.
обратите внимание, что ответ, который я действительно ищу, заключается в том, как вызывать функции во внешней области без использования изолированной области. и я не заинтересован в том, чтобы этот диалог подтверждения работал по-другому, потому что смысл этого вопроса заключается в том, чтобы выяснить, как совершать вызовы во внешнюю область и все еще иметь возможность иметь другие директивы работают против родительской области.
кроме того, мне было бы интересно услышать о решениях, которые используют изолированную область, если другие директивы все еще будут работать против родительской области, но я не думаю, что это возможно.
4 ответа:
так как директива вызывает только функцию (и не пытается установить значение для свойства), вы можете использовать $eval вместо $ parse (с неизолированной областью видимости):
scope.$apply(function() { scope.$eval(attrs.confirmAction); });
или лучше, просто использовать $apply, который будет $eval()uate его аргумент Против области:
scope.$apply(attrs.confirmAction);
вы хотите использовать сервис $parse в AngularJS.
вот пример:
.directive('confirm', function ($parse) { return { restrict: 'A', // Child scope, not isolated scope : true, link: function (scope, element, attrs) { element.bind('click', function (e) { if (confirm(attrs.confirm)) { scope.$apply(function(){ // $parse returns a getter function to be // executed against an object var fn = $parse(attrs.confirmAction); // In our case, we want to execute the statement in // confirmAction i.e. 'doIt()' against the scope // which this directive is bound to, because the // scope is a child scope, not an isolated scope. // The prototypical inheritance of scopes will mean // that it will eventually find a 'doIt' function // bound against a parent's scope. fn(scope, {$event : e}); }); } }); } }; });
есть проблема с установкой свойства с помощью $parse, но я позволю вам пересечь этот мост, когда вы придете к нему.
явного вызова
hideButton
в родительской области.вот скрипка:http://jsfiddle.net/pXej2/5/
и вот обновленный HTML:
<div ng-app="myModule" ng-controller="myController"> <input ng-model="showIt"></input> <button ng-hide="$parent.hideButton()" confirm="Are you sure?" confirm-action="doIt()">Do It</button> </div>
единственная проблема у меня есть, как я могу вызвать метод из родительской области если я не передам его в изолированную область?
вот jsfiddle, где я не использую изолированную область и ng-hide работает нормально, но, конечно, вызов confirmAction() не делает работа, и я не знаю, как заставить ее работать.
во-первых, небольшой момент: в этом случае область внешнего контроллера не является родительской областью действия директивы; внешний область действия контроллера и область действия директивы. Другими словами, имена переменных, используемые в директиве, будут просматриваться непосредственно в области контроллера.
далее писать!--4--> не работает, потому что
attrs.confirmAction
для этой кнопки<button ... confirm-action="doIt()">Do It</button>
строка
"doIt()"
, и вы не можете вызвать строку, например"doIt()"()
.Ваш вопрос действительно есть:
как мне вызвать функцию, когда я его струна?
в JavaScript вы в основном вызываете функции, используя точечную нотацию, например:
some_obj.greet()
но вы также можете использовать нотацию массива:
some_obj['greet']
обратите внимание, как значение индекса строка. Так, в директиве вы можете просто сделать это:
link: function (scope, element, attrs) { element.bind('click', function (e) { if (confirm(attrs.confirm)) { var func_str = attrs.confirmAction; var func_name = func_str.substring(0, func_str.indexOf('(')); // Or func_str.match(/[^(]+/)[0]; func_name = func_name.trim(); console.log(func_name); // => doIt scope[func_name](); } }); }