Custom component example for ionic4

I’m trying to use a custom component from this ionic3 example in ionic4: https://www.joshmorony.com/using-google-maps-and-geolocation-in-ionic-with-capacitor/

But I think i’m not adding it to the module correctly. I keep getting this error:

core.js:1673 ERROR Error: Uncaught (in promise): Error: Template parse errors:
'app-google-maps' is not a known element:
1. If 'app-google-maps' is an Angular component, then verify that it is part of this module.

app.module.ts

import { NgModule} from '@angular/core';

import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, RouteReuseStrategy, Routes } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { GoogleMapsComponent } from './google-maps/google-maps.component';

@NgModule({
  declarations: [AppComponent, GoogleMapsComponent ],
  entryComponents: [],
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent],
})
export class AppModule {
}

app.component.ts

import { Component, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { GoogleMapsComponent } from './google-maps/google-maps.component';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html'
})
export class AppComponent {
  constructor(
    private platform: Platform,
    private splashScreen: SplashScreen,
    private statusBar: StatusBar,
    private injector: Injector
  ) {
    this.initializeApp();

    // convert AppGoogleMaps to customElement
    const GoogleMapsElement = createCustomElement(GoogleMapsComponent, {injector} );
    // Register the custom element with the browser.
    customElements.define('app-google-maps', GoogleMapsElement);    
  }

  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
    });
  }
}

any suggestions?

I can get it to work if I add the GoogleMapsComponent to the HomePageModule

home.module.ts

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    RouterModule.forChild([
      {
        path: '',
        component: HomePage
      }
    ])
  ],
  declarations: [HomePage, 
    GoogleMapsComponent
  ],
})
export class HomePageModule {}

and remove the declaration from the AppModule

app.module.ts

@NgModule({
  declarations: [AppComponent, 
    // GoogleMapsComponent    # do not declare here
  ],
  entryComponents: [],
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

But why is this so? especially since the ionic generate component GoogleMaps put it in the AppModule?

2 Likes

you’ve saved my day! but if you use this approach to reuse the component in 2 pages, it failed by claiming a duplicate declaration, and suggest to declare it in app module or in another module dedicated for components.

I finally figured how do to it properly-- you need to export your Component to be able to import it elsewhere. Here’s an example–I just import this shared module in the XXX.module.ts of each page.

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
  ],
  declarations: [
    MarkerListComponent,
    MarkerGroupComponent, 
    MarkerItemComponent,
    GoogleMapsComponent, 
    DataURLPipe,
  ],
  entryComponents: [  ],
  exports: [
    MarkerListComponent,
    MarkerGroupComponent,
    MarkerItemComponent,
    GoogleMapsComponent, 
    PhotoswipeComponent,  
  ],
})
export class SharedComponentModule {}
1 Like

If you’ve the time, I would be interested to know what source-map-explorer has to say about your resulting app bundle, specifically how many copies of the google maps code there are.

That is an awesome utility. here’s what I got for my /www/main.js