AngularJS - найти элемент с атрибутом

Я новичок в AngularJS. Я узнал, что могу найти элементы в DOM, используя следующие запросы:

var e = angular.element(document.querySelector('#id'));
var e = angular.element(elem.querySelector('.classname'));

Это полезно для поиска элементов по идентификатору или имени класса CSS. Однако мне нужно найти элемент, используя другой подход. У меня есть элемент, который выглядит следующим образом:

<div my-directive class='myContainer'>...</div>

Я не могу запросить "myContainer" из-за того, насколько он повторно используется. По этой причине я хотел бы найти любой элемент с атрибутом 'my-directive'. Как выполнить поиск в DOM и найти любой элемент, который использует "my-directive"?

Ответ 1

Вместо запроса DOM для элементов (который не очень похож на angular см. "Мышление в AngularJS" , если у меня есть фон jQuery?), вы должны выполните свою DOM-манипуляцию в своей директиве. Элемент доступен вам в вашей функции ссылок.

Итак, в вашем myDirective

return {
    link: function (scope, element, attr) {
        element.html('Hello world');
    }
}

Если вы должны выполнить запрос за пределами директивы, тогда было бы возможно использовать querySelectorAll в современных браузерах

angular.element(document.querySelectorAll("[my-directive]"));

однако вам нужно будет использовать jquery для поддержки IE8 и назад

angular.element($("[my-directive]"));

или напишите свой собственный метод, как показано здесь Получить элементы по атрибуту, когда querySelectorAll недоступен без использования библиотек?

Ответ 2

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

Способ состоит в том, что дочерняя директива может require родительскую директиву. Директива parent может выставить метод, который позволяет прямой директиве регистрировать свой элемент с родительской директивой. Благодаря этому родительская директива может получить доступ к дочернему элементу (элементам). Поэтому, если у вас есть шаблон, например:

<div parent-directive>
  <div child-directive></div>
  <div child-directive></div>
</div>

Тогда директивы могут быть закодированы следующим образом:

app.directive('parentDirective', function($window) {
  return {
    controller: function($scope) {
      var registeredElements = [];
      this.registerElement = function(childElement) {
        registeredElements.push(childElement);
      }
    }
  };
});

app.directive('childDirective', function() {
  return {
    require: '^parentDirective',
    template: '<span>Child directive</span>',
    link: function link(scope, iElement, iAttrs, parentController) {
      parentController.registerElement(iElement);
    }
   };
});

Это можно увидеть в действии http://plnkr.co/edit/7zUgNp2MV3wMyAUYxlkz?p=preview

Ответ 3

Вы не указали, где вы ищете элемент. Если это входит в сферу действия контроллера, возможно, несмотря на хор, который вы услышите об этом, не являясь "Angular Way". Хор хорош, но иногда, в реальном мире, это неизбежно. (Если вы не согласны, свяжитесь с нами - у меня есть вызов для вас.)

Если вы передадите $element в контроллер, как и вы, $scope, вы можете использовать его функцию find(). Обратите внимание, что в jQueryLite, включенном в Angular, find() будет определять метки только по имени, а не по атрибуту. Однако, если вы включите полномасштабный jQuery в свой проект, можно использовать все функции find(), включая поиск по атрибуту.

Итак, для этого HTML:

<div ng-controller='MyCtrl'>
    <div>
        <div name='foo' class='myElementClass'>this one</div>
    </div>
</div>

Этот код AngularJS должен работать:

angular.module('MyClient').controller('MyCtrl', [
    '$scope',
    '$element',
    '$log',
    function ($scope, $element, $log) {

        // Find the element by its class attribute, within your controller scope
        var myElements = $element.find('.myElementClass');

        // myElements is now an array of jQuery DOM elements

        if (myElements.length == 0) {
            // Not found. Are you sure you've included the full jQuery?
        } else {
            // There should only be one, and it will be element 0
            $log.debug(myElements[0].name); // "foo"
        }

    }
]);