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
12 changes: 9 additions & 3 deletions src/Resources/doc/3_24.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@
A page that fetches rendered forms and swaps them into the document - a single
page CRUD, a modal that loads its form, a wizard step - initializes a model per
render. `addModel()` keeps every render in the registry, so the ones whose
markup the application has removed have to be taken back out, otherwise the
registry keeps growing and `getFormInstances()` keeps answering with elements
of nodes that are gone.
markup the application has removed have to be taken back out, otherwise
`getFormInstances()` keeps answering with elements of nodes that are gone.

Registering a form drops the registrations of that model whose markup has left
the document, so a page that swaps a form for a new one does not grow a
registration per swap on its own. That only covers the renders a later
registration of the same model passes over: a form the page removed and did not
render again, and every other model, stay in the registry until they are taken
out.

Three methods take a registration back. Each one detaches the model from the
DOM nodes it was attached to and removes the submit listener this library put
Expand Down
28 changes: 24 additions & 4 deletions src/Resources/public/js/SvarohJsFormValidator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1511,11 +1511,16 @@ describe('SvarohJsFormValidator model teardown', () => {
});

test('removeDetachedForms drops the registrations of nodes that left the document', () => {
renderProfile();
const gone = document.getElementById('profile');
document.body.innerHTML =
'<form id="profile"><input id="profile_email" name="profile[email]"></form>'
+ '<form id="profile"><input id="profile_email" name="profile[email]"></form>';
window.SvarohJsFormValidator.addModel(profileModel(), false);
window.SvarohJsFormValidator.addModel(profileModel(), false);

const [gone, kept] = Array.from(document.querySelectorAll('form'));
// The node leaves after the last registration, so the sweep that
// registering does on its own has not seen it
gone.remove();
renderProfile();
const kept = document.getElementById('profile');

expect(window.SvarohJsFormValidator.getFormInstances('profile')).toHaveLength(2);
expect(window.SvarohJsFormValidator.removeDetachedForms()).toBe(1);
Expand All @@ -1526,6 +1531,21 @@ describe('SvarohJsFormValidator model teardown', () => {
expect(window.SvarohJsFormValidator.forms.profile.domNode).toBe(kept);
});

// Registering sweeps on its own, so a page that swaps a form for a new one
// does not grow a registration per swap even when it never asks
test('registering a form drops the registrations of nodes that left the document', () => {
renderProfile();
document.getElementById('profile').remove();
renderProfile();
const kept = document.getElementById('profile');

const instances = window.SvarohJsFormValidator.getFormInstances('profile');
expect(instances).toHaveLength(1);
expect(instances[0].domNode).toBe(kept);
expect(window.SvarohJsFormValidator.forms.profile.domNode).toBe(kept);
expect(window.SvarohJsFormValidator.removeDetachedForms()).toBe(0);
});

test('initializing the same markup again does not validate the form twice', () => {
renderProfile();
const form = document.getElementById('profile');
Expand Down