moltin / js-sdk

JavaScript & Node.js SDKs for the Elastic Path Commerce Cloud eCommerce API
http://documentation.elasticpath.com/
MIT License
173 stars 77 forks source link

Impossible to initialize Moltin as a service in Angular 2 #88

Closed gatoenano closed 7 years ago

gatoenano commented 7 years ago

Hi guys!

I've been trying to use the sdk with Angular 2 (actually the 4.1.3 version) initializing the Molltin package as a service, but without success.

The following code, is the typical used to start a new project in Angular 2 very simple, but it seems that the Moltin module is not returning the necessary things to register it as a service. Or maybe the problem is that I'm actually doing something wrong (probably xD)

Every time that I tried, the app throws an error with this message: Error: No provider for gateway!

So, a little bit of my code:


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
// App modules
import { AppComponent } from './app.component';
// Moltin module
import { gateway as MoltinGateway } from '@moltin/sdk';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [
    MoltinGateway
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}```

Anybody with the same problem?

Many thanks in advance!
ynnoj commented 7 years ago

@gatoenano Sorry for the delayed response. Did you manage to resolve this?

Are you using a bundler (such as Webpack) in your project?

gatoenano commented 7 years ago

Hey @ynnoj thanks for your response, no prob :)

I haven't tried since this problem. And the bundler is the default used by Angular CLI, webpack.

Did you tried to initialize the moltin service in a clean Angular project? It worked?

Greetings

skaparate commented 7 years ago

@gatoenano,

In your AppModule, You must provide an instance of the gateway with your client_id, otherwise the injector wouln't find the required dependency :

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
// App modules
import { AppComponent } from './app.component';
// Moltin module
import { gateway as MoltinGateway } from '@moltin/sdk';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [
    { provide: MoltinGateway, useValue: new MoltinGateway({ client_id: '....' }) }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Edited: please, do not use this example. It may work, but is wrong.

gatoenano commented 7 years ago

Hi @skaparate

Many thanks for your response. But sadly your solution didn't worked to me :/

On terminal it throws an error like this:

ERROR in Error encountered resolving symbol values statically. Calling function 'gateway', function calls are not supported. Consider replacing the function or lambda with a reference to an exported function, resolving symbol AppModule in...

Then I tried putting this code, to solve it:

// Core modules
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
// App modules
import { AppComponent } from './app.component';
// Moltin
import { gateway as MoltinGateway } from '@moltin/sdk';

// AoT requires an exported function for factories
export function MoltinGatewayExporter() {
    return new MoltinGateway();
}

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [
    { provide: MoltinGateway, useValue: new MoltinGateway({ client_id: '.....' }) }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

It seemed to work regarding compilation errors on terminal. But a new error appeared on browser instead of the terminal:

 __WEBPACK_IMPORTED_MODULE_5__moltin_sdk__.a is not a constructor

Any thougths about what could be the problem?

Thx to all!

skaparate commented 7 years ago

@gatoenano,

Maybe it has something to do with the angular version. Could you update to the angular-cli 4.3.2? Which version of the moltin sdk are you using? This are my package.json dependencies:

"@angular/common": "^4.3.2",
"@angular/compiler": "^4.3.2",
"@angular/core": "^4.3.2",
"@angular/forms": "^4.3.2",
"@angular/http": "^4.3.2",
"@angular/platform-browser": "^4.3.2",
"@angular/platform-browser-dynamic": "^4.3.2",
"@angular/router": "^4.3.2",
"moltin/sdk": "^2.5.0",
"core-js": "^2.4.1",
"rxjs": "^5.4.2",
"zone.js": "^0.8.16"
ynnoj commented 7 years ago

@gatoenano gateway is not a class - its a function. You won't be able to instantiate it the way you are trying to. The below should work based on @skaparate's comment. Although I'm not sure how he has had success with his example 😕

import { gateway as MoltinGateway } from '@moltin/sdk';

providers: [
    {
      provide: MoltinGateway, useValue: MoltinGateway({
        client_id: '.....'
      })
    }
]
skaparate commented 7 years ago

@ynnoj, @gatoenano,

Oops! Sorry, the new keyword was my bad, but the rest is right :).

skaparate commented 7 years ago

@gatoenano,

As it turns out, I was using new in my code... I don't really know why it worked, but it shouldn't. The initial idea was right, but the implementation is wrong: we have to use InjectionToken:

import { BrowserModule } from '@angular/platform-browser';

// You must import InjectionToken:
import { NgModule, InjectionToken } from '@angular/core';

import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
// App modules
import { AppComponent } from './app.component';
// Moltin module
import { gateway as MoltinGateway } from '@moltin/sdk';

const moltin = MoltinGateway({ client_id: ' ... ' });
export const moltinToken = new InjectionToken('MoltinGateway');

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [
    { provide: moltinToken, useValue: moltin }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Then you can use it like this:

import { Injectable, Inject } from '@angular/core';
import { gateway as MoltinGateway } from '@moltin/sdk';
import { moltinToken } from './app.module';

@Injectable()
export class MyService {
    constructor(@Inject(moltinToken) private moltinGw: MoltinGateway) { }
}
ynnoj commented 7 years ago

Going to close this. Please reopen if you're still have issues @gatoenano.

Thanks for the assist, @skaparate! I'm going to document your recommended Angular approach in the Wiki 🙃