如何在以编程方式检查 HTML 复选框元素之前正确等待其加载?
2020-04-22
346
我想在用户进入页面时动态激活一些复选框。为此,我将 HTML 复选框元素的 ID 保存在服务中。当用户进入页面时,将访问此服务并返回包含这些 ID 的数组。在每个循环中检查活动元素。
this.platform.ready().then(() => {
let checboxState = this.service.checboxState;
if (checboxState !== undefined && checboxState.length > 0) {
checboxState.forEach(checbox => {
let element = document.getElementById(checbox.id) as HTMLInputElement;
element.checked = true;
});
}
});
但我收到此错误:
Uncaught (in promise): TypeError: Cannot set property 'checked' of null
这可能表明 Javascript 函数在加载 DOM 之前触发。如果是这样,为什么
platform.ready()
不起作用?我也尝试过:
-
document.addEventListener("DOMContentLoaded",() => {}
-
window.onload = () => {}>
但没有成功。
我设法通过在函数前添加
setTimeout()
来使该函数正常工作,那么如何在触发 JS 函数之前正确等待 HTML 元素加载?
页面中的复选框由 *ngFor 函数加载。
2个回答
当复选框通过
*ngFor
循环添加到 DOM 时,为了得到通知:
-
为复选框元素分配一个模板引用变量(例如
#chk
) -
借助
ViewChildren
将复选框元素关联到QueryList
> -
在
ngAfterViewInit
中订阅QueryList.changes
可观察对象,并在回调中处理复选框列表。您还可以直接在ngAfterViewInit
中检查,以解决复选框元素已呈现的情况
<input type="checkbox" #chk *ngFor="let id of idList" [id]="id">
@ViewChildren("chk") private checkboxList: QueryList<ElementRef<HTMLInputElement>>;
...
ngAfterViewInit() {
// Check if the checkbox is already in the DOM
this.findCheckBoxWithId("chk36");
// Find the checkbox if rendered after a delay
this.checkboxList.changes.subscribe(() => {
this.findCheckBoxWithId("chk36");
});
}
findCheckBoxWithId(id) {
const checkbox = this.checkboxList.find(x => x.nativeElement.id === id);
...
}
请参阅 此 stackblitz 以获取演示
ConnorsFan
2020-04-22
或者,在 ConnorsFan 的答案 的基础上,使用可观察对象:
@ViewChildren('chk') private checkboxQueryList: QueryList<ElementRef<HTMLInputElement>>;
checkbox$: Observable<HTMLInputElement>;
...
ngAfterViewInit(): void {
this.checkbox$ = this.observableFromQueryListFind(
this.checkboxQueryList,
x => x.nativeElement.id === 'chk36',
);
}
...
observableFromQueryListFind<T>(
queryList: QueryList<T>,
fn: (item: T, index: number, array: T[]) => boolean,
): Observable<T> {
const item = queryList.find(fn);
if (item) {
return concat(
of(item),
queryList.changes
.pipe(
map((queryList: QueryList<T>) => queryList.find(fn)),
),
);
} else {
return queryList.changes
.pipe(
map((queryList: QueryList<T>) => queryList.find(fn)),
);
}
}
此答案代码未经测试,但基于工作代码库中 80-90% 相似的代码。
hlovdal
2023-03-31