-
-
Save bjo3rnf/85e8490b98955cb6016f44445d9843fb to your computer and use it in GitHub Desktop.
{% macro collection_item(form) %} | |
<div data-form-collection-target="field"> | |
{{ form_widget(form) }} | |
<button type="button" | |
data-action="form-collection#removeItem"> | |
remove | |
</button> | |
</div> | |
{% endmacro %} | |
{% import _self as formMacros %} | |
{{ form_start(form) }} | |
<div data-controller="form-collection" | |
data-form-collection-max-items-value="10" | |
data-form-collection-prototype-value="{{ formMacros.collection_item(form.collectionField.vars.prototype)|json_encode }}"> | |
<div data-form-collection-target="fields"> | |
{% do form.collectionField.setRendered %} | |
{% for field in form.collectionField %} | |
{{ formMacros.collection_item(field) }} | |
{% endfor %} | |
</div> | |
<button type="button" | |
data-action="form-collection#addItem" | |
data-form-collection-target="addButton"> | |
add | |
</button> | |
</div> | |
{{ form_rest(form) }} | |
{{ form_end(form) }} |
import { Controller } from 'stimulus' | |
export default class extends Controller { | |
static targets = [ 'fields', 'field', 'addButton' ] | |
static values = { | |
prototype: String, | |
maxItems: Number, | |
itemsCount: Number, | |
} | |
connect() { | |
this.index = this.itemsCountValue = this.fieldTargets.length | |
} | |
addItem() { | |
let prototype = JSON.parse(this.prototypeValue) | |
const newField = prototype.replace(/__name__/g, this.index) | |
this.fieldsTarget.insertAdjacentHTML('beforeend', newField) | |
this.index++ | |
this.itemsCountValue++ | |
} | |
removeItem(event) { | |
this.fieldTargets.forEach(element => { | |
if (element.contains(event.target)) { | |
element.remove() | |
this.itemsCountValue-- | |
} | |
}) | |
} | |
itemsCountValueChanged() { | |
if (false === this.hasAddButtonTarget || 0 === this.maxItemsValue) { | |
return | |
} | |
const maxItemsReached = this.itemsCountValue >= this.maxItemsValue | |
this.addButtonTarget.classList.toggle('hidden', maxItemsReached) | |
} | |
} |
The addButton target is not used inside the html.
Instead of
<button data-action="form-collection#addItem">
add
</button>
It should be:
<button data-form-collection-target="addButton">
add
</button>
Than you need to add the eventListener manually.
connect() {
this.index = this.itemsCountValue = this.fieldTargets.length
this.hasAddButtonTarget && this.addButtonTarget.addEventListener('click', event => this.addItem(event))
}
Hi @MichaelBrauner,
the target is used to control if the add-button should be rendered or not depending on a possible upper limit of elements (see itemsCountValueChanged()
. Moreover adding of event-handlers should be left to the framework to ensure they will be removed automatically as well.
Cheers
Björn
Ok. The eventListener should be set with a data-action attribute. I did it this way because so I have not to set the target and the action. But u are right. It might be better to use the framework for that.
But the data-form-collection-target
on the button is missing anyway in your example html.
The itemsCountValueChanged()
function can not set a hidden class on a non existing target.
Yes, you are right. I added the missing target, thanks.
Thank you much for sharing this.