Таргеты: привязка элементов DOM

Таргеты в Stimulus позволяют установить прямую связь между элементами DOM и контроллером. Это обеспечивает удобный способ взаимодействия с элементами страницы без необходимости постоянно использовать селекторы querySelector или getElementById.

Каждый контроллер может иметь один или несколько таргетов, которые определяются через специальный атрибут data-<имя контроллера>-target. Имя таргета указывается после дефиса, например:

<div data-controller="example">
  <input type="text" data-example-target="input">
  <button data-action="click->example#submit">Отправить</button>
</div>

В данном примере input — это таргет контроллера example.


Объявление таргетов в контроллере

В контроллере Stimulus необходимо явно указать, какие таргеты он использует, с помощью статического свойства targets:

import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
  static targets = ["input"];

  submit() {
    console.log(this.inputTarget.value);
  }
}

Ключевые моменты:

  • static targets = ["имя"] объявляет таргет. После этого в контроллере автоматически создается свойство <имя>Target.
  • Если таргет отсутствует на странице, обращение к нему через <имя>Target вызовет ошибку. Для безопасного доступа можно использовать проверку через has<Имя>Target.

Доступ к таргетам

Stimulus генерирует специальные свойства для работы с таргетами:

  • <имя>Target — возвращает первый элемент, соответствующий таргету.
  • <имя>Targets — возвращает массив всех элементов с этим таргетом.
  • has<Имя>Target — возвращает true, если элемент с таргетом существует.
  • has<Имя>Targets — возвращает true, если существует хотя бы один элемент с таким таргетом.

Пример:

export default class extends Controller {
  static targets = ["item"];

  logItems() {
    if (this.hasItemTargets) {
      this.itemTargets.forEach((el) => console.log(el.textContent));
    }
  }
}

В этом примере проверяется наличие таргетов и выводится текст всех элементов.


Использование нескольких таргетов

Контроллер может работать с несколькими таргетами одновременно:

static targets = ["input", "output"];

updateOutput() {
  if (this.hasInputTarget && this.hasOutputTarget) {
    this.outputTarget.textContent = this.inputTarget.value;
  }
}

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


Динамическое добавление и удаление таргетов

Stimulus отслеживает изменения DOM, поэтому новые элементы с объявленными таргетами автоматически становятся доступными через свойства <имя>Targets.

Пример динамического добавления элемента:

addItem() {
  const li = document.createElement("li");
  li.dataset.exampleTarget = "item";
  li.textContent = "Новый элемент";
  this.element.appendChild(li);

  console.log(this.itemTargets.length); // теперь включает добавленный элемент
}

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


Таргеты и действия

Таргеты часто используются вместе с действиями для удобного взаимодействия:

<div data-controller="todo">
  <input type="text" data-todo-target="input">
  <button data-action="click->todo#addItem">Добавить</button>
  <ul data-todo-target="list"></ul>
</div>

Контроллер:

export default class extends Controller {
  static targets = ["input", "list"];

  addItem() {
    const li = document.createElement("li");
    li.textContent = this.inputTarget.value;
    this.listTarget.appendChild(li);
    this.inputTarget.value = "";
  }
}

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


Конвенции именования

  • Таргеты должны иметь имена в camelCase, если они составные: data-example-target="firstName".
  • Для нескольких слов в HTML используется kebab-case: data-example-target="first-name", но в контроллере это преобразуется в firstNameTarget.
  • Проверка наличия таргета: hasFirstNameTarget.

Практические советы

  • Использовать таргеты для элементов, с которыми часто происходит взаимодействие.
  • Избегать поиска элементов через селекторы внутри контроллера, если уже есть таргет.
  • Для повторяющихся элементов использовать массив Targets вместо отдельных свойств.
  • Таргеты повышают читаемость и модульность кода, делая контроллеры более предсказуемыми и удобными для тестирования.

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