У меня есть директива, вот код:
.directive('map', function() {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
link: function($scope, element, attrs) {
var center = new google.maps.LatLng(50.1, 14.4);
$scope.map_options = {
zoom: 14,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// create map
var map = new google.maps.Map(document.getElementById(attrs.id), $scope.map_options);
var dirService= new google.maps.DirectionsService();
var dirRenderer= new google.maps.DirectionsRenderer()
var showDirections = function(dirResult, dirStatus) {
if (dirStatus != google.maps.DirectionsStatus.OK) {
alert('Directions failed: ' + dirStatus);
return;
}
// Show directions
dirRenderer.setMap(map);
//$scope.dirRenderer.setPanel(Demo.dirContainer);
dirRenderer.setDirections(dirResult);
};
// Watch
var updateMap = function(){
dirService.route($scope.dirRequest, showDirections);
};
$scope.$watch('dirRequest.origin', updateMap);
google.maps.event.addListener(map, 'zoom_changed', function() {
$scope.map_options.zoom = map.getZoom();
});
dirService.route($scope.dirRequest, showDirections);
}
}
})
Я хотел бы призвать updateMap()
к действию пользователя. Кнопка действия не указана в директиве.
Как лучше всего позвонить updateMap()
с контроллера?
angularjs
angularjs-directive
mcbjam
источник
источник
Ответы:
Если вы хотите использовать изолированные области, вы можете передать объект управления, используя двунаправленную привязку
=
переменной из области контроллера. Вы также можете управлять несколькими экземплярами одной и той же директивы на странице с одним и тем же объектом управления.источник
scope.control
существует, в противном случае другие места, которые используют директиву, но не нуждаются в доступе к методам директивы и не имеютcontrol
attr, начнут выдавать ошибки о невозможности установить атрибутыundefined
Если предположить , что действие кнопка использует тот же контроллер
$scope
, что и директива, просто определить функциюupdateMap
на$scope
внутри функции связи. Затем ваш контроллер может вызвать эту функцию при нажатии кнопки действия.fiddle
Согласно комментарию @ FlorianF, если директива использует изолированную область видимости, все будет сложнее. Вот один из способов заставить его работать: добавьте
set-fn
атрибут вmap
директиву, который зарегистрирует функцию директивы в контроллере:fiddle
источник
scope
свойство в объявление директивы.Хотя может показаться заманчивым выставить объект в изолированной области действия директивы для облегчения связи с ним, выполнение может привести к путанице в коде «спагетти», особенно если вам нужно связать эту связь через пару уровней (от контроллера до директивы, вложенной директиве и т. д.)
Первоначально мы пошли по этому пути, но после дополнительных исследований выяснили, что это имеет больше смысла и привело к созданию более удобного и удобочитаемого кода для представления событий и свойств, которые директива будет использовать для связи через службу, а затем с помощью $ watch для свойств этой службы в директива или любые другие элементы управления, которые должны были бы реагировать на эти изменения для связи.
Эта абстракция очень хорошо работает с инфраструктурой внедрения зависимостей AngularJS, поскольку вы можете внедрить службу в любые элементы, которые должны реагировать на эти события. Если вы посмотрите на файл Angular.js, то увидите, что директивы в нем также используют службы и $ watch таким образом, они не отображают события в изолированной области видимости.
Наконец, в случае, если вам нужно обмениваться данными между директивами, которые зависят друг от друга, я бы порекомендовал разделить контроллер между этими директивами в качестве средства связи.
В Wiki для лучших практик AngularJS также упоминается следующее:
источник
=
, переменная содержит имя метода и аргументы. (2) выставить строку одностороннего связывания в@
качестве идентификатора темы и позволить вызываемому абоненту отправить событие по этой теме. Теперь я видел лучшие практики вики. Я думаю, что есть причина не делать это в любом случае. Но мне все еще не очень понятно, как это работает. В моем случае я создал директиву tabset, я хочу предоставитьswitchTab(tabIndex)
метод. Не могли бы вы привести пример?switchTab(tabIndex)
метод, вы бы связались только сtabIndex
переменной. Ваш контроллер страницы может иметь действия, которые изменяют эту переменную. Вы связываете / передаете эту переменную в вашу вкладку Directive. Ваша директива Tab может затем отслеживать эту переменную на предмет изменений и выполнять switchTab самостоятельно. Потому что директива решает, когда и как управлять своими вкладками на основе переменной. Это не работа внешнего источника, в противном случае внешние источники требуют знания внутренней работы директивы, что плохо.Основываясь на ответе Оливера - вам не всегда может понадобиться доступ к внутренним методам директивы, и в этих случаях вам, вероятно, не нужно создавать пустой объект и добавлять
control
attr к директиве просто для того, чтобы она не выдавала ошибку (cannot set property 'takeTablet' of undefined
).Вы также можете использовать метод в других местах директивы.
Я бы добавил проверку, чтобы убедиться, что она
scope.control
существует, и установил для нее методы аналогично шаблону раскрывающегося модуля.источник
Если честно, меня не очень убедил ни один из ответов в этой теме. Итак, вот мои решения:
Директива Обработчик (Менеджер) Подход
Этот метод не зависит от того,
$scope
является ли директива разделяемой или изолированнойА,
factory
чтобы зарегистрировать экземпляры директивыКод директивы, я обычно помещаю всю логику, которая не имеет дело с DOM, внутри контроллера директив. И регистрация экземпляра контроллера внутри нашего обработчика
код шаблона
Получите доступ к экземпляру контроллера с помощью
factory
& запускайте общедоступные методыУгловой подход
Извлечение листа из книги Angular о том, как они справляются
используя $ parse и регистрируя контроллер в
$parent
области видимости. Этот метод не работает с изолированными$scope
директивами.Доступ к нему внутри контроллера с помощью
$scope.foo
источник
$scope.foo
должно быть$scope.my_form
$scope.foo
так как наш шаблон<div my-directive name="foo"></div>
иname
значение атрибута является «Foo».<form
это всего лишь пример одной из директив угловой, в которой используется эта техникаНемного поздно, но это решение с изолированной областью действия и «событиями» для вызова функции в директиве. Это решение вдохновлен этой SO пост по satchmorun и добавляет модуль и API.
Создайте API для связи с директивой. AddUpdateEvent добавляет событие в массив событий, а updateMap вызывает каждую функцию события.
(Может быть, вам нужно добавить функциональность, чтобы удалить событие.)
В директиве установите ссылку на MapAPI и добавьте $ scope.updateMap как событие, когда вызывается MapApi.updateMap.
В «главном» контроллере добавьте ссылку на MapApi и просто вызовите MapApi.updateMap (), чтобы обновить карту.
источник
Вы можете указать атрибут DOM, который можно использовать, чтобы директива определяла функцию в родительской области. Родительская область может затем вызвать этот метод, как и любой другой. Вот плункер. И ниже соответствующий код.
clearfn
является атрибутом элемента директивы, в который родительская область может передавать свойство области, которое директива затем может установить для функции, которая выполняет желаемое поведение.источник
scope: { clearFn: '=clearfn' }
).Просто используйте scope. $ Parent, чтобы связать функцию, вызываемую с функцией директивы
в HTML
источник
Вы можете сообщить имя метода директиве, чтобы определить, какой метод вы хотите вызвать из контроллера, но без изолированной области видимости,
источник
ПРОВЕРЕНО Надеюсь, что это кому-то поможет.
Мой простой подход (Думайте теги как ваш оригинальный код)
источник
Возможно, это не лучший выбор, но вы можете сделать
angular.element("#element").isolateScope()
или$("#element").isolateScope()
получить доступ к области действия и / или контроллеру вашей директивы.источник
Как получить контроллер директивы в контроллере страницы:
напишите пользовательскую директиву, чтобы получить ссылку на контроллер директивы из элемента DOM:
используйте его в html-контроллере страницы:
Используйте директивный контроллер в контроллере страницы:
Примечание: данное решение работает только для контроллеров директив элемента (имя тега используется для получения имени требуемой директивы).
источник
Приведенное ниже решение будет полезно, когда у вас есть контроллеры (как родительские, так и директивы (изолированные)) в формате «контроллер как»
кто-то может найти это полезным,
директива:
Директива контроллера:
HTML-код:
источник