[ionic 4] EmailComposer Plugin TypeError: Object(...)

#1

I’m getting the following error when I try to use the EmailComposer plugin on my ionic 4 app. I followed the installation and usage instructions from this page.

What am I missing?

core.js:14597 ERROR Error: Uncaught (in promise): TypeError: Object(...) is not a function
TypeError: Object(...) is not a function
    at index.js:202
    at Module../node_modules/@ionic-native/email-composer/index.js (index.js:306)
    at __webpack_require__ (bootstrap:83)
    at Module../src/app/pages/submenu/submenu.ts (pages-submenu-submenu-module.js:1723)
    at __webpack_require__ (bootstrap:83)
    at Module../src/app/pages/submenu/submenu.module.ts (pages-submenu-submenu-module.js:1657)
    at __webpack_require__ (bootstrap:83)
    at $_lazy_route_resource lazy namespace object:56
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:388)
    at Object.onInvoke (core.js:16156)
    at resolvePromise (zone.js:814)
    at resolvePromise (zone.js:771)
    at zone.js:873
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
    at Object.onInvokeTask (core.js:16147)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
    at drainMicroTaskQueue (zone.js:595)
#2

Hello,
what I am missing is related code.

Best regards, anna-liebt

#3

@anna_liebt Here’s the related code.

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { HttpClientModule, HttpClient} from '@angular/common/http';

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

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

import { TranslateModule, TranslateLoader } from "@ngx-translate/core";
import { TranslateHttpLoader } from '@ngx-translate/http-loader';

// The translate loader needs to know where to load i18n files
// in Ionic's static asset pipeline.
export function setTranslateLoader(http: HttpClient) {
  return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule, 
    IonicModule.forRoot(), 
    AppRoutingModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: (setTranslateLoader),
        deps: [HttpClient]
      }
    }),
    HttpClientModule
  ],
  providers: [
    StatusBar,
    SplashScreen,
    EmailComposer,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

submenu.ts

import { Component } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { EmailComposer } from '@ionic-native/email-composer';
import { Plugins } from '@capacitor/core';

const { Browser } = Plugins;

export interface Submenu {
  title: string;
  description: string;
  category: string;
  icon: string;
  order: string;
  type: string;
}

@Component({
  selector: 'page-submenu',
  templateUrl: 'submenu.html',
  styleUrls: ['submenu.scss']
})

export class SubMenuPage {

  title: string;
  animation: string;
  submenuData: Submenu[];
  filteredData: Submenu[];
  category: string;
  hcolor: string;
  values: any;

  constructor(
    public router: Router,
    public activatedRoute: ActivatedRoute,
    public translate: TranslateService,
    private emailComposer: EmailComposer) {

    // default header color if none selected
    this.hcolor = "primary";

    // get active category
    this.category = this.activatedRoute.snapshot.paramMap.get('catid');
    
    // translate menu items and assign color based on category
    translate.get(["PROFILE_TITLE","ORDERS_TITLE","ALERTS_TITLE","CONTACTUS_TITLE","PRODUCT_LEARNING_TITLE", "REGULATORY_TITLE","LIST_SUBMENU_TITLE"])
    .subscribe((values) => {
      this.values = values;

      // Dynamic background color
      switch(this.category) { 
        case 'PROFILE': { 
          this.hcolor = 'purple';
          this.title = this.values.PROFILE_TITLE;
          break; 
        } 
        case 'ORDERS': { 
          this.hcolor = 'orange';
          this.title = this.values.ORDERS_TITLE;
          break; 
        }
        case 'ALERTS': { 
          this.hcolor = 'red';
          this.title = this.values.ALERTS_TITLE;
          break; 
        }
        case 'CONTACTUS': { 
          this.hcolor = 'blue';
          this.title = this.values.CONTACTUS_TITLE;
          break; 
        }
        case 'LEARNING': { 
          this.hcolor = 'yellow';
          this.title = this.values.PRODUCT_LEARNING_TITLE;
          break; 
        }
        case 'REGULATORY': { 
          this.hcolor = 'green';
          this.title = this.values.REGULATORY_TITLE;
          break; 
        } 
        default: { 
          this.hcolor = 'primary';
          this.title = this.values.LIST_SUBMENU_TITLE;
          break; 
        } 
      }
      
    });

    this.submenuData = [
      {title: 'CONTACT_INFO_TITLE', description: '', category: 'PROFILE', icon: 'fa fa-user', order: '1', type: 'page'},
      {title: 'INSURANCE_TITLE', description: '', category: 'PROFILE', icon: 'fa fa-user', order: '2', type: 'page'},
      {title: 'DOCTOR_TITLE', description: '', category: 'PROFILE', icon: 'fa fa-user', order: '3', type: 'page'},
      {title: 'EMERGENCY_CONTACTS_TITLE', description: '', category: 'PROFILE', icon: 'fa fa-user', order: '4', type: 'page'},
      {title: 'DOCUMENTS_TITLE', description: '', category: 'PROFILE', icon: 'fa fa-user', order: '5', type: 'page'},
      {title: 'EQUIPMENT_TITLE', description: '', category: 'PROFILE', icon: 'fa fa-user', order: '6', type: 'page'},
      {title: 'BILLING_TITLE', description: '', category: 'PROFILE', icon: 'fa fa-user', order: '7', type: 'page'},

      {title: 'TRACK_ORDER_TITLE', description: '', category: 'ORDERS', icon: 'fa fa-cart-plus', order: '1', type: 'page'},
      {title: 'NEXT_ORDER_TITLE', description: '', category: 'ORDERS', icon: 'fa fa-cart-plus', order: '2', type: 'page'},

      {title: 'ORDER_ALERTS_TITLE', description: '', category: 'ALERTS', icon: 'fa fa-clock-o', order: '1', type: 'page'},
      {title: 'CATHING_ALERTS_TITLE', description: '', category: 'ALERTS', icon: 'fa fa-clock-o', order: '2', type: 'page'},
      {title: 'PRESCRIPTION_ALERTS_TITLE', description: '', category: 'ALERTS', icon: 'fa fa-clock-o', order: '3', type: 'page'},
      {title: 'FEEDING_ALERTS_TITLE', description: '', category: 'ALERTS', icon: 'fa fa-clock-o', order: '4', type: 'page'},

      {title: 'SCHEDULE_CALL_TITLE', description: '', category: 'CONTACTUS', icon: 'fa-id-card-o', order: '1', type: 'action'},
      {title: 'CALL_NOW_TITLE', description: '', category: 'CONTACTUS', icon: 'fa-id-card-o', order: '2', type: 'action'},
      {title: 'TEXT_NOW_TITLE', description: '', category: 'CONTACTUS', icon: 'fa-id-card-o', order: '3', type: 'action'},
      {title: 'EMAIL_NOW_TITLE', description: '', category: 'CONTACTUS', icon: 'fa-id-card-o', order: '4', type: 'action'},

      {title: 'LEARN_FEEDING_PUMPS_TITLE', description: '', category: 'LEARNING', icon: 'fa-graduation-cap', order: '1', type: 'browser'},
      {title: 'LEARN_WOUND_CARE_TITLE', description: '', category: 'LEARNING', icon: 'fa-graduation-cap', order: '2', type: 'browser'},
      {title: 'LEARN_INCONTINENCE_TITLE', description: '', category: 'LEARNING', icon: 'fa-graduation-cap', order: '3', type: 'browser'},
      {title: 'LEARN_UROLOGY_TITLE', description: '', category: 'LEARNING', icon: 'fa-graduation-cap', order: '4', type: 'browser'},
      {title: 'LEARN_RESOURCES_TITLE', description: '', category: 'LEARNING', icon: 'fa-graduation-cap', order: '5', type: 'browser'},

      {title: 'MEDICARE_SUPPLIER_STANDARD_TITLE', description: '', category: 'REGULATORY', icon: 'fa fa-gavel', order: '1', type: 'browser'},
      {title: 'WARRANTY_INFORMATION_TITLE', description: '', category: 'REGULATORY', icon: 'fa fa-gavel', order: '2', type: 'browser'},
      {title: 'REGULATORY_CONTACTS_TITLE', description: '', category: 'REGULATORY', icon: 'fa fa-gavel', order: '3', type: 'browser'}
    ];

    // Filter by category
    this.filteredData = this.submenuData.filter(
      submenu => submenu.category === this.category
    )

  }

  ionViewWillEnter() {
    this.animation = 'fade-in-bottom';
  }

  openPage(menu: any) {
    if (menu.type === 'browser') {
      this.doBrowser(menu);
    } else if (menu.type === 'action') {
      this.doAction(menu);
    } else {
      this.doPage(menu);
    }
  }

  menu() {
    this.router.navigateByUrl('/app/tabs/menu');
  }

  async doBrowser(menu: any) {
    if (menu.title === 'MEDICARE_SUPPLIER_STANDARD_TITLE') {
      await Browser.open({ url: 'https://google.com' });
    }
    if (menu.title === 'WARRANTY_INFORMATION_TITLE') {
      await Browser.open({ url: 'https://google.com' });
    }
    if (menu.title === 'REGULATORY_CONTACTS_TITLE') {
      await Browser.open({ url: 'https://google.com' });
    }
  }

  async doAction(menu: any) {
    if (menu.title === 'SCHEDULE_CALL_TITLE') {
      //await window.open('tel:800.888.8888');
    }
    if (menu.title === 'CALL_NOW_TITLE') {
      await window.open('tel:800.888.8888');
    }
    if (menu.title === 'TEXT_NOW_TITLE') {
      //await window.open('tel:800.888.8888');
    }
    if (menu.title === 'EMAIL_NOW_TITLE') {
      //await window.open('tel:800.888.8888');
    }
  }

  doPage(menu: any) {
    console.log('page here', menu);
  }
  
  contactSupport() {
    let email = {
      to: 'support@test.com',
      subject: 'I need support',
      body: 'I have a problem with the app and I need support...',
      isHtml: true
    }
    this.emailComposer.open(email);
  }

}

#4

hello,

I see imports with …/ngx, so I assume you are using capacitor. In that case you need also the same with email composer

import { EmailComposer } from '@ionic-native/email-composer/ngx';

contactSupport I haven’t tested, but looks good.

Best regrads, anna-liebt

#5

The …/ngx import doesn’t exist for EmailComposer

import { EmailComposer } from '@ionic-native/email-composer/ngx';
#6

After creating a brand new ionic 4 app and adding the EmailComposer plugin, I was able to confirm that this is a bug. I submitted a bug report already.

#7

Hello,
take a look to your package.json. Is your native email composer on a 5.x.x Version? If it is on 4 please update it to a version like the other native plugins have for example

"@ionic-native/core": "5.0.0-beta.21",
    "@ionic-native/email-composer": "^5.0.0-beta.21",
    "@ionic-native/splash-screen": "5.0.0-beta.21",
    "@ionic-native/status-bar": "5.0.0-beta.21",

Best regards, anna-liebt

#8

Yep, as I see in your repo. Wrong version. Update it

Best regards, anna-liebt

#9

@anna_liebt that did it. Thank you very much. You’re the best!!!