AngularJS: ng-click на img? Манипулирование изображениями (вроде галереи) с помощью jQuery?

Должен ли ng-click работать с тегом img?

<img ng-src="img" ng-click="openNewWindow(url)/>

myFunction определен в контроллере и доступен в $scope... Ничто не вызвано; есть идеи?

(Я хотел бы открыть новую вкладку/окно при щелчке изображения, но я даже не попал в свою функцию)

Спасибо за любую информацию

ИЗМЕНИТЬ Я, наверное, помчался, когда впервые задал этот вопрос. Теперь я знаю, почему это не работает в моем случае: я манипулирую изображениями с помощью jQuery для какого-то эффекта "галереи"... (если у кого есть идея, как это сделать в AngularJS, пожалуйста, принесите его). Это html, о котором я говорю:

<div class="commercial-container">
    <img class="commercial" ng-src="pathToImageOrImageVar" ng-click="openNewWindow(urlToOpen)" />
    <img class="commercial" ng-src="pathToImageOrImageVar" ng-click="openNewWindow(urlToOpen2)" />
    <img class="commercial" ng-src="pathToImageOrImageVar" ng-click="openNewWindow(urlToOpen3)" />
    <img class="commercial" ng-src="pathToImageOrImageVar" ng-click="openNewWindow(urlToOpen4)" />
</div>

И здесь jQuery, с помощью которого я создаю эффект fade-in/fade-out (показывая одно изображение, затем следующее и так далее бесконечно)

 function fadeInLastImg(){
    var backImg = $('.commercial-container img:first');
    backImg.hide();
    backImg.remove();
    $('.commercial-container' ).append( backImg );
    backImg.fadeIn();
};

Итак, мой настоящий вопрос:

  • Как я могу получить то же поведение, что и с моим jQuery, чтобы изображения были ng-clickable?

Конечно, вы можете предложить лучшее решение (возможно, AngularJS) для изменения изображений, например, если вы знаете один...

Спасибо

Ответы

Ответ 1

Да, ng-click работает с изображениями.

Без дополнительного кода я не могу сказать вам, почему ваш не работает, но код, который вы вставили, вызовет myFunction в область действия контроллера, управляющего этим элементом.

ИЗМЕНИТЬ

Вам определенно не нужно использовать jQuery для этого, и он не думает об этом в стиле "angular", если вы это сделаете.

Мое предложение - сделать директиву для этого. Я создал плункер с простым примером того, как он мог выглядеть.

Здесь резюме:

Примечание. Поскольку анимация важна для вас, убедитесь, что вы включили ng-animate src и включили ее в качестве зависимости в определении вашего модуля приложения. Используйте ту же версию анимации, что и base angular.

HTML

<script src="http://code.angularjs.org/1.2.13/angular.js"></script>

<script src="http://code.angularjs.org/1.2.13/angular-animate.js"></script>

Javascript

angular.module("gallery", ['ngAnimate'])

Теперь задайте шаблон для своей директивы:

galleryPartial.html

<div class="container">
  <img ng-src="{{image.url}}" 
       alt="{{image.name}}" 
       ng-repeat="image in images" 
       class="gallery-image fade-animation"
       ng-click="openInNewWindow($index)"
       ng-show="nowShowing==$index">
</div>

Этот шаблон просто говорит: "Я хочу одно изображение для каждого элемента, указанного в массиве" images "из области действия. src должен быть свойством url изображения, а текст alt должен быть имя. Когда я нажимаю изображение, запустите функцию openInNewWindow, передающую индекс этого изображения в массиве. Наконец, скройте изображения, если только переменная nowShowing не указана в их индексе."

Также обратите внимание на класс fade-animation. Это можно назвать чем угодно, но это класс, который мы будем использовать для определения анимации в CSS позже.

Далее мы пишем эту директиву. Это довольно просто - нужно просто использовать этот шаблон, а затем определить функцию openInNewWindow, а также выполнить итерацию nowShowing через индексы массива:

.directive('galleryExample', function($interval, $window){
  return {
    restrict: 'A',
    templateUrl: 'galleryPartial.html',
    scope: {
      images: '='
    },
    link: function(scope, element, attributes){
      // Initialise the nowshowing variable to show the first image.
      scope.nowShowing = 0;

      // Set an interval to show the next image every couple of seconds.
      $interval(function showNext(){
        // Make sure we loop back to the start.
        if(scope.nowShowing != scope.images.length - 1){
          scope.nowShowing ++;
        }
        else{
          scope.nowShowing = 0;
        }
      }, 2000);

      // Image click behaviour
      scope.openInNewWindow = function(index){
        $window.open(scope.images[index].url);
      }
    }
  };
})

Вы увидите, что я использовал изолировать область, чтобы сделать эту директиву многократной, и чтобы все было прекрасно разделено. Вам не обязательно это делать, но это хорошая практика. Поэтому html для директивы должен также передавать изображения, которые вы хотите поместить в галерею, например:

index.html

  <body ng-controller="AppController">
    <div gallery-example="" images="imageList"></div>
  </body>

Итак, последний бит javascript, который нам нужно написать, - это заполнить этот массив изображений в области AppController. Обычно вы должны использовать сервис, чтобы получить список изображений с сервера или что-то в этом роде, но в этом случае мы будем его жестко кодировать:

.controller('AppController', function($scope){
  $scope.imageList = [
    {
      url: 'http://placekitten.com/200/200',
      name: 'Kitten 1'
    },
    {
      url: 'http://placekitten.com/201/201',
      name: 'Kitten 2'
    },
    {
      url: 'http://placekitten.com/201/202',
      name: 'Kitten 3'
    },
    {
      url: 'http://placekitten.com/201/203',
      name: 'Kitten 4'
    }
  ]
})

Наконец, стиль. Это также определит анимацию (обратите внимание на использование классов ng-hide и т.д.). Я настоятельно рекомендую вам прочитать здесь здесь, поскольку он слишком большой, чтобы охватить этот ответ (уже длинный!):

.fade-animation.ng-hide-add,
.fade-animation.ng-hide-remove {
  -webkit-transition:0.5s linear all;
  -moz-transition: 0.5s linear all;
  -o-transition: 0.5s linear all;
  transition:0.5s linear all;

  display:block !important;
  opacity:1;
}

Это ваш конечный результат

Ответ 2

ИЗМЕНИТЬ Поскольку, как вы сказали в комментариях, бутстрап не является для вас вариантом, я бы предложил вам написать свою небольшую директиву. Там, вероятно, есть тонны учебника, такие как this


Проблема в вашем случае заключается в том, что вы манипулируете DOM вне Angular -Scope. Итак, Angular iteslf даже не знает об этих новых элементах изображения, а также не о директиве ng-click и ng-src. Это будет иметь место только в том случае, если вы будете использовать собственный инструмент компиляции Angulars для возврата изображений в DOM.

Я бы порекомендовал вам использовать Angular -UI Bootstrap для галереи изображений. Кроме того, для этого вам нужно будет создать свою собственную Директиву, но зачем изобретать колесо?

Ответ 3

В итоге я обернул каждое изображение ссылкой и сменил jQuery соответствующим образом. Это был самый быстрый и легкий для меня.

<a href="url" target="_blank">
   <img class="commercial" ng-src="pathToImageOrImageVar"/>
</a>

И изменилась строка

var backImg = $('.commercial-container img:first');

изменено на

var backImg = $('.commercial-container a:first');

Ответ 4

У меня была эта проблема в случае, когда я использовал псевдонимы angularJS. Если бы я написал что-то вроде этого:

function someController($scope) {
    var vm = this;

    vm.switchSelected = function (passedEvent) {
    }
}

а затем, если в html-коде записать следующее:

<div ng-controller="toolBoxController as tbc">

то для использования switchSelected вам нужно написать что-то вроде этого:

<img ng-src="{{si}}" width="230px" ng-click="tbc.switchSelected($event)"/>

Итак, проверьте, использовали ли вы

 var vm=this;

в вашем контроллере. Затем вам нужно добавить aliasing к вашей части html.