mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-25 20:18:38 +02:00
update cancel and reset behavior
This commit is contained in:
parent
ee6a43dd48
commit
fa588e5e35
3 changed files with 120 additions and 13 deletions
|
@ -4,6 +4,7 @@ export class NameserverForm {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.addNameserverButton = document.getElementById('nameserver-add-form');
|
this.addNameserverButton = document.getElementById('nameserver-add-form');
|
||||||
this.nameserversForm = document.querySelector('.nameservers-form');
|
this.nameserversForm = document.querySelector('.nameservers-form');
|
||||||
|
this.formChanged = false;
|
||||||
|
|
||||||
// Bind event handlers to maintain 'this' context
|
// Bind event handlers to maintain 'this' context
|
||||||
this.handleAddFormClick = this.handleAddFormClick.bind(this);
|
this.handleAddFormClick = this.handleAddFormClick.bind(this);
|
||||||
|
@ -28,6 +29,20 @@ export class NameserverForm {
|
||||||
showElement(this.nameserversForm);
|
showElement(this.nameserversForm);
|
||||||
hideElement(this.addNameserverButton);
|
hideElement(this.addNameserverButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle display of table view errors
|
||||||
|
// if error exists in an edit-row, make that row show, and readonly row hide
|
||||||
|
const formTable = document.querySelector('.usa-table')
|
||||||
|
if (formTable) {
|
||||||
|
const editRows = formTable.querySelectorAll('.edit-row');
|
||||||
|
editRows.forEach(editRow => {
|
||||||
|
if (editRow.querySelector('.usa-input--error')) {
|
||||||
|
const readOnlyRow = editRow.previousElementSibling;
|
||||||
|
showElement(editRow);
|
||||||
|
hideElement(readOnlyRow);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeEventListeners() {
|
initializeEventListeners() {
|
||||||
|
@ -42,6 +57,14 @@ export class NameserverForm {
|
||||||
cancelButtons.forEach(cancelButton => {
|
cancelButtons.forEach(cancelButton => {
|
||||||
cancelButton.addEventListener('click', this.handleCancelClick);
|
cancelButton.addEventListener('click', this.handleCancelClick);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const textInputs = document.querySelectorAll("input[type='text']");
|
||||||
|
textInputs.forEach(input => {
|
||||||
|
input.addEventListener("input", function() {
|
||||||
|
this.formChanged = true;
|
||||||
|
console.log("Form changed");
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAddFormClick(event) {
|
handleAddFormClick(event) {
|
||||||
|
@ -53,37 +76,117 @@ export class NameserverForm {
|
||||||
let editButton = event.target;
|
let editButton = event.target;
|
||||||
let readOnlyRow = editButton.closest('tr'); // Find the closest row
|
let readOnlyRow = editButton.closest('tr'); // Find the closest row
|
||||||
let editRow = readOnlyRow.nextElementSibling; // Get the next row
|
let editRow = readOnlyRow.nextElementSibling; // Get the next row
|
||||||
|
|
||||||
if (!editRow || !readOnlyRow) {
|
if (!editRow || !readOnlyRow) {
|
||||||
console.warn("Expected DOM element but did not find it");
|
console.warn("Expected DOM element but did not find it");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if any other edit row is currently visible and hide it
|
// Check if any other edit row is currently visible and hide it
|
||||||
document.querySelectorAll('tr.edit-row:not(.display-none)').forEach(openEditRow => {
|
document.querySelectorAll('tr.edit-row:not(.display-none)').forEach(openEditRow => {
|
||||||
let correspondingReadOnlyRow = openEditRow.previousElementSibling;
|
let correspondingReadOnlyRow = openEditRow.previousElementSibling;
|
||||||
hideElement(openEditRow);
|
hideElement(openEditRow);
|
||||||
showElement(correspondingReadOnlyRow);
|
showElement(correspondingReadOnlyRow);
|
||||||
});
|
});
|
||||||
|
// hide and show rows as appropriate
|
||||||
hideElement(readOnlyRow);
|
hideElement(readOnlyRow);
|
||||||
showElement(editRow);
|
showElement(editRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the click event for the cancel button within the table form.
|
||||||
|
*
|
||||||
|
* This method identifies the edit row containing the cancel button and resets
|
||||||
|
* it to its initial state, restoring the corresponding read-only row.
|
||||||
|
*
|
||||||
|
* @param {Event} event - the click event triggered by the cancel button
|
||||||
|
*/
|
||||||
handleCancelClick(event) {
|
handleCancelClick(event) {
|
||||||
|
// get the cancel button that was clicked
|
||||||
let cancelButton = event.target;
|
let cancelButton = event.target;
|
||||||
let editRow = cancelButton.closest('tr'); // Find the closest row
|
// find the closest table row that contains the cancel button
|
||||||
let readOnlyRow = editRow.previousElementSibling; // Get the next row
|
let editRow = cancelButton.closest('tr');
|
||||||
|
if (editRow) {
|
||||||
|
this.resetEditRowAndFormAndCollapseEditRow(editRow);
|
||||||
|
} else {
|
||||||
|
console.warn("Expected DOM element but did not find it");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetEditRowAndFormAndCollapseEditRow(editRow) {
|
||||||
|
let readOnlyRow = editRow.previousElementSibling; // Get the next row
|
||||||
if (!editRow || !readOnlyRow) {
|
if (!editRow || !readOnlyRow) {
|
||||||
console.warn("Expected DOM element but did not find it");
|
console.warn("Expected DOM element but did not find it");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// reset the values set in editRow
|
||||||
|
this.resetInputValuesInRow(editRow);
|
||||||
|
// copy values from editRow to readOnlyRow
|
||||||
|
this.copyEditRowToReadonlyRow(editRow, readOnlyRow);
|
||||||
|
// remove errors from the editRow
|
||||||
|
this.removeErrorsFromRow(editRow);
|
||||||
|
// remove errors from the entire form
|
||||||
|
this.removeFormErrors();
|
||||||
|
// reset formChanged
|
||||||
|
this.resetFormChanged();
|
||||||
|
// hide and show rows as appropriate
|
||||||
hideElement(editRow);
|
hideElement(editRow);
|
||||||
showElement(readOnlyRow);
|
showElement(readOnlyRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetInputValuesInRow(editRow) {
|
||||||
|
let textInputs = editRow.querySelectorAll("input[type='text']");
|
||||||
|
textInputs.forEach(input => {
|
||||||
|
input.value = input.dataset.initialValue;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
copyEditRowToReadonlyRow(editRow, readOnlyRow) {
|
||||||
|
let textInputs = editRow.querySelectorAll("input[type='text']");
|
||||||
|
let tds = readOnlyRow.querySelectorAll("td");
|
||||||
|
|
||||||
|
// if server is defined, copy the value to the first td in readOnlyRow
|
||||||
|
if (textInputs[0] && tds[0]) {
|
||||||
|
tds[0].innerText = textInputs[0].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if ip is defined, copy the value to the second td in readOnlyRow
|
||||||
|
if (textInputs[1] && tds[1]) {
|
||||||
|
tds[1].innerText = textInputs[1].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeErrorsFromRow(editRow) {
|
||||||
|
// remove class 'usa-form-group--error' from divs in editRow
|
||||||
|
editRow.querySelectorAll("div.usa-form-group--error").forEach(div => {
|
||||||
|
div.classList.remove("usa-form-group--error");
|
||||||
|
});
|
||||||
|
|
||||||
|
// remove class 'usa-label--error' from labels in editRow
|
||||||
|
editRow.querySelectorAll("label.usa-label--error").forEach(label => {
|
||||||
|
label.classList.remove("usa-label--error");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove divs whose id ends with '__error-message' (error message divs)
|
||||||
|
editRow.querySelectorAll("div[id$='__error-message']").forEach(errorDiv => {
|
||||||
|
errorDiv.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
// remove class 'usa-input--error' from inputs in editRow
|
||||||
|
editRow.querySelectorAll("input.usa-input--error").forEach(input => {
|
||||||
|
input.classList.remove("usa-input--error");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFormErrors() {
|
||||||
|
let formErrorDiv = document.getElementById("form-errors");
|
||||||
|
if (formErrorDiv) {
|
||||||
|
formErrorDiv.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetFormChanged() {
|
||||||
|
this.formChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initFormNameservers() {
|
export function initFormNameservers() {
|
||||||
|
|
|
@ -62,13 +62,13 @@
|
||||||
<div class="grid-row grid-gap-2 flex-end">
|
<div class="grid-row grid-gap-2 flex-end">
|
||||||
<div class="tablet:grid-col-6">
|
<div class="tablet:grid-col-6">
|
||||||
{% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %}
|
{% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %}
|
||||||
{% with attr_required=True span_for_text=True %}
|
{% with attr_required=True span_for_text=True add_initial_value_attr=True %}
|
||||||
{% input_with_errors form.server %}
|
{% input_with_errors form.server %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
<div class="tablet:grid-col-6">
|
<div class="tablet:grid-col-6">
|
||||||
{% with attr_required=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_group_class="usa-form-group--unstyled-error" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label %}
|
{% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_group_class="usa-form-group--unstyled-error" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label %}
|
||||||
{% input_with_errors form.ip %}
|
{% input_with_errors form.ip %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -164,13 +164,13 @@
|
||||||
<tr class="edit-row display-none">
|
<tr class="edit-row display-none">
|
||||||
<td>
|
<td>
|
||||||
{% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %}
|
{% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %}
|
||||||
{% with attr_required=True span_for_text=True add_group_class="margin-top-0" %}
|
{% with attr_required=True add_initial_value_attr=True span_for_text=True add_group_class="margin-top-0" %}
|
||||||
{% input_with_errors form.server %}
|
{% input_with_errors form.server %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% with attr_required=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_group_class="usa-form-group--unstyled-error" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label add_group_class="margin-top-0" %}
|
{% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_group_class="usa-form-group--unstyled-error" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label add_group_class="margin-top-0" %}
|
||||||
{% input_with_errors form.ip %}
|
{% input_with_errors form.ip %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</td>
|
</td>
|
||||||
|
@ -225,18 +225,18 @@
|
||||||
{% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %}
|
{% with sublabel_text="Example: ns"|concat:forloop.counter|concat:".example.com" %}
|
||||||
{% if forloop.counter <= 2 %}
|
{% if forloop.counter <= 2 %}
|
||||||
{# span_for_text will wrap the copy in s <span>, which we'll use in the JS for this component #}
|
{# span_for_text will wrap the copy in s <span>, which we'll use in the JS for this component #}
|
||||||
{% with attr_required=True add_group_class="usa-form-group--unstyled-error" span_for_text=True %}
|
{% with attr_required=True add_initial_value_attr=True add_group_class="usa-form-group--unstyled-error" span_for_text=True %}
|
||||||
{% input_with_errors form.server %}
|
{% input_with_errors form.server %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% with span_for_text=True %}
|
{% with span_for_text=True add_initial_value_attr=True %}
|
||||||
{% input_with_errors form.server %}
|
{% input_with_errors form.server %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
<div class="tablet:grid-col-6">
|
<div class="tablet:grid-col-6">
|
||||||
{% with attr_required=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_group_class="usa-form-group--unstyled-error" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label %}
|
{% with attr_required=True add_initial_value_attr=True label_text=form.ip.label sublabel_text="Example: 86.124.49.54 or 2001:db8::1234:5678" add_group_class="usa-form-group--unstyled-error" add_aria_label="Name server "|concat:forloop.counter|concat:" "|concat:form.ip.label %}
|
||||||
{% input_with_errors form.ip %}
|
{% input_with_errors form.ip %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -173,6 +173,10 @@ def input_with_errors(context, field=None): # noqa: C901
|
||||||
if aria_labels:
|
if aria_labels:
|
||||||
context["aria_label"] = " ".join(aria_labels)
|
context["aria_label"] = " ".join(aria_labels)
|
||||||
|
|
||||||
|
# Conditionally add the data-initial-value attribute
|
||||||
|
if context.get("add_initial_value_attr", False):
|
||||||
|
attrs["data-initial-value"] = field.initial or ""
|
||||||
|
|
||||||
# ask Django to give us the widget dict
|
# ask Django to give us the widget dict
|
||||||
# see Widget.get_context() on
|
# see Widget.get_context() on
|
||||||
# https://docs.djangoproject.com/en/4.1/ref/forms/widgets
|
# https://docs.djangoproject.com/en/4.1/ref/forms/widgets
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue