I'm new to angular and would like to ask if why I'm encountering Cannot read property 'setLng' of null?
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css']
})
export class MapComponent implements OnInit {
lat: number = 0;
lng: number = 0;
maptitle : string = '';
constructor() {
}
ngOnInit() {
this.initMap();
}
initMap() {
if (navigator) {
navigator.geolocation.watchPosition(this.showPos);
};
}
showPos(position) {
this.setLng(position.coords.latitude);
this.setLat(position.coords.latitude);
}
setLng(lng){
this.lng = lng;
}
setLat(lat){
this.lat = lat;
}
}
Error
ERROR TypeError: Cannot read property 'setLng' of null
at webpackJsonp.../../../../../src/app/map/map.component.ts.MapComponent.showPos (map.component.ts:26)
at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:388)
at Object.onInvoke (core.js:4749)
The issue is only due to scope.
Do Something like this :
initMap() {
if (navigator) {
navigator.geolocation.watchPosition(this.showPos.bind(this));
};
}
The problem is that watchPosition expects a callback and the scope is changed .
By binding this , the scope is always of the class.
Related
I got problem with angular component.
When I make my component with selector, it works as expected: execute httpget, and render photo with title.
But in console I got two errors:
ERROR TypeError: "_co.photo is undefined"
View_PhotoHolderComponent_0 PhotoHolderComponent.html:2
and
ERROR CONTEXT
...
PhotoHolderComponent.html:2:8
View_PhotoHolderComponent_0 PhotoHolderComponent.html:2
I got html:
<div class="photo-holder">
<h2>{{photo.title}}</h2>
<img src="{{photo.url}}">
</div>
and ts:
import { Component, OnInit } from '#angular/core';
import { Photo } from './photo'
import { PhotoDeliveryService } from '../photo-delivery-service.service'
#Component({
selector: 'app-photo-holder',
templateUrl: './photo-holder.component.html',
styleUrls: ['./photo-holder.component.css']
})
export class PhotoHolderComponent implements OnInit {
photo:Photo
constructor( private photoService : PhotoDeliveryService) {
}
ngOnInit() {
this.photoService.getRandomPhoto().subscribe((data: Photo) => this.photo = {...data})
}
}
and service :
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Photo } from './photo-holder/photo'
#Injectable({
providedIn: 'root'
})
export class PhotoDeliveryService {
value : Number
url : string
constructor(private http: HttpClient) {
this.url = "https://jsonplaceholder.typicode.com/photos/";
this.value = Math.floor(Math.random() * 10) + 1;
}
getRandomPhoto() {
return this.http.get<Photo>(this.getUrl())
}
getUrl(){
return this.url + this.value;
}
}
I suspect that could be made by binding property before query results was returned.
How can I rid off this problem, can I wait for this query, or this is different kind of problem ?
You are getting the error because before your service could resolve, the template bindings are resolved and at that time photo object is undefined.
first thing, you can initialize the photo object but then you might have to detect the changes using ChangeDetectorRef to reflect the value returned by the service.
photo:Photo = {
title:'',
url:''
};
constructor( private photoService : PhotoserviceService, private cdr:ChangeDetectorRef) {
}
ngOnInit() {
this.photoService.getRandomPhoto().subscribe((data: Photo) => {
this.photo = data;
this.cdr.detectChanges();
});
}
My code was working previously, displaying the data from an API correctly after using the reduce function.
I pulled my files from github on a new machine and suddenly I'm getting this error. Any help is greatly appreciated, as I've tried what I can to figure out what I've done wrong.
"ERROR TypeError: tickets.reduce is not a function
at SectionDashboardComponent.push../src/app/Sections/section-
dashboard/section-
dashboard.component.ts.SectionDashboardComponent.getTicketData (section-dashboard.component.ts:30)"
Here's the ts page where this error seems to be occurring:
import { Component, OnInit } from '#angular/core';
import { freshServiceService } from
'src/app/Services/freshservice.service';
import { Ticket } from 'src/app/Domain/Ticket';
#Component({
selector: 'app-section-dashboard',
templateUrl: './section-dashboard.component.html',
styleUrls: ['./section-dashboard.component.css']
})
export class SectionDashboardComponent implements OnInit {
constructor(private _freshServiceService: freshServiceService) { }
private ticketCounts: number[];
private ticketResponders: string[];
ngOnInit() {
this._freshServiceService.fetchTickets().subscribe
(
data =>
{
console.log(data);
this.getTicketData(data);
}
);
}
private getTicketData(tickets: Ticket[]): void {
const mappedTickets = tickets.reduce((x, y) => {
{x[y.responder_name] = x[y.responder_name] + 1 || 1};
return x;
}, []);
this.ticketResponders = Object.keys(mappedTickets);
this.ticketCounts = Object.values(mappedTickets);
console.log(this.ticketResponders);
console.log(this.ticketCounts);
}
}
I'm using 2GIS maps API based on Leaflet library. There are few functions in MapService (such as addMarkerToList()) which need to be called while clicking on map.
But there is a problem: using this.mapService.addMarkerToList will caught an error:
ERROR TypeError: Cannot read property 'addMarkerToList' of undefined
So I use const self = this construction to avoid this problem.
Can it be solved by another way?
map.component.ts
import {Component, OnInit} from '#angular/core';
import * as DG from '2gis-maps';
import {MapService} from '../../services/map/map.service';
let currentUserPos;
#Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css']
})
export class MapComponent implements OnInit {
constructor(private mapService: MapService) {}
ngOnInit() {
const self = this;
const map = DG.map('map', {
'center': [54.98, 82.89],
'zoom': 13,
'fullscreenControl': false
});
if (map) {
console.log('Map added');
}
map.locate()
.on('locationfound', function (e) {
currentUserPos = DG.marker([e.latitude, e.longitude]).addTo(map).bindLabel('Your location', {
static: true
});
const currentCenter = new DG.latLng(e.latitude, e.longitude);
console.log('Current position founded: ' + 'lat = ' + e.latitude + '; lng = ' + e.longitude);
map.setView(currentCenter, 16);
});
map.on('click', function (e) {
const marker = DG.marker([e.latlng.lat, e.latlng.lng]);
marker.addTo(map);
marker.on('click', function() {
marker.remove(map);
self.mapService.deleteMarkerFromList(e.latlng.lat, e.latlng.lng);
});
console.log('Marker after adding:' + marker.getLatLng());
self.mapService.addMarkerToList(e.latlng.lat, e.latlng.lng);
});
}
}
I have problem to fit my pushpin custom template into angular component.
My component:
import { Component, AfterViewInit } from '#angular/core';
#Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.scss']
})
export class MapComponent implements, AfterViewInit {
#ViewChild('myMap') myMap;
map: any;
infoboxClick;
infoboxTemplate = `<div id="infoboxText" class="custom-infobox">
<span class ="close-sighn" onclick="closeCustomInfoBox()">x</span>
{description}
</div>`;
constructor(private dataService: MapService) {
}
ngAfterViewInit() {
this.getMap();
}
getMap() {
if ((window as any).Microsoft && (window as any).Microsoft.Maps) {
this.map = new (window as any).Microsoft.Maps.Map(document.getElementById('mapId'), {
credentials: ''
});
var pushpin = new (window as any).Microsoft.Maps.Pushpin(map.getCenter(), null);
(window as any).Microsoft.Maps.Events.addHandler(pushpin, 'click', (args) => {
this.infoboxClick.setOptions({
location: args.target.getLocation(),
htmlContent: this.infoboxTemplate.replace('{description}', 'Some test description'),
visible: true
});
});
map.entities.push(pushpin);
} else {
setTimeout(() => { this.getMap() }, 1000);
}
}
closeCustomInfoBox() {
this.infoboxClick.setOptions({
visible: false
});
}
}
My view:
<div #myMap id="mapId" class="map-container"></div>
In infoboxTemplate I have function 'closeCustomInfoBox()', which should close infobox.
1) How I can call that function from my angular component?
2) I need to get proper angular scope if I call it how I can get approach to my 'infoboxClick' variables?
If you mean you want to access closeCustomInfoBox() function and infoboxClick variable from the parent component.
Check this
https://angular.io/guide/component-interaction#parent-interacts-with-child-via-local-variable
I have a case when I am using component in component. By accessing properties of child component via #ViewChild, I am getting undefined for methods in child component.
// Parent component
declare var google: any;
#Component({
selector: 'app-map',
templateUrl: `
<div id="map"></div>
<app-context-menu></app-context-menu>`,
styleUrls: ['./map.component.css'],
providers: [CitiesService],
})
export class MapComponent implements AfterViewInit {
#ViewChild(ContextMenuComponent) contextMenu: ContextMenuComponent;
user: UserInterface;
city: any;
map: any;
constructor(
private userStorage: UserStorage,
private citiesService: CitiesService,
private theMap: TheMap,
) {}
ngAfterViewInit() {
this.findUserCityCoords();
}
inittializeMap(mapOpts) {
let mapProps = {
center: new google.maps.LatLng(mapOpts.lat, mapOpts.lng),
zoom: mapOpts.zoom,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
let map = new google.maps.Map(document.getElementById('map'), mapProps);
let menu = this.contextMenu;
map.addListener('rightclick', (e) => {
console.log('map', this);
console.log('menu', this.contextMenu);
this.contextMenu.open(e);
});
}
findUserCityCoords() {
let userCity = this.userStorage.getFromStorage().city;
this.citiesService.getCityConfig()
.subscribe(cities => {
cities.forEach(city => {
if (city.name === userCity) this.inittializeMap(city.center);
});
});
}
From this class when 'map event listener' calls 'menu.open(e);' the context changes and inside child component, the methods of child component are not available. To call i.e. 'this.draw()' method.
// Child component
import { Component, OnInit, ElementRef, AfterViewInit } from
'#angular/core';
import { TheMap } from '../../services/mapServices/TheMap';
import { Marker } from '../../services/mapServices/marker.service';
declare var google: any;
#Component({
selector: 'app-context-menu',
templateUrl: './context-menu.component.html',
styleUrls: ['./context-menu.component.css']
})
export class ContextMenuComponent {
overlay;
el;
constructor(
private theMap: TheMap,
private marker: Marker,
private elementRef: ElementRef
) {
this.overlay = new google.maps.OverlayView();
}
ngAfterViewInit() {}
open(e) {
let map = this.theMap.getMap();
this.overlay.set('position', e.latLng);
this.overlay.setMap(map);
this.draw(); // <---- Here, this.draw() is not a function
// So I can access properties from constructor but not this.draw() and other methods of this class
};
draw() {
// ....
}
How can I properly implement google's map 'rightclick' event listener (probably with 'bind') to use my child's component methods. Thanks
Not sure I understand the question but () => (arrow function) might be what you're looking for
map.addListener('rightclick', (e) => {
console.log('map', this);
console.log('menu', menu);
this.contextMenu.open(e);
});