Использование Angular, как мне привязать событие click к элементу и щелкнуть, сдвинуть элемент sibling вниз и вверх?

18

Я работаю с Angular, и у меня возникают проблемы с тем, что я обычно использую для jQuery.

Я хочу привязать событие click к элементу и щелкнуть, сдвинуть элемент сиблинга вниз и вверх.

Вот что будет выглядеть jQuery:

$('element').click(function() {
    $(this).siblings('element').slideToggle();
});

Использование Angular Я добавил атрибут ng-click с функцией в моей разметке:

<div ng-click="events.displaySibling()"></div>

И вот как выглядит мой контроллер:

app.controller('myController', ['$scope', function($scope) {

    $scope.events = {};

    $scope.events.displaySibling = function() {
        console.log('clicked');
    }

}]);

Пока это работает как ожидалось, но я не знаю, как выполнить слайд. Любая помощь очень ценится.

Update

Я заменил то, что у меня было с директивой.

Моя разметка теперь выглядит так:

<div class="wrapper padding myevent"></div>

Я удалил то, что у меня было в контроллере, и создал новую директиву.

app.directive('myevent', function() {
    return {
        restrict: 'C',
        link: function(scope, element, attrs) {
            element.bind('click', function($event) {
                element.parent().children('ul').slideToggle();
            });
        }
    }
});

Однако, я все еще не могу заставить переключатель слайдов работать. Я не считаю, что slideToggle () поддерживается Angular. Любые предложения?

    
задан Michael Lynch 12.03.2014 в 19:08
источник
  • Обычно вы хотите поместить DOM-манипуляцию в директиву, а не в контроллер. –  ken4z 12.03.2014 в 19:19
  • Как указано выше, директива является правильным выбором для всех манипуляций с DOM. Если вы получаете доступ к DOM с вашего контроллера, вы соединяете контроллер с вашим видом, что означает, что вы не можете изменить представление и быть уверенным, что контроллер все еще работает. Есть еще несколько причин, но ваши манипуляции с DOM должны жить в директиве. Посмотрите на создание пользовательских директив, и это должно быть довольно ясно, я приведу простой пример ниже. –  shaunhusain 12.03.2014 в 19:22
  • Я думаю, что вы правы в том, что slideToggle не включается в jqLite, если вы включите jQuery перед Angular, он будет использовать его, и вы тоже сможете. Иногда лучше избегать этого, поэтому вам не удается попасть в старые способы и пропустить более элегантные и проверенные решения, но в других случаях просто имеет смысл включить jQuery. –  shaunhusain 12.03.2014 в 19:51
  • Я хочу избежать использования jQuery по той причине, о которой вы говорили. Я новичок в Angular и хочу сосредоточиться на этом. Есть ли простой способ добиться переключения слайдов с помощью углового? –  Michael Lynch 12.03.2014 в 19:56
  • В Angular ng-animate используется для добавления / удаления классов при выполнении определенных действий (показывая / скрывая или добавляя / удаляя элементы), тогда вам в основном нужно написать соответствующие стили в ваших таблицах стилей, чтобы добиться изменений в стиль и включение переходов. Могут быть некоторые библиотеки или директивы, уже написанные для упрощения таких вещей, как jQuery. Я разработчик ex Flex, не имеющий реального опыта jQuery, но в некоторых случаях считаю полезным использовать DOM-обход, где jQLite иногда слишком светлый. –  shaunhusain 12.03.2014 в 20:01
Показать остальные комментарии

4 ответа

12

Я не уверен точно о поведении, о котором вы говорите, но я бы посоветовал вам подумать немного по-другому. Меньше jQuery, более угловатое.

То есть, у вашего html что-то вроде этого:

<div ng-click="visible = !visible"></div>
<div ng-show="visible">I am the sibling!</div>

Затем вы можете использовать сборку в ng-animate , чтобы сделать слайд-сиблинг - yearofmoo имеет отличный обзор того, как работает $animate .

Этот пример достаточно прост, что вы можете поместить логику отображения в html, но в противном случае я бы рекомендовал вам, как правило, ввести его в контроллер, например:

<div ng-click="toggleSibling()"></div>
<div ng-show="visible"></div>

Контроллер:

app.controller('SiblingExample', function($scope){

  $scope.visible = false;

  $scope.toggleSibling = function(){
    $scope.visible = !$scope.visible;
  }

});

Этот вид компонента также является основным кандидатом на директиву, который будет аккуратно упаковать его.

    
ответ дан Ed Hinchliffe 12.03.2014 в 19:25
  • Я собирался ответить на вопрос, но @Ed имеет хороший ответ. Я еще не пробовал ngAnimate, поэтому это то, что я бы сделал, прежде чем ngAnimate был введен. Если вы хотите добавить анимацию, вы можете использовать ng-class = {'open': visible} и установить .open для отображения другого состояния и использовать переход CSS для анимации. –  Paul Sham 12.03.2014 в 20:12
  • Хорошо, поэтому вместо использования моей собственной настраиваемой директивы я могу использовать встроенные директивы ngClick и ngShow, чтобы показать / скрыть родной брат без какой-либо анимации. Я понимаю, что родной брат с ng-show="visible" будет показывать только, если для параметра "visible" установлено значение true, но вы можете объяснить выражение в ng-click="visible =! Visible"? Что здесь происходит? Я посмотрю на ng-aimate. Спасибо за вашу помощь! –  Michael Lynch 12.03.2014 в 20:16
  • visible =! visible просто инвертирует значение видимого. Читать ! как нет, т. е. если видимое истинно, то, видимо, ложно. Таким образом, в основном, нажатие верхнего div переключает видимые значения между true и false. –  Ed Hinchliffe 12.03.2014 в 22:01
  • Хорошо. Я не понимал, что это условие. Синтаксис заставляет меня думать, что он просто объявляет видимым как ложное все время. –  Michael Lynch 12.03.2014 в 23:22
  • Это не условие if, это оператор javascript, который запускается каждый раз, когда вы нажимаете на элемент. видимый, и, таким образом, это значение стоит между щелчками. Начальное значение видимого объекта - false; он установлен в вызове app.controller. Без контроллера и просто используя visible =! Visible, он будет ложным, но не на самом деле ложным. После первого щелчка он будет правдой. Последующие щелчки будут переключаться между false и true. –  majinnaibu 03.06.2015 в 11:29
5
app.directive('slideMySibling', [function(){
  // Runs during compile
  return {
    // name: '',
    // priority: 1,
    // terminal: true,
    // scope: {}, // {} = isolate, true = child, false/undefined = no change
    // controller: function($scope, $element, $attrs, $transclude) {},
    // require: 'ngModel', // Array = multiple requires, ? = optional, ^ = check parent elements
    restrict: 'A', // E = Element, A = Attribute, C = Class, M = Comment
    // template: '',
    // templateUrl: '',
    // replace: true,
    // transclude: true,
    // compile: function(tElement, tAttrs, function transclude(function(scope, cloneLinkingFn){ return function linking(scope, elm, attrs){}})),
    link: function($scope, iElm, iAttrs, controller) {
      iElm.bind("click", function(){
         $(this).siblings('element').slideToggle();
      })
    }
  };
}]);

Использование будет чем-то вроде

<div slide-my-sibling><button>Some thing</button></div><div>Some sibling</div>

Обратите внимание, что все «коды» выше приведены только для примера и на самом деле не были протестированы.

Ссылка

Вот пример Plnkr, хотя, как упоминалось в комментариях, это не идеальная настройка, так как в нем все еще есть предположение о структуре представления, которое было бы в javascript, поэтому вы идеально это сделали бы с помощью нескольких директив, в которых требуется другое или используя события (см. $ emit, $ broadcast, $ on).

У вас также может быть директива, создающая детей «программно» с помощью JavaScript и обойти проблему не зная, в каком контексте используется эта директива. Существует много возможных способов решения этих проблем, хотя ни одна из проблем не будет остановить его от функциональной работы, которую они заслуживают внимания ради повторного использования, стабильности, тестирования и т. д.

    
ответ дан shaunhusain 12.03.2014 в 19:26
  • Это больше не отделено от представления, чем пример OP, потому что вы не включили шаблон. Представьте себе, например, если бы у вас (как показывает пример использования) какой-либо элемент без сестер, щелчок по нему вызовет ошибку. Я согласен с тем, что директива - это путь, но этот шаблонный код не показывает, почему. –  Ed Hinchliffe 12.03.2014 в 19:29
  • Вы правы, это не пример с флешированием. Я просто пытался показать структуру структуры директивы (просто использовал фрагмент из SublimeText), на самом деле это не значит, что это полный ответ, я Удалите его, если хотите, но подумал, что было бы полезно увидеть. Что касается вопроса о доступе к родным братьям с вашего права, но я думаю, что в принципе это можно обрабатывать несколькими способами, используя дополнительные директивы, которые требуют друг друга, или используя emit / broadcast / on для связи между элементами, существует несколько вариантов. –  shaunhusain 12.03.2014 в 19:33
  • Действительно, нет необходимости удалять ваш ответ, я просто предлагаю сделать его более полным, вставив шаблон минимально-жизнеспособного кода. –  Ed Hinchliffe 12.03.2014 в 19:39
  • Я не верю. Угловая поддержка slideToggle (). В противном случае действует директива. Спасибо за вашу помощь! Любые предложения альтернативы slideToggle ()? –  Michael Lynch 12.03.2014 в 19:52
0

В соответствии с этой ссылкой: Ссылка

Элемент AngularJs в вашем фрагменте кода представляет объект JQuery DOM для связанного элемента. Если вы хотите использовать JQuery-функции, вы должны использовать библиотеку JQuery перед угловыми нагрузками. Для более подробной информации, пожалуйста, перейдите по ссылке выше.

    
ответ дан Ravi Kanasagra 20.06.2015 в 07:44
-2

Лучшая практика:

<div ng-if="view"></div>

$scope.view = true;

$scope.toggle = function(){
  $scope.view = ($scope.view) ? false : true;
}
    
ответ дан Rafael Stepan 04.04.2017 в 23:21
  • FYI: верхний ответ описывает это с помощью $ scope.visible =! $ scope.visible ;. Этот ответ не улучшает верхний ответ вообще. Убедитесь, что новые ответы на старые вопросы добавляют больше значения, чем предыдущие ответы. –  Liam Gray 05.04.2017 в 00:22
  • Да, верхний метод хорош, но не лучший метод для переключения! –  Rafael Stepan 05.04.2017 в 11:30