Skip to content
Open
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
26 changes: 26 additions & 0 deletions __tests__/model/cell.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,32 @@ describe('Cell core API', () => {
expect(parent.getChildren()?.map((c) => c.id)).toEqual(['child'])
})

it('removeCells on parent removes children even when model is null (simulates collection flow)', () => {
const parent = new Cell({ id: 'parent' } as any)
const child1 = new Cell({ id: 'child1' } as any)
const child2 = new Cell({ id: 'child2' } as any)
parent.model = model as any
child1.model = model as any
child2.model = model as any

model.addCell(parent)
model.addCell(child1)
model.addCell(child2)

parent.addChild(child1)
parent.addChild(child2)
expect((parent.getProp('children') as any as string[])?.length).toBe(2)

// Simulate what collection.removeCells does:
// it sets model=null before calling cell.remove()
parent.model = null
parent.remove()

// Children should have been removed from the model
expect(model.map['child1']).toBeUndefined()
expect(model.map['child2']).toBeUndefined()
})

it('tools APIs: normalizeTools, set/get/add/remove/has', () => {
expect(Cell.normalizeTools('a').items[0]).toBe('a')
expect(Cell.normalizeTools(['a', 'b']).items.length).toBe(2)
Expand Down
15 changes: 14 additions & 1 deletion src/model/cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1248,16 +1248,29 @@ export class Cell<
if (nextChildrenIds.length !== childrenIds.length) {
if (nextChildrenIds.length) {
parent.store.set('children', nextChildrenIds, options)
if (parent._children) {
parent._children = parent._children.filter(
(c) => c.id !== this.id,
)
}
} else {
parent.store.remove('children', options)
parent._children = null
}
}
}
}
this.setParent(null, options)

if (options.deep !== false) {
this.eachChild((child) => child.remove(options))
// When called from collection.removeCells, this.model is already null.
// Fall back to _children cache so children are still recursively removed.
const children =
this.getChildren() ??
(this._children ? [...this._children] : null)
if (children) {
children.forEach((child) => child.remove(options))
}
}

if (this.model) {
Expand Down