Изменение DOM (slideDown/slideUp) с помощью AngularJS и jQuery
Я пытаюсь реализовать анимацию slideDown/slideUp с помощью AngularJS. Я не могу использовать переход CSS3 (к сожалению), поскольку для параметра height
установлено значение auto
(и я не хочу использовать обходное решение max-height
), поэтому я пытаюсь использовать метод jQuery slideToggle
.
Учитывая следующую разметку:
<ul>
<li ng-repeat="entry in data">
<span>{{entry.title}}</span>
<a ng-click="clicked($event)" href>more?</a>
<p>{{entry.description}}</p>
</li>
</ul>
В моем контроллере был реализован следующий метод:
$scope.clicked = function($event) {
var a = jQuery($event.target);
var p = a.next();
p.slideToggle();
};
FIDDLE
Даже если это работает так, как ожидалось, я понял, что изменение DOM должно выполняться исключительно в рамках директив.
После того, как я прочитал документацию AngularJS (которую я нахожу немного светлым IMHO), директивы все еще немного расплывчаты для меня, так что кто-нибудь скажет мне, относится ли следующая директива к наилучшим оценкам Privity AngularJS или нет?
.directive('testDirective', [
function() {
return {
restrict: 'A',
scope: {
entry: '=testDirective'
},
template: '<span>{{entry.title}}</span> ' +
'<a ng-click="clicked($event)" href>more?</a>' +
'<p>{{entry.description}}</p>',
link: function(scope, element) {
var p = jQuery(element.find('p'));
scope.clicked = function($event) {
p.slideToggle();
};
}
};
}])
FIDDLE
Можно ли улучшить? Можно ли использовать jQuery в директиве? Означает ли это разделение проблем?
Ответы
Ответ 1
В качестве альтернативы вы можете использовать AngularJS $animate
:
.animation('.slide', function() {
var NG_HIDE_CLASS = 'ng-hide';
return {
beforeAddClass: function(element, className, done) {
if(className === NG_HIDE_CLASS) {
element.slideUp(done);
}
},
removeClass: function(element, className, done) {
if(className === NG_HIDE_CLASS) {
element.hide().slideDown(done);
}
}
}
});
Используйте ng-hide
или ng-show
, чтобы показать или скрыть описание.
<li ng-repeat="entry in data">
<span>{{entry.title}}</span>
<a ng-click="expand = !expand" href="#">more?</a>
<p class="slide" ng-show="expand">{{entry.description}}</p>
</li>
См. JSFiddle
P.S. вы должны включить jquery
и angular-animate.js
Ответ 2
Я хочу показать пример того, как это делается с ng-if
, так как я искал решение для нескольких часов, запущенных в несколько совершенно разных подходов, которые работают только с ng-show
. Вы можете использовать ng-if
vs ng-show
, если вы говорите, что вам нужны директивы, инициализированные только после их видимости.
Чтобы использовать jQuery slideDown/slideUp с ng-if
, вы также можете использовать ngAnimate
, но используя разные крючки: enter
и leave
.
app.animation('.ng-slide-down', function() {
return {
enter: function(element, done) {
element.hide().slideDown()
return function(cancelled) {};
},
leave: function(element, done) {
element.slideUp();
},
};
});
<div class="ng-slide-down" ng-if="isVisible">
I will slide down upon entering the DOM.
</div>
Это было удивительно сложно выполнить, даже при попытке использовать различные подходы, основанные на JS, и CSS только подходы. В конечном счете, есть время и место для анимации jQuery.