Подтвердить что ты не робот

Изменение 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 в директиве? Означает ли это разделение проблем?

4b9b3361

Ответ 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.