mirror of
https://github.com/MarijnDoeve/TijdVoorDeTest.git
synced 2026-07-06 23:50:16 +02:00
feat: answer field UX improvements
- Auto-add one empty answer field when opening a blank question form - Auto-append new empty field when typing in the last answer field - Strip empty answer rows before submit (novalidate + JS cleanup) - Tab key skips correct/delete buttons, jumping straight to next answer
This commit is contained in:
@@ -8,6 +8,29 @@ export default class extends Controller {
|
||||
this.index = this.collectionTarget.children.length;
|
||||
this._setupDrag();
|
||||
this._syncOrdering();
|
||||
|
||||
if (this.index === 0) {
|
||||
this.addItem();
|
||||
}
|
||||
|
||||
this.collectionTarget.addEventListener('input', (e) => {
|
||||
if (e.target.type !== 'text') return;
|
||||
const item = e.target.closest('[data-collection-item]');
|
||||
const last = [...this.collectionTarget.children].at(-1);
|
||||
if (item && item === last && e.target.value.trim() !== '') {
|
||||
this.addItem();
|
||||
}
|
||||
});
|
||||
|
||||
const form = this.element.closest('form');
|
||||
if (form) {
|
||||
form.addEventListener('submit', () => {
|
||||
[...this.collectionTarget.children].forEach(item => {
|
||||
const input = item.querySelector('input[type="text"]');
|
||||
if (input && input.value.trim() === '') item.remove();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
addItem() {
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
<span class="text-muted" data-drag-handle style="cursor: grab" title="{{ 'Drag to reorder'|trans }}"><i class="bi bi-grip-vertical"></i></span>
|
||||
<div class="flex-grow-1">{{ form_widget(answerForm.text) }}</div>
|
||||
<div class="d-none">{{ form_widget(answerForm.isRightAnswer) }}</div>
|
||||
<button type="button"
|
||||
<button type="button" tabindex="-1"
|
||||
class="btn btn-sm {{ answerForm.isRightAnswer.vars.checked ? 'btn-success' : 'btn-danger' }}"
|
||||
title="{{ 'Toggle correct answer'|trans }}"
|
||||
onclick="var cb=this.closest('[data-collection-item]').querySelector('input[type=checkbox]');cb.checked=!cb.checked;this.classList.toggle('btn-success',cb.checked);this.classList.toggle('btn-danger',!cb.checked);this.querySelector('i').className=cb.checked?'bi bi-check-lg':'bi bi-x-lg'">
|
||||
<i class="{{ answerForm.isRightAnswer.vars.checked ? 'bi bi-check-lg' : 'bi bi-x-lg' }}"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-danger"
|
||||
<button type="button" tabindex="-1" class="btn btn-sm btn-outline-danger"
|
||||
data-action="bo--form-collection#removeItem"><i class="bi bi-trash"></i></button>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% import 'backoffice/partials/answer_row.html.twig' as macros %}
|
||||
|
||||
{{ form_start(form) }}
|
||||
{{ form_start(form, {attr: {novalidate: 'novalidate'}}) }}
|
||||
{{ form_row(form.question) }}
|
||||
{{ form_row(form.reusable) }}
|
||||
{{ form_row(form.labels) }}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% import 'backoffice/partials/answer_row.html.twig' as macros %}
|
||||
|
||||
{{ form_start(form) }}
|
||||
{{ form_start(form, {attr: {novalidate: 'novalidate'}}) }}
|
||||
{{ form_row(form.question) }}
|
||||
|
||||
<div data-controller="bo--form-collection"
|
||||
|
||||
@@ -73,10 +73,10 @@
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
<button class="btn btn-danger" data-action="click->bo--quiz#clearQuiz">
|
||||
<button class="btn btn-danger rounded-0" data-action="click->bo--quiz#clearQuiz">
|
||||
{{ 'Clear Quiz...'|trans }}
|
||||
</button>
|
||||
<button class="btn btn-danger rounded-0 " data-action="click->bo--quiz#deleteQuiz">
|
||||
<button class="btn btn-danger rounded-0" data-action="click->bo--quiz#deleteQuiz">
|
||||
{{ 'Delete Quiz...'|trans }}
|
||||
</button>
|
||||
<a class="btn btn-secondary rounded-0 rounded-end"
|
||||
|
||||
Reference in New Issue
Block a user