[英]Angular 12: ViewChild not working for ElementRef inside modals
I have modal on which I am searching location using google map services.我有模式,我正在使用谷歌 map 服务搜索位置。 I am getting error of
TypeError: Cannot read properties of undefined (reading 'nativeElement')
我收到
TypeError: Cannot read properties of undefined (reading 'nativeElement')
HTML HTML
<input
type="text"
[ngClass]="{ error_border: submitted && f.location.errors }"
class="form-control"
formControlName="location"
[readonly]="viewMode"
(keydown.enter)="$event.preventDefault()"
placeholder="Search Location"
autocorrect="off"
autocapitalize="off"
spellcheck="off"
#search
/>
TS TS
export class ListComponent implements OnInit, AfterViewInit {
dbLocation:any;
latitude!: number;
longitude!: number;
zoom!: number;
address!: string;
private geoCoder:any;
searchFlag:boolean = false;
@ViewChild('search' , { static: true }) public searchElementRef!: ElementRef ;
ngOnInit(): void {
}
ngAfterViewInit() {
//----------autocomplete code block------------
//load Places Autocomplete
this.mapsAPILoader.load().then(() => {
// this.setCurrentLocation();
this.geoCoder = new google.maps.Geocoder;
let autocomplete = new google.maps.places.Autocomplete(this.searchElementRef.nativeElement);
autocomplete.addListener("place_changed", () => {
this.ngZone.run(() => {
//get the place result
let place: google.maps.places.PlaceResult = autocomplete.getPlace();
//verify result
if (place.geometry === undefined || place.geometry === null) {
return;
}
//set latitude, longitude and zoom
this.latitude = place.geometry.location.lat();
this.longitude = place.geometry.location.lng();
this.getAddress(this.latitude, this.longitude);
this.zoom = 15;
this.searchFlag = true;
});
});
});
//----------autocomplete code block------------
}
}
I have tried adding { static: true }
to viewChild.我尝试将
{ static: true }
添加到 viewChild。 Also moving autocomplete code block from ngOnInit
to ngAfterViewInit
.还将自动完成代码块从
ngOnInit
移动到ngAfterViewInit
。 Also adding timeout for autocomplete code block.还为自动完成代码块添加超时。 But still giving that error.
但仍然给出那个错误。
It does not give error if input field is not on modal and autocomplete code block in ngOnInit
.如果输入字段不在
ngOnInit
的模态和自动完成代码块上,它不会给出错误。 But I have form on modal in which I have that input field of location.但是我有模态表单,其中有位置输入字段。 There it is giving error.
它在那里给出错误。
I am not able to figure it out which combination of code will work.我无法弄清楚哪种代码组合会起作用。 How can I resolve that error?
我该如何解决该错误?
Please help and guide.请帮助和指导。
Edit modal HTML编辑模态 HTML
<ng-template #formModal let-modal>
<div class="modal-header">
<h5 class="modal-title" id="modal-basic-title">
Form
</h5>
<button
type="button"
class="close"
aria-label="Close"
(click)="modal.dismiss('Cross click')"
>
<span aria-hidden="true">
<i class="fas fa-times"></i>
</span>
</button>
</div>
<div class="modal-body">
<form [formGroup]="form">
<div class="row edit_profile">
<div class="col-sm-12">
<div class="form-group">
<label>Name<b style="color: red" *ngIf="!viewMode">*</b></label>
<input
type="text"
[ngClass]="{ error_border: submitted && f.headline.errors }"
formControlName="headline"
class="form-control"
[readonly]="viewMode"
/>
<div *ngIf="submitted && f.headline.errors" class="text-danger">
<div *ngIf="f.headline.errors.required">
name is required
</div>
</div>
</div>
</div>
<div class="col-sm-7">
<div class="form-group">
<label for="location">Location <b style="color: red" *ngIf="!viewMode">*</b></label>
<div class="custome_input icons date_icon">
<i class="fas fa-map-marker-alt"></i>
<input
type="text"
[ngClass]="{ error_border: submitted && f.location.errors }"
class="form-control"
formControlName="location"
[readonly]="viewMode"
(keydown.enter)="$event.preventDefault()"
placeholder="Search Location"
autocorrect="off"
autocapitalize="off"
spellcheck="off"
#search
/>
</div>
<div *ngIf="submitted && f.location.errors" class="text-danger">
<div *ngIf="f.location.errors.required">Location is required</div>
</div>
</div>
</div>
<div class="form-group btn-group mb-0" *ngIf="!viewMode">
<button
[disabled]="loading"
class="btn"
(click)="onSubmitForm()"
>
<span
*ngIf="loading"
class="spinner-border spinner-border-sm mr-1"
></span>
Save
</button>
</div>
</form>
</div>
</ng-template>
TS of opening modal打开模态的TS
open(content) {
this.listModalRef = this.modalService.open(content,{ size: 'lg', backdrop: 'static' });
this.listModalRef.result.then((result) => {
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
});
setTimeout(() => {
//load Places Autocomplete
this.mapsAPILoader.load().then(() => {
// this.setCurrentLocation();
this.geoCoder = new google.maps.Geocoder;
let autocomplete = new google.maps.places.Autocomplete(this.searchElementRef.nativeElement);
autocomplete.addListener("place_changed", () => {
this.ngZone.run(() => {
//get the place result
let place: google.maps.places.PlaceResult = autocomplete.getPlace();
//verify result
if (place.geometry === undefined || place.geometry === null) {
return;
}
//set latitude, longitude and zoom
this.latitude = place.geometry.location.lat();
this.longitude = place.geometry.location.lng();
this.getAddress(this.latitude, this.longitude);
this.zoom = 15;
this.searchFlag = true;
});
});
});
}, 0)
}
First, you should remove { static: true }
, else searchElementRef
will always be undefined.首先,您应该删除
{ static: true }
,否则searchElementRef
将始终未定义。
Next change you would need to do, is to move this.mapsAPILoader.load().then(() => {... }
logic from ngAfterViewInit
to a method wherein you are sure that the modal has been initialized. If you are using any library component (for modal) and if it provides an event (maybe onShown
or show
or whatever) to identify modal initialization, then you can put your logic there.您需要做的下一个更改是将
this.mapsAPILoader.load().then(() => {... }
逻辑从ngAfterViewInit
到您确定模态已初始化的方法。如果您使用任何库组件(用于模态)并且如果它提供了一个事件(可能onShown
或show
或其他)来识别模态初始化,那么您可以将逻辑放在那里。
In short, you need to ensure that the modal is initialized before this.mapsAPILoader.load()
promise is resolved, else you will always get searchElementRef
as undefined.简而言之,您需要确保在
this.mapsAPILoader.load()
promise 解析之前初始化模态,否则您将始终将searchElementRef
视为未定义。
put your code located inside your modal -> in a new component.将您的代码放在您的模态中-> 在一个新组件中。
In this new component you can use @ViewChild to get an element value or native html element.在这个新组件中,您可以使用 @ViewChild 获取元素值或原生 html 元素。 Access the native element in ngAfterViewInit() (of your new component).
在 ngAfterViewInit() (您的新组件)中访问本机元素。 It won't be undefined.
它不会是未定义的。
If you want to communicate with the parent component (component which holds the modal), use @Input/@Output, or use the ngrxStore (dispatch actions).如果您想与父组件(包含模态的组件)通信,请使用@Input/@Output,或使用ngrxStore(调度操作)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.