amorebietakoudala/stimulus-controller-bundle
## Getting Started
### Minimal Setup
1. **Install the Bundle**
Add the package via Composer:
```bash
composer require amorebietakoudala/stimulus-controller-bundle
Enable the bundle in config/bundles.php:
Amorebietakoudala\StimulusControllerBundle\AmorebietakoudalaStimulusControllerBundle::class => ['all' => true],
Configure Webpack Encore
Ensure webpack.config.js includes the bundle’s Stimulus controllers:
Encore
.addEntry('app', './assets/app.js')
.enableStimulusBridge('./vendor/amorebietakoudala/stimulus-controller-bundle')
.splitEntry();
Run yarn encore dev to compile assets.
First Use Case: Table Controller
Use the table controller to handle row actions (e.g., delete, edit) with minimal JS:
<table data-controller="table" data-table-url-value="/api/items">
<tr data-table-target="row" data-table-id-value="1">
<td>Item 1</td>
<td>
<button data-action="click->table#delete" data-table-confirm-value="Are you sure?">
Delete
</button>
</td>
</tr>
</table>
Define the delete action in your controller (e.g., app/controllers/table_controller.js):
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['row'];
static values = { url: String, id: Number, confirm: String };
delete() {
if (!this.confirmValue || confirm(this.confirmValue)) {
fetch(`${this.urlValue}/${this.idValue}`, { method: 'DELETE' })
.then(() => this.rowTarget.remove());
}
}
}
Dynamic Form Actions
Use the action-changer controller to dynamically update form actions (e.g., for multi-step forms):
<form data-controller="action-changer" data-action-changer-url-value="/submit">
<button type="submit" data-action-changer-target="submitter" data-action="click->action-changer#submit">
Submit
</button>
</form>
// app/controllers/action_changer_controller.js
export default class extends Controller {
static targets = ['submitter'];
static values = { url: String };
submit() {
this.submitterTarget.form.action = this.urlValue;
}
}
Collection Management
Manage Symfony Collection fields (e.g., for nested forms) with the collection controller:
<div data-controller="collection" data-collection-url-value="/items">
<template data-collection-target="template">
<div data-collection-target="item">
<input name="items[0][name]" />
<button data-action="click->collection#remove">Remove</button>
</div>
</template>
<button data-action="click->collection#add">Add Item</button>
</div>
Select2 Integration
Enhance <select> elements with autofocus and AJAX loading:
<select data-controller="select2"
data-select2-url-value="/api/tags"
data-select2-autofocus-value="true">
<option value="">Choose...</option>
</select>
Entity CRUD
Use the entity controller for RESTful operations on single resources:
<div data-controller="entity" data-entity-url-value="/api/item/1">
<button data-action="click->entity#update">Save</button>
</div>
Route::delete('/api/items/{id}', [ItemController::class, 'destroy'])).stimulus-bridge is enabled for Stimulus controllers to work with Laravel’s asset pipeline.table_controller.js) by overriding methods or adding new targets/values.StimulusTestCase or Jest to test Stimulus controllers in isolation.Webpack Encore Version Mismatch
webpack-encore-bundle v1.11 or v2.1. Using an incompatible version may break asset compilation.composer.json for compatibility:
composer require symfony/webpack-encore-bundle:^2.1
Missing Stimulus Bridge
enableStimulusBridge() in webpack.config.js will prevent controllers from loading.Encore.enableStimulusBridge('./vendor/amorebietakoudala/stimulus-controller-bundle');
Data Attributes Not Binding
data-* attributes (e.g., data-table-id-value vs. data-table-id).static targets/values (e.g., data-table-id-value for id: Number).CSRF Token in AJAX Requests
fetch(url, {
method: 'DELETE',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
},
});
Select2 Dependencies
webpack.config.js:
Encore.addEntry('select2', './node_modules/select2/dist/js/select2.js')
.enablePostCssLoader()
.copyFiles({
from: './node_modules/select2/dist/css/',
to: 'css/[path][name].css',
});
app.js:
import { Application } from '@hotwired/stimulus';
const application = Application.start();
application.debug = true; // Logs controller lifecycle events
app.js. Check the Webpack output for errors.data-* attributes are correctly set on elements.Custom Controllers
Extend existing controllers by creating new files in app/controllers/ (e.g., custom_table_controller.js):
import { Controller } from '@hotwired/stimulus';
import { TableController } from 'stimulus-controller-bundle';
export default class extends TableController {
connect() {
super.connect();
console.log('Custom Table Controller initialized');
}
}
Override Defaults
Use the options value to override controller defaults (e.g., for the table controller):
<table data-controller="table"
data-table-options-value='{"confirm": "Custom message"}'>
Add New Actions
Extend controllers with additional methods (e.g., add a preview action to entity_controller.js):
preview() {
fetch(`${this.urlValue}/preview`)
.then(response => response.text())
.then(html => document.getElementById('preview').innerHTML = html);
}
Global Configuration
Centralize Stimulus settings in app.js:
application.register('global', {
connect() {
// Shared logic (e.g., CSRF token handling)
},
});
select2 controller enables autofocus by default. Disable it with:
<select data-select2-autofocus-value="false">
data-table-id-value matches the backend’s resource ID (e.g., database id field).table controller’s delete action, specify a data-table-return-url-value to redirect after deletion.import('./controllers/custom_controller.js').then(module => {
application.register('custom', module.default);
});
collection add/remove), debounce events to avoid rapid API calls:
let debounceTimer;
How can I help you explore Laravel packages today?