为什么 google 映射 API 组件在没有 *NgIf 的情况下也能工作,但如果被排除在外也能工作? Angular 9
Why will a google maps API component work without *NgIf but works if excluded? Angular 9
我尝试按照 中列出的步骤进行操作。它可以使用此组件加载搜索框:
map.component.html
<input id= 'box2' *ngIf="boxReady" class="controls" type="text" placeholder="Search Box">
<input id = 'box' class="controls" type="text" placeholder="Search Box">
map.component.ts
import {Component, Input, OnInit} from '@angular/core';
import {GoogleAPIService} from '../google-api.service';
declare var google: any;
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.scss'],
})
export class MapComponent implements OnInit {
@Input() boxIdVar: string;
// @Input() id: string;
boxReady = false;
constructor(private _google: GoogleAPIService){}
ngOnInit(): void {
if (typeof google !== 'undefined') {
console.log(google);
console.log('Map.NgInit');
console.log(this.boxIdVar);
this.boxReady = true;
let input = document.getElementById('box');
let originSearch = new google.maps.places.SearchBox(input);
input = document.getElementById('box2');
let dest = new google.maps.places.SearchBox(input);
}
else {
console.log('Google was undefined Map');
}
}
}
但是,如果我添加一个 *NgIf 语句,该语句仅在加载组件时才加载其中一个框,那么该搜索框将不再有效,并且我会收到未捕获的 promise 异常。
map.component.html
<input id= 'box2' *ngIf="boxReady" class="controls" type="text" placeholder="Search Box">
<input id = 'box' class="controls" type="text" placeholder="Search Box">
在控制台中发现错误:
ERROR Error: "Uncaught (in promise): TypeError: b is null
v$.prototype.o@https://maps.googleapis.com/maps-api-v3/api/js/40/5/places_impl.js:78:66
这一切都是因为我想动态改变输入框的Id。但它接缝时,只要 HTML 元素有一些 angular 绑定变量,功能就会中断。
您正在查询 ngOnInit()
中的 DOM。 Angular 将其添加到 DOM 的组件生命周期还为时过早。将 *ngIf
条件设置为真不会 立即 将其添加到 DOM.
相反,您应该 运行 任何在组件生命周期后期需要 DOM 元素的代码,在 ngAfterViewInit()
.
此外,获取 DOM 元素的更 "Angular" 方法是使用 @ViewChild()
.
<input *ngIf="boxReady" #box2 />
@ViewChild('box2') box2: ElementRef;
boxReady = false;
ngOnInit(): void {
this.boxReady = true;
const viewChild = this.box2 ? this.box2.nativeElement : null;
console.log('ngOnInit viewChild', viewChild); // null
}
ngAfterViewInit() {
const viewChild = this.box2.nativeElement;
console.log('ngAfterViewInit viewChild', viewChild);
}
我尝试按照
map.component.html
<input id= 'box2' *ngIf="boxReady" class="controls" type="text" placeholder="Search Box">
<input id = 'box' class="controls" type="text" placeholder="Search Box">
map.component.ts
import {Component, Input, OnInit} from '@angular/core';
import {GoogleAPIService} from '../google-api.service';
declare var google: any;
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.scss'],
})
export class MapComponent implements OnInit {
@Input() boxIdVar: string;
// @Input() id: string;
boxReady = false;
constructor(private _google: GoogleAPIService){}
ngOnInit(): void {
if (typeof google !== 'undefined') {
console.log(google);
console.log('Map.NgInit');
console.log(this.boxIdVar);
this.boxReady = true;
let input = document.getElementById('box');
let originSearch = new google.maps.places.SearchBox(input);
input = document.getElementById('box2');
let dest = new google.maps.places.SearchBox(input);
}
else {
console.log('Google was undefined Map');
}
}
}
但是,如果我添加一个 *NgIf 语句,该语句仅在加载组件时才加载其中一个框,那么该搜索框将不再有效,并且我会收到未捕获的 promise 异常。
map.component.html
<input id= 'box2' *ngIf="boxReady" class="controls" type="text" placeholder="Search Box">
<input id = 'box' class="controls" type="text" placeholder="Search Box">
在控制台中发现错误:
ERROR Error: "Uncaught (in promise): TypeError: b is null
v$.prototype.o@https://maps.googleapis.com/maps-api-v3/api/js/40/5/places_impl.js:78:66
这一切都是因为我想动态改变输入框的Id。但它接缝时,只要 HTML 元素有一些 angular 绑定变量,功能就会中断。
您正在查询 ngOnInit()
中的 DOM。 Angular 将其添加到 DOM 的组件生命周期还为时过早。将 *ngIf
条件设置为真不会 立即 将其添加到 DOM.
相反,您应该 运行 任何在组件生命周期后期需要 DOM 元素的代码,在 ngAfterViewInit()
.
此外,获取 DOM 元素的更 "Angular" 方法是使用 @ViewChild()
.
<input *ngIf="boxReady" #box2 />
@ViewChild('box2') box2: ElementRef;
boxReady = false;
ngOnInit(): void {
this.boxReady = true;
const viewChild = this.box2 ? this.box2.nativeElement : null;
console.log('ngOnInit viewChild', viewChild); // null
}
ngAfterViewInit() {
const viewChild = this.box2.nativeElement;
console.log('ngAfterViewInit viewChild', viewChild);
}