I have modal on which I am searching location using google map services. I am getting error of TypeError: Cannot read properties of undefined (reading 'nativeElement')
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
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. Also moving autocomplete code block from ngOnInit
to 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
. 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
<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
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.
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.
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.
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. Access the native element in ngAfterViewInit() (of your new component). 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).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.