Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ We have JavaScript support for dynamic formsets as part of a form. For an exampl
1. Pass a custom `prefix` to the formset, e.g: `formset = FormsetFactory(prefix="<Some custom formset id>")`.
2. Create a `ul` element for the formset elements with the attribute `data-formset-list-id="<The formset prefix>"`.
3. Render the formset's `empty_form` somewhere on the page inside an element with the attribute `data-formset-template-for-id="<The formset prefix>"`.
4. To use buttons to add and remove formset items to and from the formset, use the attribute `data-formset-append-to-list-id="<The formset prefix>"` on the append button and `data-formset-remove-from-list-id="<The formset prefix>"` on the remove button.
4. Formset item templates should be fully contained within an element with the ".formset" class.
5. To use buttons to add and remove formset items to and from the formset, use the attribute `data-formset-append-to-list-id="<The formset prefix>"` on the append button and `data-formset-remove-from-list-id="<The formset prefix>"` on the remove button.
6. Inside a formset item, elements with the `data-formset-count` attribute will have their contents replaced with the current count of the formset item (e.g. "1" for the first formset item, "2" for the second, etc).
7. To make formset items collapsible, add the `data-formset-expand-collapse-toggle` to some clickable element. This will toggle the ".formset--collapsible" class on the formset. Items within the formset which should be hidden when collapsed should have the ".formset-content--collapsible" class.

### URL Format Select Field

Expand Down
14 changes: 12 additions & 2 deletions core/static/css/site.css
Original file line number Diff line number Diff line change
Expand Up @@ -510,10 +510,20 @@ a.button--primary:hover {
padding-top: 0;
}

.formset .formset__close-trigger {
.formset--collapsed button[data-formset-expand-collapse-toggle] {
transform: rotate(180deg);
}

.formset--collapsed .formset-content--collapsible {
display: none;
}

.schema-ref-formset__actions {
position: absolute;
right: 0.75rem;
top: 0.75rem;
top: 1rem;
display: flex;
gap: 1rem;
}

.formset-controls {
Expand Down
50 changes: 39 additions & 11 deletions core/static/js/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,24 @@

/** @param {HTMLElement} formsetElement */
const attachFormsetControlHandlers = (formsetElement) => {
const closeTriggerElements = Array.from(
formsetElement.getElementsByClassName('formset__close-trigger')
);
closeTriggerElements.forEach((element) => {
Array.from(
formsetElement.querySelectorAll('[data-formset-close-trigger]')
).forEach((element) => {
element.addEventListener('click', () => {
formsetElement.remove();
});
});
Array.from(
formsetElement.querySelectorAll('[data-formset-expand-collapse-toggle]')
).forEach((element) => {
element.addEventListener('click', () => {
if (formsetElement.classList.contains('formset--collapsed')) {
formsetElement.classList.remove('formset--collapsed');
return;
}
formsetElement.classList.add('formset--collapsed');
});
});
};

/**
Expand All @@ -45,7 +55,7 @@
*
* @param {HTMLElement} formsetListElement
*/
const initializeFormsetListManagementForm = (formsetListElement) => {
const initializeFormsetList = (formsetListElement) => {
const formsetListId = formsetListElement.getAttribute(
'data-formset-list-id'
);
Expand Down Expand Up @@ -73,14 +83,32 @@
);
return;
}
totalFormInput.value = formsetListElement
.getElementsByClassName('formset')
.length.toString();
// If nodes were not added, we're done. Otherwise, wire up the handlers.
const formsetElements =
formsetListElement.getElementsByClassName('formset');
totalFormInput.value = formsetElements.length.toString();
// If the number of formset items changed,
// insert the new count for each.
if (
(mutation.addedNodes && mutation.addedNodes.length) ||
(mutation.removedNodes && mutation.removedNodes.length)
) {
Array.from(formsetElements).forEach((formsetElement, index) => {
const count = (index + 1).toString();
formsetElement
.querySelectorAll('[data-formset-count]')
.forEach((countElement) => {
if (countElement instanceof HTMLElement) {
countElement.innerText = count;
}
});
});
}
// If nodes were not added, we're done.
// Otherwise, wire up the handlers and insert the correct count.
if (!mutation.addedNodes || !mutation.addedNodes.length) {
return;
}
mutation.addedNodes.forEach((node) => {
Array.from(mutation.addedNodes).forEach((node) => {
if (
node instanceof HTMLElement &&
node.classList.contains('formset')
Expand Down Expand Up @@ -202,7 +230,7 @@
if (!(formsetListElement instanceof HTMLElement)) {
return;
}
initializeFormsetListManagementForm(formsetListElement);
initializeFormsetList(formsetListElement);
Array.from(
formsetListElement.getElementsByClassName('formset')
).forEach((formsetElement) => {
Expand Down
20 changes: 14 additions & 6 deletions core/templates/core/manage/documentation_item_form.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
<li class="formset form-container">
<button class="button formset__close-trigger" type="button">
<i data-lucide="x" class="icon--md"></i>
</button>
<div class="split-field-container split-field-container--67-33">
<li class="formset form-container{% if form.url.value %} formset--collapsed{% endif %}">
<div class="schema-ref-formset__actions">
<button class="button" type="button" data-formset-close-trigger>
<i data-lucide="x" class="icon--md"></i>
</button>
<button class="button" type="button" data-formset-expand-collapse-toggle>
<i data-lucide="chevron-up" class="icon--md"></i>
</button>
</div>
<div>
Documentation Item <span data-formset-count>{{ count }}</span>
</div>
<div class="split-field-container split-field-container--67-33 formset-content--collapsible">
{% include "core/manage/field.html" with field=form.name %}
{% include "core/manage/field.html" with field=form.role %}
</div>
<div class="split-field-container split-field-container--67-33">
<div class="split-field-container split-field-container--67-33 formset-content--collapsible">
{% include "core/manage/field.html" with field=form.url %}
{% include "core/manage/field.html" with field=form.format %}
</div>
Expand Down
4 changes: 2 additions & 2 deletions core/templates/core/manage/schema.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ <h2 class="field__label--is-required">Definition URL </h2>
<ul class="formsets" data-formset-list-id="schema_refs">
{{ form.schema_refs_formset.management_form }}
{% for subform in form.schema_refs_formset %}
{% include "core/manage/schema_ref_form.html" with form=subform %}
{% include "core/manage/schema_ref_form.html" with form=subform count=forloop.counter %}
{% endfor %}
</ul>
<div class="formset-controls">
Expand All @@ -42,7 +42,7 @@ <h2>Additional documentation</h2>
<ul class="formsets" data-formset-list-id="documentation_items">
{{ form.additional_documentation_items_formset.management_form }}
{% for subform in form.additional_documentation_items_formset %}
{% include "core/manage/documentation_item_form.html" with form=subform %}
{% include "core/manage/documentation_item_form.html" with form=subform count=forloop.counter %}
{% endfor %}
</ul>
<div class="formset-controls">
Expand Down
18 changes: 13 additions & 5 deletions core/templates/core/manage/schema_ref_form.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
<li class="formset form-container">
<button class="button formset__close-trigger" type="button">
<i data-lucide="x" class="icon--md"></i>
</button>
<div class="split-field-container split-field-container--50-50">
<li class="formset form-container schema-ref-formset{% if form.url.value %} formset--collapsed{% endif %}">
<div class="schema-ref-formset__actions">
<button class="button" type="button" data-formset-close-trigger>
<i data-lucide="x" class="icon--md"></i>
</button>
<button class="button" type="button" data-formset-expand-collapse-toggle>
<i data-lucide="chevron-up" class="icon--md"></i>
</button>
</div>
<div>
Schema <span data-formset-count>{{ count }}</span>
</div>
<div class="split-field-container split-field-container--50-50 formset-content--collapsible">
{% include "core/manage/field.html" with field=form.name %}
{% include "core/manage/field.html" with field=form.url %}
</div>
Expand Down