使用 renderer2 Angular 在按键时将字符包装在 span 元素中
Wrap a character in a span element on key press with renderer2 Angular
我有一个 contenteditable div,它会在用户按“@”时触发一个事件。
它所做的是将按下的 @ 字母包装在同一位置的自定义元素中。
这是代码
<div contenteditable="true" role="textarea" (keydown.@)= "onWrap()">
</div>
onWrap() {
setTimeout(() => {
const caretPosition = window.getSelection().getRangeAt(0);
const range = document.createRange();
range.setStart(caretPosition.commonAncestorContainer, caretPosition.startOffset - 1);
range.setEnd(caretPosition.commonAncestorContainer, caretPosition.endOffset );
const previousNode = (range.cloneContents().lastChild as HTMLElement);
const newWrap = this.renderer.createElement('my-custom-component');
//range.surroundContents(newWrap );
}, 10);
}
所以按@后可编辑的文本必须变成
<div contenteditable="true" role="textarea">
this is my editable content and i want to insert here <my-custom-component>@</my-custom-component> and the rest of the text
</div>
我想转换 <my-custom-component>
- 我目前正在使用 surroundContents,但不推荐使用它,自定义组件也没有改变。也许我必须使用 renderer.appendChild 但我不知道如何使用。
- 我正在使用超时,因为在按键时未检测到 @,我不想使用它。
如评论中所述,您可以利用 ComponentRendererFactory
并动态创建和附加组件。您需要的是注入所需的服务。 Injector
是解析组件工厂所必需的,ApplicationRef
是将组件附加到 DOM
constructor(
private injector: Injector,
private cfr: ComponentFactoryResolver,
private applicationRef: ApplicationRef
)
Define a dummy component :
@Component({
selector: "app-wrapper",
styleUrls: ["./wrapper.component.css"],
template: `
<span style="background-color:aqua">
x:
{{ innerText }}
</span>
`
})
export class WrapperComponent {
innerText: string;
}
Create component dynamically
const wrap = this.renderer.createElement("wrapper-container"); // this can be anything but it is required
const factory = this.cfr.resolveComponentFactory<WrapperComponent>(WrapperComponent);
const cmp = factory.create(this.injector, [], wrap); // attach your component into host element : `wrapper-container`
this.applicationRef.attachView(cmp.hostView); // attach component into DOM
const contents = range.extractContents(); // extract contents
cmp.instance.innerText = contents.textContent; // set components text
range.insertNode(wrap); // insert everything into range.
这里是 Stackblitz sample。
我有一个 contenteditable div,它会在用户按“@”时触发一个事件。 它所做的是将按下的 @ 字母包装在同一位置的自定义元素中。
这是代码
<div contenteditable="true" role="textarea" (keydown.@)= "onWrap()">
</div>
onWrap() {
setTimeout(() => {
const caretPosition = window.getSelection().getRangeAt(0);
const range = document.createRange();
range.setStart(caretPosition.commonAncestorContainer, caretPosition.startOffset - 1);
range.setEnd(caretPosition.commonAncestorContainer, caretPosition.endOffset );
const previousNode = (range.cloneContents().lastChild as HTMLElement);
const newWrap = this.renderer.createElement('my-custom-component');
//range.surroundContents(newWrap );
}, 10);
}
所以按@后可编辑的文本必须变成
<div contenteditable="true" role="textarea">
this is my editable content and i want to insert here <my-custom-component>@</my-custom-component> and the rest of the text
</div>
我想转换 <my-custom-component>
- 我目前正在使用 surroundContents,但不推荐使用它,自定义组件也没有改变。也许我必须使用 renderer.appendChild 但我不知道如何使用。
- 我正在使用超时,因为在按键时未检测到 @,我不想使用它。
如评论中所述,您可以利用 ComponentRendererFactory
并动态创建和附加组件。您需要的是注入所需的服务。 Injector
是解析组件工厂所必需的,ApplicationRef
是将组件附加到 DOM
constructor(
private injector: Injector,
private cfr: ComponentFactoryResolver,
private applicationRef: ApplicationRef
)
Define a dummy component :
@Component({
selector: "app-wrapper",
styleUrls: ["./wrapper.component.css"],
template: `
<span style="background-color:aqua">
x:
{{ innerText }}
</span>
`
})
export class WrapperComponent {
innerText: string;
}
Create component dynamically
const wrap = this.renderer.createElement("wrapper-container"); // this can be anything but it is required
const factory = this.cfr.resolveComponentFactory<WrapperComponent>(WrapperComponent);
const cmp = factory.create(this.injector, [], wrap); // attach your component into host element : `wrapper-container`
this.applicationRef.attachView(cmp.hostView); // attach component into DOM
const contents = range.extractContents(); // extract contents
cmp.instance.innerText = contents.textContent; // set components text
range.insertNode(wrap); // insert everything into range.
这里是 Stackblitz sample。