Skip to content

Commit 40f4214

Browse files
authored
fix(list-render): add support for children-outlet component (#250)
1 parent 831ec85 commit 40f4214

17 files changed

+324
-100
lines changed

.changeset/calm-jokes-shout.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'slate-angular': patch
3+
---
4+
5+
support custom elements to set the position of children elements

demo/app/components/editable-button/editable-button.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import { ChangeDetectionStrategy, Component, HostListener } from '@angular/core';
22
import { ButtonElement } from '../../../../custom-types';
33
import { BaseElementComponent } from 'slate-angular';
4-
import { SlateChildren } from '../../../../packages/src/components/children/children.component';
4+
import { SlateChildrenOutlet } from '../../../../packages/src/components/children/children-outlet.component';
55

66
@Component({
77
selector: 'span[demo-element-button]',
88
template: `
99
<span contenteditable="false" style="font-size: 0;">{{ inlineChromiumBugfix }}</span>
10-
<slate-children [children]="children" [context]="childrenContext" [viewContext]="viewContext"></slate-children>
10+
<slate-children-outlet></slate-children-outlet>
1111
<span contenteditable="false" style="font-size: 0;">{{ inlineChromiumBugfix }}</span>
1212
`,
1313
host: {
1414
class: 'demo-element-button'
1515
},
1616
changeDetection: ChangeDetectionStrategy.OnPush,
1717
standalone: true,
18-
imports: [SlateChildren]
18+
imports: [SlateChildrenOutlet]
1919
})
2020
export class DemoElementEditableButtonComponent extends BaseElementComponent<ButtonElement> {
2121
// Put this at the start and end of an inline component to work around this Chromium bug:

demo/app/components/link/link.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { ChangeDetectionStrategy, Component, HostBinding, HostListener } from '@angular/core';
22
import { LinkElement } from 'custom-types';
33
import { BaseElementComponent } from 'slate-angular';
4-
import { SlateChildren } from '../../../../packages/src/components/children/children.component';
4+
import { SlateChildrenOutlet } from '../../../../packages/src/components/children/children-outlet.component';
55

66
@Component({
77
selector: 'a[demo-element-link]',
88
template: `
99
<span contenteditable="false" style="font-size: 0;">{{ inlineChromiumBugfix }}</span>
10-
<slate-children [children]="children" [context]="childrenContext" [viewContext]="viewContext"></slate-children>
10+
<slate-children-outlet></slate-children-outlet>
1111
<span contenteditable="false" style="font-size: 0;">{{ inlineChromiumBugfix }}</span>
1212
`,
1313
changeDetection: ChangeDetectionStrategy.OnPush,
1414
standalone: true,
15-
imports: [SlateChildren]
15+
imports:[SlateChildrenOutlet]
1616
})
1717
export class DemoElementLinkComponent extends BaseElementComponent<LinkElement> {
1818
// Put this at the start and end of an inline component to work around this Chromium bug:
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ChangeDetectionStrategy, Component, ElementRef } from '@angular/core';
2+
3+
@Component({
4+
selector: 'slate-children-outlet',
5+
template: ``,
6+
changeDetection: ChangeDetectionStrategy.OnPush,
7+
standalone: true
8+
})
9+
export class SlateChildrenOutlet {
10+
constructor(private elementRef: ElementRef<HTMLElement>) {}
11+
getNativeElement() {
12+
return this.elementRef.nativeElement;
13+
}
14+
}

packages/src/components/children/children.component.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import { NgFor } from '@angular/common';
88
selector: 'slate-children',
99
template: ``,
1010
changeDetection: ChangeDetectionStrategy.OnPush,
11-
standalone: true,
12-
imports: [NgFor]
11+
standalone: true
1312
})
1413
export class SlateChildren extends ViewContainer<any> {
1514
@Input() children: Descendant[];
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<slate-string-template #templateComponent></slate-string-template>
1+
<slate-string-template #templateComponent></slate-string-template>

packages/src/components/editable/editable.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ export class SlateEditable implements OnInit, OnChanges, OnDestroy, AfterViewChe
191191

192192
viewContainerRef = inject(ViewContainerRef);
193193

194-
getOutletElement = () => {
194+
getOutletParent = () => {
195195
return this.elementRef.nativeElement;
196196
};
197197

@@ -239,7 +239,7 @@ export class SlateEditable implements OnInit, OnChanges, OnDestroy, AfterViewChe
239239
// add browser class
240240
let browserClass = IS_FIREFOX ? 'firefox' : IS_SAFARI ? 'safari' : '';
241241
browserClass && this.elementRef.nativeElement.classList.add(browserClass);
242-
this.listRender = new ListRender(this.viewContext, this.viewContainerRef, this.getOutletElement);
242+
this.listRender = new ListRender(this.viewContext, this.viewContainerRef, this.getOutletParent, () => null);
243243
}
244244

245245
ngOnChanges(simpleChanges: SimpleChanges) {

packages/src/module.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { SlateDefaultElement } from './components/element/default-element.compon
88
import { SlateString } from './components/string/string.component';
99
import { SlateStringTemplate } from './components/string/template.component';
1010
import { SlateChildren } from './components/children/children.component';
11+
import { SlateChildrenOutlet } from './components/children/children-outlet.component';
1112
import { SlateBlockCard } from './components/block-card/block-card.component';
1213
import { SlateDefaultLeaf } from './components/leaf/default-leaf.component';
1314
import { SlateLeaves } from './components/leaves/leaves.component';
@@ -28,11 +29,13 @@ import { SlateDefaultString } from './components/string/default-string.component
2829
SlateBlockCard,
2930
SlateLeaves,
3031
SlateDefaultLeaf,
31-
SlateDefaultString
32+
SlateDefaultString,
33+
SlateChildrenOutlet
3234
],
3335
exports: [
3436
SlateEditable,
3537
SlateChildren,
38+
SlateChildrenOutlet,
3639
SlateElement,
3740
SlateLeaves,
3841
SlateString,

packages/src/testing/create-document.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function createDefaultDocument() {
1515
];
1616
}
1717

18-
export function createMutipleParagraph() {
18+
export function createMultipleParagraph() {
1919
return [
2020
{
2121
type: 'paragraph',
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { Component, ViewChild } from '@angular/core';
2+
import { createEditor, Element } from 'slate';
3+
import { SlateEditable } from '../components/editable/editable.component';
4+
import { withAngular } from '../plugins/with-angular';
5+
import { SlateChildrenOutlet } from '../components/children/children-outlet.component';
6+
import { BaseElementComponent } from '../view/base';
7+
8+
const customType = 'custom-with-outlet';
9+
10+
@Component({
11+
selector: 'editable-with-outlet',
12+
template: `<slate-editable
13+
[editor]="editor"
14+
[(ngModel)]="value"
15+
(ngModelChange)="ngModelChange()"
16+
[renderElement]="renderElement()"
17+
></slate-editable> `
18+
})
19+
export class EditableWithOutletComponent {
20+
editor = withAngular(createEditor());
21+
22+
value: Element[] = createDefaultDocument() as Element[];
23+
24+
@ViewChild(SlateEditable, { static: true })
25+
editableComponent: SlateEditable;
26+
27+
renderElement() {
28+
return (element: Element) => {
29+
if ((element.type as any) === customType) {
30+
return TestElementWithOutletComponent;
31+
}
32+
return null;
33+
};
34+
}
35+
36+
ngModelChange() {}
37+
38+
constructor() {}
39+
}
40+
41+
export function createDefaultDocument() {
42+
return [
43+
{
44+
type: customType,
45+
children: [
46+
{
47+
type: 'paragraph',
48+
children: [{ text: 'This is editable text!' }]
49+
}
50+
]
51+
}
52+
];
53+
}
54+
55+
@Component({
56+
selector: 'div[test-element-with-outlet]',
57+
template: `
58+
<div>before</div>
59+
<slate-children-outlet></slate-children-outlet>
60+
<div>after</div>
61+
`,
62+
host: {
63+
class: 'test-element-with-outlet'
64+
},
65+
standalone: true,
66+
imports: [SlateChildrenOutlet]
67+
})
68+
export class TestElementWithOutletComponent extends BaseElementComponent<any> {}

0 commit comments

Comments
 (0)