Browse Source

fix: detach reused components from their old collection in `resetFromString`

pull/6775/head
DavidHarvey 2 months ago
parent
commit
cacbf67b86
Failed to extract signature
  1. 2
      packages/core/src/dom_components/model/Components.ts
  2. 25
      packages/core/test/specs/dom_components/model/Component.ts

2
packages/core/src/dom_components/model/Components.ts

@ -70,6 +70,8 @@ const getComponentsFromDefs = (
result = all[id] as any;
const { onAttributes, onStyle } = updateOptions;
const component = result as unknown as Component;
// Detach the reused model from its old container so re-inserting it updates `collection`/`parent`
component.collection?.remove(component, { silent: true } as any);
const htmlImportOpts = { ...opts, parsedImportSource: 'html' as const };
tagName && component.set({ tagName }, { ...htmlImportOpts, silent: true });

25
packages/core/test/specs/dom_components/model/Component.ts

@ -582,6 +582,31 @@ describe('Component', () => {
);
});
test('resetFromString re-parents a reused component when its wrapper is removed', () => {
const wrapper = dcomp.getWrapper()!;
wrapper.components().resetFromString(`<div id="i5y6"><p id="i8sd">Insert your text here</p></div>`);
const div = wrapper.components().at(0);
const paragraph = div.components().at(0);
expect(div.getId()).toBe('i5y6');
expect(paragraph.getId()).toBe('i8sd');
expect(paragraph.parent()).toBe(div);
// Remove the wrapping div, promoting the reused <p> to a direct child of the wrapper.
wrapper.components().resetFromString(`<p id="i8sd">Insert your text here</p>`);
const allById = dcomp.allById();
// The same <p> model instance is reused, not rebuilt.
expect(wrapper.components().at(0)).toBe(paragraph);
expect(allById['i8sd']).toBe(paragraph);
// The removed div is gone from the global registry.
expect(allById['i5y6']).toBeUndefined();
// The reused <p> reports the wrapper as its parent, not the removed div.
expect(paragraph.parent()).toBe(wrapper);
expect(paragraph.collection).toBe(wrapper.components());
expect(em.getHtml()).toBe('<body><p id="i8sd">Insert your text here</p></body>');
});
test('Ability to stop/change propagation chain', () => {
obj.append({
removable: false,

Loading…
Cancel
Save