问题
I'm trying to access a ngSwitchCase view using @ViewChild and ElementRef to load a google map in my Ionic 3 app. I understand the ngSwitch creates its own scope but is it not accessible in anyway so I can load the map from google to the #map id="map" div in the mapView ngSwitchCase?
page.ts
//the import
import { ElementRef, ViewChild } from '@angular/core';
@Component({
selector: 'page-views',
templateUrl: 'views.html'
})
export class ViewsPage {
//the attribute in the export class
@ViewChild('map') mapElement : ElementRef;
views: string = "listView";
constructor(public navCtrl: NavController) {}
//the functions
ionViewDidLoad(){
this.loadMap();
}
loadMap(){
this.geolocation.getCurrentPosition().then((position) => {
let latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
// initializing map attributes
let mapOptions = {
center: latLng,
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);
});
}
}
page.html
<ion-toolbar>
<ion-segment [(ngModel)]="views">
<ion-segment-button value="mapView">
Map
</ion-segment-button>
<ion-segment-button value="listView">
List
</ion-segment-button>
</ion-segment>
</ion-toolbar>
<ion-content padding>
<div [ngSwitch]="views">
<ion-list *ngSwitchCase="'mapView'">
<ion-item>
<div #map id="map"></div>
</ion-item>
</ion-list>
<ion-list *ngSwitchCase="'listView'">
//other stuff
</ion-list>
</div>
</ion-content>
回答1:
ngSwitch creates and destroys the respective DOM element dynamically. Since you start your default view initialized to list view with
views: string = "listView";
the ion-list which is
<ion-list *ngSwitchCase="'mapView'">
does not exist in DOM. Consequently, the div with map, which is child of ion-list does not exist. Hence mapElement : ElementRef
is null. Its possible that if you start with default segment view with map like
views: string = "mapView";
your code might run and create the map for once. Just try it. It works for me. Note that on switching segments the map is destroyed and may not be created again since your loadMap()
only runs one time.
At this point, you have two options.
Instead of ngSwitch (which creates/destroys elements), use show/hide Map and List.
page.scss
.hide { display: none !important; }
page.html
<ion-content padding> <div #map id="map" [ngClass]="{ 'hide': views != 'mapView' }"></div> <div [ngClass]="{ 'hide': views != 'listView' }"> <ion-list > //other stuff </ion-list> </div> </ion-content>
Have a tabs component with a Map tab and a List tab.
page.ts
import { ElementRef, ViewChild } from '@angular/core'; import { ListPage } from '../list/list'; import { MapPage } from '../map/map'; @Component({ selector: 'page-views', templateUrl: 'views.html' }) export class ViewsPage { views: string = "listView"; tab1Root = MapPage; tab2Root = ListPage; constructor(public navCtrl: NavController) {} }
page.html
<ion-content> <ion-tabs> <ion-tab [root]="tab1Root" tabTitle="Map" tabIcon="map"></ion-tab> <ion-tab [root]="tab2Root" tabTitle="List" tabIcon="list"></ion-tab> </ion-tabs> </ion-content>
map.ts
. . export class MapPage { @ViewChild('map') mapElement : ElementRef; constructor(){} ionViewDidLoad(){ this.loadMap(); } loadMap(){ //stuff here } }
Also, I noticed that you are creating a list of maps with
<ion-list *ngSwitchCase="'mapView'">
<ion-item>
<div #map id="map"></div>
</ion-item>
</ion-list>
Don't you want just one map? Shouldn't this be like
<div [ngSwitch]="views">
<div #map id="map" *ngSwitchCase="'mapView'"></div>
<ion-list *ngSwitchCase="'listView'">
.
.
来源:https://stackoverflow.com/questions/43745022/loading-map-to-ngswitch-child-scope-using-elementref-in-ionic