Stimulus — это легковесный JavaScript-фреймворк, ориентированный на
добавление интерактивности к HTML без перегрузки сложной логикой. Его
основной принцип — связывание контроллеров с элементами
DOM через атрибуты data-*, что позволяет
организовать динамическое поведение на страницах с минимальными
усилиями. В контексте форм это особенно полезно для управления полями,
их валидацией и динамическим отображением.
Контроллер Stimulus определяется классом JavaScript, наследующимся от
Controller. Основные элементы:
Пример базового контроллера для формы:
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["input", "output"];
connect() {
console.log("Form controller connected");
}
updateOutput() {
this.outputTarget.textContent = this.inputTarget.value;
}
}
HTML-разметка для этого контроллера:
<div data-controller="form">
<input type="text" data-form-target="input" data-action="input->form#updateOutput">
<div data-form-target="output"></div>
</div>
Ключевое здесь — связывание события input с методом
контроллера через data-action. Любое изменение в поле
автоматически обновляет связанный элемент.
Частая задача — динамическая генерация новых полей в форме. Для этого удобно использовать методы контроллера:
static targets = ["fieldsContainer"];
addField(event) {
event.preventDefault();
const newField = document.createElement("input");
newField.type = "text";
newField.name = "dynamic_field[]";
newField.classList.add("dynamic-input");
this.fieldsContainerTarget.appendChild(newField);
}
removeField(event) {
event.preventDefault();
const field = event.target.closest("input");
if (field) field.remove();
}
HTML для управления динамическими полями:
<div data-controller="form">
<div data-form-target="fieldsContainer"></div>
<button data-action="click->form#addField">Добавить поле</button>
</div>
Такое решение обеспечивает чистую и реактивную логику без необходимости обращаться к глобальным селекторам или создавать сложные шаблоны вручную.
Stimulus позволяет легко показывать и скрывать поля на основе состояния других элементов. Пример:
static targets = ["toggleInput", "dependentField"];
toggleField() {
this.dependentFieldTarget.hidden = !this.toggleInputTarget.checked;
}
HTML:
<input type="checkbox" data-form-target="toggleInput" data-action="change->form#toggleField">
<input type="text" data-form-target="dependentField" hidden>
Использование hidden вместо display: none в
стиле CSS позволяет сохранять семантику формы и упрощает работу с
валидацией.
Stimulus удобно использовать для локальной валидации перед отправкой формы. Пример проверки на пустое поле:
static targets = ["input"];
validate() {
this.inputTargets.forEach((input) => {
if (!input.value.trim()) {
input.classList.add("error");
} else {
input.classList.remove("error");
}
});
}
HTML:
<form data-controller="form" data-action="submit->form#validate">
<input type="text" data-form-target="input">
<input type="text" data-form-target="input">
<button type="submit">Отправить</button>
</form>
Такой подход делает форму интерактивной и предотвращает отправку некорректных данных без использования сложных библиотек.
Stimulus values позволяют хранить состояние контроллера
и автоматически обновлять интерфейс при изменении. Пример управления
числом динамических полей:
static values = { count: Number };
addField() {
this.countValue++;
const newField = document.createElement("input");
newField.type = "text";
newField.name = `dynamic_field_${this.countValue}`;
this.fieldsContainerTarget.appendChild(newField);
}
HTML:
<div data-controller="form" data-form-count-value="0">
<div data-form-target="fieldsContainer"></div>
<button data-action="click->form#addField">Добавить поле</button>
</div>
Это обеспечивает синхронность состояния и DOM, облегчая управление сложными формами.
Комбинация targets, actions и values позволяет реализовать:
Stimulus сохраняет чистоту HTML и минимализм JavaScript, делая форму легко расширяемой и поддерживаемой. Такой подход подходит для любых интерактивных интерфейсов с большим количеством зависимых полей и условной логики.