我正在尝试在highlight()
上调用此ngOnInit
,但出现此错误:ERROR TypeError: Cannot read property 'innerHTML' of null
。
在ngOninit
中,我有
this.annotationSub = this.annotationService
.getWordUpdateListenerTwo()
.subscribe((theHardWords: ComplexWord[]) => {
this.thewords = [];
this.theHardWords = theHardWords;
this.theHardWords.map(word => {
this.thewords.push(word.word);
this.wordWithAnnotation.push(word);
});
});
this.postsSub = this.postsService
.getPostUpdateListenerTwo()
.subscribe((posts: Post[]) => {
this.posts = posts;
this.posts.map(post => {
if (post.id === this.id) {
this.postIWant = post.fileText;
}
});
});
this.highlight(this.thewords);
这会挑选出帖子,然后显示如下:
我的HTML:
<div id="scrollable">
{{ postIWant }}
</div>
这是给我带来问题的highlight
函数,如果在文档加载按钮后调用此highlight
函数,它可以正常工作,但是如果我在{{ 1}}没有足够的时间来填充innerHTML,因此会引发错误。
我尝试使用ngOnInit
,但即使这样也没有足够的时间。以下是ngAfterViewInit(): void {}
函数。
highlight
如前所述,如果我加载页面并按一个按钮来触发highlight(words) {
const high = document.getElementById('scrollable');
const paragraph = high.innerHTML.split(' ');
const res = [];
paragraph.map(word => {
let t = word;
if (words.indexOf(word) > -1) {
t =
'<a class="clickable" style="background-color: yellow; text-decoration: underline;">' +
word +
'</a>';
}
res.push(t);
});
high.innerHTML = res.join(' ');
const elementsToMakeClickable = document.getElementsByClassName(
'clickable'
);
const elementsToMakeClickableArray = Array.from(elementsToMakeClickable);
elementsToMakeClickableArray.map(element => {
element.addEventListener('click', this.viewAnnotation.bind(this));
});
document.getElementById('btnHighLight').style.visibility = 'visible';
}
,它可以工作,但是我希望它运行该功能并突出显示单词,而无需我点击任何东西。有人有什么想法吗?谢谢!
(我正在使用Angular)。
答案 0 :(得分:2)
我可以看到您没有正确同步观察对象。我宁愿结合来自annotationService
和postsService
的可观察物。然后订阅并执行this.highlight(this.thewords);
。
以下是示例(在RxJS 6中):
const annotation$ = this.annotationService.getWordUpdateListenerTwo();
const posts$ = this.postsService.getPostUpdateListenerTwo();
annotation$.pipe(combineLatest(posts$, (annotations, posts) => ({annotations, posts}))).subscribe((annotations, posts) => {
// Do your logic here and after execute highlight()
this.highlight(thewords);
});
在上面的示例中,我组合了annotation$
和posts$
,这意味着订阅将在最新的可观察对象上执行。然后,我猜测您将执行所需的逻辑,最后可以执行highlight()
。
但是,上述方法不能确保在合并的可观察完成之前加载scrolable
div。要侦听特定DOM元素上的更改,可以使用MutationObserver
API并创建可添加到scrollable
div中的自定义指令。请参阅以下文章Listening to DOM Changes Using MutationObserver in Angular。
您也可以尝试通过ViewChild访问HTML。请在以下stackoverflow问题中查看更多信息:How can I select an element in a component template?
答案 1 :(得分:2)
您的document.getElementById('scrollable');
调用返回空值。
这就是为什么您不应该与Angular中的DOM交互的原因。 Angular完全解耦了它,并为您提供了一个与之交互的API。
在解析了组件的ngOnInit
和Input
之后,调用 Outputs
。一旦附加了视图模板并且解析了模板变量,就会调用ngAfterViewInit
。
有很多方法可以通过Angular而不是通过DOM查询来获取元素,但是这里没有必要。
只需将其绑定到标记中即可
component.html:
<div id="scrollable">
<a class="clickable inline-styling-is-bad" style="background-color: yellow; text-decoration: underline;">
{{ postIWant }}
</a>
</div>
如果您需要基于数组的一系列重复元素,这似乎很明显,但是只需使用*ngFor
。
您的“可观察流”也存在一些问题,但这超出了本主题的范围。