How come a Google Maps API component functions properly even without using *NgIf, but fails to work when excluded in Angular 9?

I recently followed the guide provided in this discussion with success. The method outlined worked perfectly for loading search boxes using this component:

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');
    }
  }
}

However, I encountered an issue when attempting to use an *NgIf statement to load one of the boxes only when the component is rendered. This resulted in that particular searchbox failing to function and generating an uncaught promise exception.

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">

An error message was displayed in the console:

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

The root cause of this issue stemmed from my attempt to dynamically alter the Id of the input box. It appears that whenever an HTML element is bound to an Angular variable, the functionality is disrupted.

Answer №1

When querying the DOM in ngOnInit(), it may be too early in Angular's component lifecycle for the element to have been added. Even if the *ngIf condition is set to true, the element might not be immediately present in the DOM.

For tasks that require access to the DOM element, it is recommended to wait until a later stage in the component lifecycle, such as ngAfterViewInit().

Furthermore, a more Angular-friendly approach to obtaining a DOM element is by using @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);
}

Check out the DEMO here: https://stackblitz.com/edit/angular-2um7rp

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The jQuery carousel script is not functioning

Currently developing a jQuery slideshow for my website, and I stumbled upon a code that fits my requirements perfectly. I made some adjustments to the code from this source: . My specifications were that the code should be created from scratch, lightweight ...

Are cookies with the http_only attribute included in requests made through AJAX?

While browsing the web, I came across this interesting link However, it also mentioned at the bottom that This information may no longer be current. This got me thinking, can http_only cookies be transmitted with AJAX? And can AJAX responses set http_only ...

Is the Wrapper created by the combination of React, JavaScript Arrow functions, and Classes

I stumbled upon a website at: After implementing the solution successfully, I found myself puzzled by the javascript code. There was a snippet in the AnimatedWrapper.js class that caught my attention: const AnimatedWrapper = WrappedComponent => class ...

Can Next.js accommodate server-side redirection with internationalization?

I'm working on a small Next.js app that has pages accessible only to logged in users. To manage the authenticated routes, I created an HOC (withAuth) that handles redirection on the server side to prevent page flashing on the client side. Everything i ...

What could be causing the issue with running npx create-react-app my-first-app?

Encountered issues when attempting to execute npx create-react-app. Need assistance troubleshooting the error messages preventing the command from running. View Screenshot of Terminal with stacktrace Error: EPERM: operation not permitted, mkdir 'C:& ...

The Typescript decorator is unable to access the property type within its own scope

I am currently in the process of developing a dependency injector for use in my VUE js project. Recently, I created an Inject decorator with the intention of accessing a property type. It was functioning perfectly fine yesterday, but now it seems that som ...

Like button for Facebook located at the bottom of a static webpage

I am facing an issue with my web application where it does not scroll properly, especially when there is a Facebook button at the bottom. The behavior in Chrome and Firefox is inconsistent and causing some trouble. In Chrome, the div repositions correctly ...

Enhance the functionality of jqGrid by customizing key bindings for arrow and tab keys

In order to enhance my jqGrid functionality, I am seeking to implement the ability for users to press different keys for specific actions. For example, pressing Enter should save data (which is currently working fine), while pressing the left arrow key sho ...

Converting Background Images from html styling to Next.js

<div className="readyContent" style="background-image: url(assets/images/banner/banner-new.png);"> <div className="row w-100 align-items-center"> <div className="col-md-7 dFlex-center"> ...

Starting http-server in the background using an npm script

Is there a way to run http-server in the background using an npm script, allowing another npm script, like a Mocha test with jsdom, to make HTTP requests to http-server? To install the http-server package, use: npm install http-server --save-dev In your ...

Locate the index position of an element in one array based on a corresponding element in a

I am seeking a way to determine the index and group that an item belongs to within a parent json group. Is there a method for achieving this? I am willing to modify the json format if necessary. I made an attempt using JSON.stringify(), but it seems to be ...

Sending every piece of information to the URL may not be the most efficient approach, in my opinion

Lately, I have incorporated NodeJS into my Angular project and here is how I am currently implementing it: Node : app.get('/register/:username/:password', function(req, res){ db.collection('users').insertOne({ username: req ...

Having trouble with using findByIdAndUpdate and push in MongoDB?

As someone who is new to Mongodb, I have been using the findByIdAndUpdate function to update a document in my project. However, I noticed that it returns the old document instead of the updated one. Below is the code snippet of my function: exports.crea ...

Guide on reusing javascript to toggle between image sources

I have a simple website with buttons that, when clicked, change the image being displayed. However, I find myself repeating code for each button, and I'm wondering if there is a more efficient solution to this problem. Here is an example of what I cu ...

Display a delete icon when hovering over a Chip component from Material-ui

Recently, I've been exploring ways to implement the on-hover functionality for a chip. What I'm looking for is when I hover over a chip in an array of chips, it should display a delete icon. Below is the code snippet I've been working on: ...

Tips for using useState to update only the element that was clicked:

When I click the button to add a step to a chapter, it's adding a step to all chapters instead of just one. What mistake am I making? const example_chapters = [ { id: 1, title: 'Chapter 1'}, { id: 2, title: 'Chapter 2'}, ...

Close button for body

I have created a form that floats in the center of the screen On this form, I have included a button designed to close it However, I would like for the form to be closed anywhere on the screen when clicked with the mouse Here is my code: $(".offer-clo ...

Perform a task upon clicking the JavaScript menu

Implementing dropdown menu items using a text link with JavaScript and CSS. You can view a demo here. I am looking to trigger an action when each menu item is clicked. Currently, they are not behaving as expected. HTML: <span class="inline-dropdown- ...

Deactivate Mongoose connection in Node.js after completing tasks

Here is a mongoose script I have been using to connect to the local database and perform some operations. However, I am facing an issue with disconnecting the connection after use. const mongoose = require('mongoose'); const db = mongoose.connec ...

import types dynamically in TypeScript

One of the files I have is called MyFactory.ts. Here is its content: export type CommandFactory = () => string[] | undefined; export enum FactoryIds {commandFactory : 'commandFactory'} Now, my goal is to dynamically import this file into anot ...