Какой хороший способ управлять программным обеспечением angular -ui accordion?
Я использую директиву гармонии от http://angular-ui.github.com/bootstrap/, и мне нужно больше контролировать, когда аккордеоны открываются и закрываются.
Чтобы быть более точным, мне нужна кнопка внутри группы аккордеона, которая закроет его родительский аккордеон и откроет следующий (так что в основном имитирует, что щелчок следующего заголовка будет делать, если close-others был установлен в true).
Я также должен выполнить некоторую проверку, прежде чем я смогу разрешить закрытие аккордеона, и следующий, который нужно открыть, и мне также нужно подключить это событие для кликов на заголовках аккордеона.
Я новичок в angular, и мы в настоящее время переписываем приложение из Backbone + JQuery на Angular. В Backbone-версии мы использовали Twitter-бутстрап-аккордеоны, и мы открывали и закрывали их с помощью JQuery. Хотя мы все еще можем это делать, я бы скорее избавился от манипуляций JQuery DOM, поэтому я ищу для этого чистое решение angular.
То, что я пытался сделать с точки зрения проверки,
<accordion-group ng-click="close($event)">
и в моем контроллере
event.preventDefault();
event.stopPropagation();
Это явно не работает, поскольку элемент DOM заменяется директивой, и обработчик кликов никогда не добавляется. Я перебираю исходный код (и нашел несколько очень приятных недокументированных функций), но я в недоумении, где даже начать решение этой конкретной задачи. Я рассматривал forking angular -ui и попытался добавить эту функциональность в директиву гармоник, но если я смогу добиться этого, не изменяя директивы, которая будет намного приятнее.
Ответы
Ответ 1
В accordion-group
есть атрибут is-open
, который указывает на связующее выражение. Используя это выражение, вы можете программно управлять элементами аккордеона, например:
<div ng-controller="AccordionDemoCtrl">
<accordion>
<accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.open">
{{group.content}}
</accordion-group>
</accordion>
<button class="btn" ng-click="groups[0].open = !groups[0].open">Toggle first open</button>
<button class="btn" ng-click="groups[1].open = !groups[1].open">Toggle second open</button>
</div>
и рабочий фрагмент здесь: http://plnkr.co/edit/DepnVH?p=preview
Ответ 2
Для тех, у кого решение @pkozlowski.opensource не работает (например, я), вы можете просто заставить компонент принять CSS, который закроет его (без перехода).
Теория: Директива angular расширяется в стандартные HTML-элементы div, в основном, где стили CSS придают ей внешний вид аккордеона. Div с классом .panel-collapse
является телом элемента аккордеонной группы. Вы можете поменять свой второй класс с .in
на .collapse
вместе с несколькими другими изменениями, как показано ниже.
Код:
$scope.toggleOpen = function(project) {
var id = '<The ID of the accordion-group you want to close>';
var elements = angular.element($document[0].querySelector('#'+id));
var children = elements.children();
for(var i = 0; i < children.length; i++) {
var child = angular.element(children[i]);
if(child.hasClass('panel-collapse')) {
if(child.hasClass('in')) { // it is open
child.removeClass('in');
child.addClass('collapse');
child.css('height', '0px');
} else { // it is closed
child.addClass('in');
child.removeClass('collapse');
child.css('height', 'auto');
}
}
}
};
Как мы говорим о Angular, очень возможно, что вы генерируете аккордеон через тег ng-repeat. В этом случае вы также можете сгенерировать идентификатор для таких элементов, как:
<accordion-group ng-repeat="user in users"
is-disabled="user.projects.length == 0"
id="USER{{user._id}}">
Учитывая пользовательскую модель Mongoose, обратите внимание, что идентификатор, который я даю, не user._id
, а перед ним добавлен USER. Это связано с тем, что Mongoose может генерировать идентификатор, который начинается численно, а querySelector не нравится;-) go figure!