Poltavskiy
@Poltavskiy
Junior front-end developer

AngularJS как получить доступ к this контроллера дочернего компонента?

Есть два компонента, необходимо из родительского вызвать метод дочерчего
broadcast`ы не подходят, потому что данный виджет может быть вложенным один в другой, в broadcast будет идти в глубину во все дочерние
Так же не вариант использовать сервисы, ведь этих виджетов может быть несколько, с разными настройками, по этой же причине отпадает вариант и с глобальной переменной angular и rootscope

Доступ необходим для реализации логики "OnlyOneOpen"
Когда пользователь нажимает на item добавляется класс isOpen, когда он нажмёт на другой item необходимо предыдущий закрыть. Из этого же item`a я не могу закрыть остальные

Если есть какие-то идеи как можно сделать это умнее, пишите))

<moto-accordion ng-cloak>
	<moto-accordion-item class="moto-accordion-item panel panel-default">
		<header class="header-text">
			Header
		</header>
		<div class="content-text">
			Content
		</div>
	</moto-accordion-item>
</moto-accordion>


Вот родительский компонент
angular.module('moto-accordionApp')
.component('motoAccordion', {
	transclude: true,
	template:  '<div ng-transclude></div>',
	bindings: {
		openOnlyOneCheckbox: '=openOnlyOne',
		closeAllButton: '=closeAll'
	},
	controller: [
		'$element',
		'$attrs',
		'$scope',
		'openAccordionService',
		function($element, $attrs, $scope, openAccordionService) {
			this.$onInit = function () {

			};
		}
	]
});


Вот дочерний компонент
angular.module('moto-accordionApp')
.component('motoAccordionItem', {
	transclude: {
		'header': 'header',
		'body': 'div'
	},
	template:
	'<div class="panel-heading header" ng-transclude="header" ng-click="$ctrl.open()"></div>' +
	'<section ng-transclude="body" class="content"></section>',
	require: {
		motoAccordion: '^motoAccordion'
	},
	controller: [
		'$element',
		'$attrs',
		'$scope',
		'openAccordionService',
		function($element, $attrs, $scope, openAccordionService) {
			this.$onInit = function () {
				var vm = this;
				vm.isOpen = false;

				vm.open = function() {
					if(!vm.isOpen) {
						$element.addClass('isOpen');
						vm.isOpen = true;
					}
					else {
						$element.removeClass('isOpen');
						vm.isOpen = false;
					}
				}
			}
		}
	]
});
  • Вопрос задан
  • 477 просмотров
Пригласить эксперта
Ответы на вопрос 2
Сделать isOpen - биндингом, который приходит из родителя.
Сделать метод какой-то у родительского контроллера, который будет биндиться/доставаться через require в child и будет делать текущий элемент активным.
т.е. в parent:
vm.elements = [ {id: 1, isOpen: false}, {id: 2, isOpen: true}];
vm.onItemClick = function(id) {
    elements.forEach(function(element) {
           element.isOpen = (element.id === id);
    });
}
Ответ написан
@lega
В alight можно опубликовать апи для управления компонентом https://jsfiddle.net/lega911/vfeL3g6L/
В ангуляре можно сделать подобное, передавайте имя переменной в компонент, компонент туда уже будет вкладывать свое апи.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы