Establishing the placement of map markers in Angular

Currently, I am in the process of developing a simple web application. The main functionality involves retrieving latitude and longitude data from my MongoDB database and displaying markers on a map, which is functioning correctly. However, the issue I'm facing is related to setting the colors of these markers. While I can achieve this by storing the URL of the marker PNG in the database, I am exploring options to dynamically change the marker color based on specific data from MongoDB. Presently, I have included a field named 'marker' in each MongoDB document containing a number ranging from 1 to 4, which determines the color of the corresponding marker.

This snippet showcases the component.ts setup:

import { Component, OnInit } from '@angular/core';
import { SchoolService } from '../school.service';
import { School } from '../School';

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.css']
 })

export class MapComponent implements OnInit {

  startLat = 35.782169;
  startLng = -80.793457;
  zoom = 7;
  greenMarker = 'http://www.google.com/intl/en_us/mapfiles/ms/micons/green-dot.png';
  yellowMarker = 'http://www.google.com/intl/en_us/mapfiles/ms/micons/yellow-dot.png';
  schools: School[] = [];

  constructor(private schoolService: SchoolService) { }

  ngOnInit() {
    this.getSchools();
    this.getIcon();
  }

  getSchools(): void {
    this.schoolService.getSchools()
      .subscribe((schoolList: School[]) => {
        this.schools = schoolList;
        console.log(this.schools);
      });
  }

  getIcon() {
    for (let i = 0; i <= this.schools.length; i++) {
      if (this.schools[i].marker === 1) {
        return this.greenMarker;
      } else {
        return this.yellowMarker;
      }
    }
  }
}

Below is the HTML markup:

 <div class="container">

  <ul class="legend">
    <li><span class="faster"></span>IPv6 Load Time ≤ IPv4</li>
    <li><span class="all-elements"></span>Fully IPv6 Accessible</li>
    <li><span class="reachable"></span>DNS AAA Record</li>
    <li><span class="DNS-AAAA"></span>Not IPv6 Accessible</li>
  </ul>

  <agm-map id="map" [latitude]="startLat" [zoom]="zoom" 
[longitude]="startLng">
    <agm-marker *ngFor="let school of schools; let i = index"
      [latitude]="school.lat" [longitude]="school.long" 
[iconUrl]="getIcon()">
      <agm-info-window>
        <h4>{{ school.name }}</h4>
        <p>lat: {{ school.lat }}</p>
        <p>long: {{ school.long }}</p>
      </agm-info-window>
    </agm-marker>
  </agm-map>
</div>

School.ts Schema:

export class School {
    name: string;
    lat: number;
    long: number;
    marker: number;
}

School Service Implementation:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class SchoolService {


  constructor(private http: HttpClient) { }

  getSchools() {
    return this.http.get('http://localhost:3000/get');
  }
}

Error log generated:

MapComponent_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property 'marker' of undefined
    at MapComponent.push../src/app/map/map.component.ts.MapComponent.getIcon (map.component.ts:38)
    at MapComponent.push../src/app/map/map.component.ts.MapComponent.ngOnInit (map.component.ts:25)
    at checkAndUpdateDirectiveInline (core.js:22099)
    at checkAndUpdateNodeInline (core.js:23363)
    ...

Answer №1

It seems like the issue lies within the template when attempting to call the "getIcon()" method. This function could be triggered before the subscription is completed.

To resolve this, you should modify your template and component code as shown below -

<agm-map id="map" [latitude]="startLat" [zoom]="zoom" 
[longitude]="startLng">
    <agm-marker *ngFor="let school of schools; let i = index"
      [latitude]="school.lat" [longitude]="school.long" 
[iconUrl]="getIcon(school)">
      <agm-info-window>
        <h4>{{ school.name }}</h4>
        <p>lat: {{ school.lat }}</p>
        <p>long: {{ school.long }}</p>
      </agm-info-window>
    </agm-marker>
  </agm-map>

getIcon(school) {

if(school) {
  if(school.marker === 1) {
  return this.greenMarker;
      } else {
        return this.yellowMarker;
      }
  }

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

Is it possible to import in TypeScript using only the declaration statement?

Is there a way to use a node module in TypeScript without explicitly importing it after compilation? For example: I have a global variable declared in a file named intellisense.ts where I have: import * as fs from 'fs'; Then in another file, ...

There appears to be an issue with the headers not being

Whenever I use HttpClient to send a request, I make sure to set the necessary headers. However, upon checking the network tab in Chrome, I noticed that these headers are not being properly set. Here is the code snippet: request(url: string, method: strin ...

The use of 'import ... =' is restricted to TypeScript files

Error: Oops! Looks like there's a hiccup in the code... 'import ... =' is exclusive to TypeScript files. Expecting '=' here. Don't forget the ';'. Unexpected keyword or identifier popping up! package.json ...

Adjusting the timeout for a particular operation according to its unique identifier

I am looking for a solution to call a method that posts an answer after an input change in my Angular project. I want to reset the timeout if another input change occurs to avoid multiple posts. Is there a smart way to achieve this? My project involves po ...

Ways to expand the width of mat-dialog-actions component in Angular 8

Is there a way to make the cancel and save buttons in the dialog window take up the entire available space? If anyone has any suggestions on how to achieve this, please let me know! ...

Error in AWS Cloud Development Kit: Cannot access properties of undefined while trying to read 'Parameters'

I am currently utilizing aws cdk 2.132.1 to implement a basic Lambda application. Within my project, there is one stack named AllStack.ts which acts as the parent stack for all other stacks (DynamoDB, SNS, SQS, StepFunction, etc.), here is an overview: im ...

Removing Angular Template space highlights in WebStorm can be done easily with a few simple steps

Is there a way to remove space highlights in Angular / TypeScript using WebStorm 2019? https://i.stack.imgur.com/vfudR.jpg Many thanks, Sean ...

Exploring the capabilities of renderOption within Material-UI's AutoComplete functionality

Hey there, I've been pondering a question lately and could really use some help. I've been trying to set up my autocomplete feature to display a label in the options while having a different value. After doing some research, I learned about usin ...

The Typescript compiler is throwing an error in a JavaScript file, stating that "type aliases can only be used in a .ts file."

After transitioning a react js project to react js with typescript, I made sure to move all the code to the typescript react app and added types for every necessary library. In this process, I encountered an issue with a file called HeatLayer.js, which is ...

Is the child constantly updating due to a function call?

Having difficulty navigating the intricacies where a child keeps re-rendering due to passing a function from the parent, which in turn references an editor's value in draftjs. function Parent() { const [doSomethingValue, setDoSomethingValue] = Re ...

Upgrading Angular from version 8 to 9: Dealing with Compilation Errors in Ivy Templates

After successfully upgrading my Angular application from version 8 to version 9 following the Angular Update Guide, I encountered some issues in the ts files and managed to resolve them all. In version 8, I was using the View Engine instead of Ivy, which ...

Running ngAfterViewInit() code in Angular should be done only after Inputs() have been initialized

Within a particular component, I have implemented some code in ngAfterViewInit: @Input public stringArray: string[]; public newArray: string[]; ngAfterViewInit() { this.newArray = this.stringArray.filter(x => x.includes('a')); } I placed ...

Adal TypeScript Document

Recently, I've been experimenting with the TypeScript version of adal.js. As part of my setup process, I'm referring to this link to install adal.ts. However, after executing the command: npm install adal-typescript --save a new "node_modules" ...

invoke the next function a different privateFunction within rxjs

I'm trying to figure out how to pass the resetPassword data to the _confirmToUnlock method in Typescript/RxJS. Here is my subscribe method: public invokeUnlockModal() { let resetPassword = { userName: this.user?.userName}; //i need to send this ...

Issue: Angular 2 is missing the runtime compiler component

In my Angular2 project, I utilized the compiler service to create a dynamic module and render it at runtime in the app. However, an issue arises when I run the command ng build --prod. The process completes without any errors, but upon hosting it on heroku ...

What issues arise from using ng-content within a web component?

I have a unique component structure for my website: <div (click)="popup.showAsComponent()"> <ng-content></ng-content> </div> Here is how I implement it: <my-web-component><button>Click!</button></my ...

The appearance of the Angular app undergoes a change following deployment using ng build

I have been working with Angular for several years now, but only recently delved into using Angular Material components in my latest project. I was pleased with how my layout turned out and ready to push it to production. However, after deployment, the com ...

Extract JSON values based on a given condition

I am working on a Typescript project that involves an array and a JSON object. I need to extract the value of a property from the object based on another property's value being in the array. Here is the array: let country: string[] = [ 'AR' ...

Encountering an npm package resolution error despite following all of the necessary requirements

error message: ERESOLVE Unable to resolve dependency Issues encountered while resolving: @ionic/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="52333c35273e332012657c667c60">[email protected]</a> Found: <a href ...

Determine parameter types and return values by analyzing the generic interface

I am currently working on a feature where I need to create a function that takes an interface as input and automatically determines the return types based on the 'key' provided in the options object passed to the function. Here is an example of ...