salemdar / angular2-cookie

Implementation of Angular 1.x $cookies service to Angular 2
MIT License
109 stars 29 forks source link

AOT compiled code throws error because of CookieOptions (Angular 2.4.x) #37

Closed exequiel09 closed 6 years ago

exequiel09 commented 7 years ago

Details: OS: macOS 10.12.2 Angular version: 2.4.0 Angular-CLI version: 1.0.0-beta.24 angular2-cookie version: 1.2.6

When running the compiled code using ng serve --aot or running the code built using the command ng build --prod --aot it throws the error EXCEPTION: Uncaught (in promise): Error: No provider for CookieOptions!

When running a non-AOT compiled code, it works.

My module definition looks like this:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { Http } from '@angular/http';
import { ModalModule, TooltipModule, AccordionModule } from 'ng2-bootstrap';
import { TranslateModule, TranslateLoader } from 'ng2-translate';
import { SaraiNg2RoutingModule } from './app-routing.module';
import { StoreModule } from './store';
import { MapModule } from './map';

import { CookieService } from 'angular2-cookie/services/cookies.service';
import { AppLoggerService } from './app-logger.service';
import { TranslationFactoryLoader } from './app-translation-factory.service';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    SaraiNg2RoutingModule,
    ModalModule.forRoot(),
    TooltipModule.forRoot(),
    AccordionModule.forRoot(),
    StoreModule,
    MapModule,
    TranslateModule.forRoot({
      provide: TranslateLoader,
      useFactory: TranslationFactoryLoader,
      deps: [Http]
    })
  ],
  providers: [
    AppLoggerService,
    CookieService
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Stack Trace:

EXCEPTION: Uncaught (in promise): Error: No provider for CookieOptions!
Error: DI Error
    at NoProviderError.BaseError [as constructor] (http://localhost:4200/vendor.bundle.js:5231:27) [angular]
    at NoProviderError.AbstractProviderError [as constructor] (http://localhost:4200/vendor.bundle.js:71091:16) [angular]
    at new NoProviderError (http://localhost:4200/vendor.bundle.js:71140:16) [angular]
    at ReflectiveInjector_._throwOrNull (http://localhost:4200/vendor.bundle.js:86387:19) [angular]
    at ReflectiveInjector_._getByKeyDefault (http://localhost:4200/vendor.bundle.js:86424:25) [angular]
    at ReflectiveInjector_._getByKey (http://localhost:4200/vendor.bundle.js:86374:25) [angular]
    at ReflectiveInjector_.get (http://localhost:4200/vendor.bundle.js:86136:21) [angular]
    at AppModuleInjector.get [as _CookieService_93] (http://localhost:4200/main.bundle.js:5978:149) [angular]
    at AppModuleInjector.getInternal (http://localhost:4200/main.bundle.js:6297:24) [angular]
    at AppModuleInjector.NgModuleInjector.get (http://localhost:4200/vendor.bundle.js:53973:44) [angular]
    at View_AppComponent0.AppView.injectorGet (http://localhost:4200/vendor.bundle.js:2384:45) [angular]
    at ElementInjector.get (http://localhost:4200/vendor.bundle.js:86653:27) [angular]
    at ReflectiveInjector_._getByKeyDefault (http://localhost:4200/vendor.bundle.js:86421:24) [angular]
    at ReflectiveInjector_._getByKey (http://localhost:4200/vendor.bundle.js:86374:25) [angular]
ErrorHandler.handleError @ error_handler.js:50
next @ application_ref.js:346
schedulerFn @ async.js:91
SafeSubscriber.__tryOrUnsub @ Subscriber.js:223
SafeSubscriber.next @ Subscriber.js:172
Subscriber._next @ Subscriber.js:125
Subscriber.next @ Subscriber.js:89
Subject.next @ Subject.js:55
EventEmitter.emit @ async.js:77
NgZone.triggerError @ ng_zone.js:329
onHandleError @ ng_zone.js:290
ZoneDelegate.handleError @ zone.js:246
Zone.runGuarded @ zone.js:129
_loop_1 @ zone.js:429
drainMicroTaskQueue @ zone.js:438
error_handler.js:55 ORIGINAL STACKTRACE:
ErrorHandler.handleError @ error_handler.js:55
next @ application_ref.js:346
schedulerFn @ async.js:91
SafeSubscriber.__tryOrUnsub @ Subscriber.js:223
SafeSubscriber.next @ Subscriber.js:172
Subscriber._next @ Subscriber.js:125
Subscriber.next @ Subscriber.js:89
Subject.next @ Subject.js:55
EventEmitter.emit @ async.js:77
NgZone.triggerError @ ng_zone.js:329
onHandleError @ ng_zone.js:290
ZoneDelegate.handleError @ zone.js:246
Zone.runGuarded @ zone.js:129
_loop_1 @ zone.js:429
drainMicroTaskQueue @ zone.js:438
error_handler.js:56 Error: Uncaught (in promise): Error: No provider for CookieOptions!
Error: DI Error
    at NoProviderError.BaseError [as constructor] (errors.js:31) [angular]
    at NoProviderError.AbstractProviderError [as constructor] (reflective_errors.js:53) [angular]
    at new NoProviderError (reflective_errors.js:102) [angular]
    at ReflectiveInjector_._throwOrNull (reflective_injector.js:994) [angular]
    at ReflectiveInjector_._getByKeyDefault (reflective_injector.js:1031) [angular]
    at ReflectiveInjector_._getByKey (reflective_injector.js:981) [angular]
    at ReflectiveInjector_.get (reflective_injector.js:743) [angular]
    at AppModuleInjector.get [as _CookieService_93] (app.module.ngfactory.ts:561) [angular]
    at AppModuleInjector.getInternal (app.module.ngfactory.ts:689) [angular]
    at AppModuleInjector.NgModuleInjector.get (ng_module_factory.js:148) [angular]
    at View_AppComponent0.AppView.injectorGet (view.js:152) [angular]
    at ElementInjector.get (element_injector.js:32) [angular]
    at ReflectiveInjector_._getByKeyDefault (reflective_injector.js:1028) [angular]
    at ReflectiveInjector_._getByKey (reflective_injector.js:981) [angular]
    at resolvePromise (zone.js:486) [angular]
    at resolvePromise (zone.js:471) [angular]
    at :4200/vendor.bundle.js:172254:17 [angular]
    at Object.onInvokeTask (ng_zone.js:260) [angular]
    at ZoneDelegate.invokeTask (zone.js:274) [angular]
    at Zone.runTask (zone.js:151) [<root> => angular]
    at drainMicroTaskQueue (zone.js:418) [<root>]
ErrorHandler.handleError @ error_handler.js:56
next @ application_ref.js:346
schedulerFn @ async.js:91
SafeSubscriber.__tryOrUnsub @ Subscriber.js:223
SafeSubscriber.next @ Subscriber.js:172
Subscriber._next @ Subscriber.js:125
Subscriber.next @ Subscriber.js:89
Subject.next @ Subject.js:55
EventEmitter.emit @ async.js:77
NgZone.triggerError @ ng_zone.js:329
onHandleError @ ng_zone.js:290
ZoneDelegate.handleError @ zone.js:246
Zone.runGuarded @ zone.js:129
_loop_1 @ zone.js:429
drainMicroTaskQueue @ zone.js:438
zone.js:405 Unhandled Promise rejection: No provider for CookieOptions! ; Zone: angular ; Task: Promise.then ; Value: NoProviderError {_nativeError: Error: No provider for CookieOptions!
    at NoProviderError.BaseError [as constructor] (http://loca…, keys: Array[1], injectors: Array[1]} Error: DI Error
    at NoProviderError.BaseError [as constructor] (http://localhost:4200/vendor.bundle.js:5231:27) [angular]
    at NoProviderError.AbstractProviderError [as constructor] (http://localhost:4200/vendor.bundle.js:71091:16) [angular]
    at new NoProviderError (http://localhost:4200/vendor.bundle.js:71140:16) [angular]
    at ReflectiveInjector_._throwOrNull (http://localhost:4200/vendor.bundle.js:86387:19) [angular]
    at ReflectiveInjector_._getByKeyDefault (http://localhost:4200/vendor.bundle.js:86424:25) [angular]
    at ReflectiveInjector_._getByKey (http://localhost:4200/vendor.bundle.js:86374:25) [angular]
    at ReflectiveInjector_.get (http://localhost:4200/vendor.bundle.js:86136:21) [angular]
    at AppModuleInjector.get [as _CookieService_93] (http://localhost:4200/main.bundle.js:5978:149) [angular]
    at AppModuleInjector.getInternal (http://localhost:4200/main.bundle.js:6297:24) [angular]
    at AppModuleInjector.NgModuleInjector.get (http://localhost:4200/vendor.bundle.js:53973:44) [angular]
    at View_AppComponent0.AppView.injectorGet (http://localhost:4200/vendor.bundle.js:2384:45) [angular]
    at ElementInjector.get (http://localhost:4200/vendor.bundle.js:86653:27) [angular]
    at ReflectiveInjector_._getByKeyDefault (http://localhost:4200/vendor.bundle.js:86421:24) [angular]
    at ReflectiveInjector_._getByKey (http://localhost:4200/vendor.bundle.js:86374:25) [angular]
consoleError @ zone.js:405
_loop_1 @ zone.js:434
drainMicroTaskQueue @ zone.js:438
zone.js:407 Error: Uncaught (in promise): Error: No provider for CookieOptions!
Error: DI Error
    at NoProviderError.BaseError [as constructor] (errors.js:31) [angular]
    at NoProviderError.AbstractProviderError [as constructor] (reflective_errors.js:53) [angular]
    at new NoProviderError (reflective_errors.js:102) [angular]
    at ReflectiveInjector_._throwOrNull (reflective_injector.js:994) [angular]
    at ReflectiveInjector_._getByKeyDefault (reflective_injector.js:1031) [angular]
    at ReflectiveInjector_._getByKey (reflective_injector.js:981) [angular]
    at ReflectiveInjector_.get (reflective_injector.js:743) [angular]
    at AppModuleInjector.get [as _CookieService_93] (app.module.ngfactory.ts:561) [angular]
    at AppModuleInjector.getInternal (app.module.ngfactory.ts:689) [angular]
    at AppModuleInjector.NgModuleInjector.get (ng_module_factory.js:148) [angular]
    at View_AppComponent0.AppView.injectorGet (view.js:152) [angular]
    at ElementInjector.get (element_injector.js:32) [angular]
    at ReflectiveInjector_._getByKeyDefault (reflective_injector.js:1028) [angular]
    at ReflectiveInjector_._getByKey (reflective_injector.js:981) [angular]
    at NoProviderError.BaseError [as constructor] (errors.js:31) [angular]
    at NoProviderError.AbstractProviderError [as constructor] (reflective_errors.js:53) [angular]
    at new NoProviderError (reflective_errors.js:102) [angular]
    at ReflectiveInjector_._throwOrNull (reflective_injector.js:994) [angular]
    at ReflectiveInjector_._getByKeyDefault (reflective_injector.js:1031) [angular]
    at ReflectiveInjector_._getByKey (reflective_injector.js:981) [angular]
    at ReflectiveInjector_.get (reflective_injector.js:743) [angular]
    at AppModuleInjector.get [as _CookieService_93] (app.module.ngfactory.ts:561) [angular]
    at AppModuleInjector.getInternal (app.module.ngfactory.ts:689) [angular]
    at AppModuleInjector.NgModuleInjector.get (ng_module_factory.js:148) [angular]
    at View_AppComponent0.AppView.injectorGet (view.js:152) [angular]
    at ElementInjector.get (element_injector.js:32) [angular]
    at ReflectiveInjector_._getByKeyDefault (reflective_injector.js:1028) [angular]
    at ReflectiveInjector_._getByKey (reflective_injector.js:981) [angular]
    at resolvePromise (zone.js:486) [angular]
    at resolvePromise (zone.js:471) [angular]
    at :4200/vendor.bundle.js:172254:17 [angular]
    at Object.onInvokeTask (ng_zone.js:260) [angular]
    at ZoneDelegate.invokeTask (zone.js:274) [angular]
    at Zone.runTask (zone.js:151) [<root> => angular]
    at drainMicroTaskQueue (zone.js:418) [<root>]
consoleError @ zone.js:407
_loop_1 @ zone.js:434
drainMicroTaskQueue @ zone.js:438
salemdar commented 7 years ago

Could you try to import it like this and tell me if it changes anything?

import { CookieService } from 'angular2-cookie/core';
exequiel09 commented 7 years ago

@salemdar No good. Still the same.

salemdar commented 7 years ago

Thanks. Then the issue requires some investigation. I will try to duplicate and solve the problem after work.

elvirdolic commented 7 years ago

I have the same issue

exequiel09 commented 7 years ago

Issue is also present on Angular 2.4.1.

elvirdolic commented 7 years ago

The problem is with the @Optional in the CookieService constructor

I have copied the CookieService and created my own without the CookieOptions constructor (which I don't need in my app) and injected it instead of original CookieService. It works as a workaround.

exequiel09 commented 7 years ago

According to this documentation on the Optional - Angular Docs "A parameter metadata that marks a dependency as optional. Injector provides null if the dependency is not found.".

Do you think this is a bug introduced in the 2.4.x? Or is it something else? Haven't dug deeper on the Angular codebase. This is just a mere speculation.

exequiel09 commented 7 years ago

So i managed to make it to be AOT-compilable by changing this line

import { CookieService } from 'angular2-cookie/services/cookies.service';

to

import { CookieService, CookieOptions } from 'angular2-cookie/core';

and finally provide a default value to the CookieOptions by providing a value (adding in the list of providers in the NgModule):

{ provide: CookieOptions, useValue: {} }

@salemdar @elvirdolic kindly verify if it works on your end. Thanks.

@elvirdolic I managed it without removing the @Optional decorator.

exequiel09 commented 7 years ago

Maybe a mere hack, but it works as expected on my end. But I think, this should be transparent to the user. What do you think?

cacogr commented 7 years ago

@exequiel09 It works for me. Thanks.

salemdar commented 7 years ago

@exequiel09 Thanks for checking it. Strange that @Optional doesn't work with AOT.

I will update the documentation, but I believe that we should somehow handle this internally and save user from the complexity.

brendanalexdr commented 7 years ago

@exequiel09 Thanks for the fix! Worked for me too

exequiel09 commented 7 years ago

Since https://github.com/salemdar/angular2-cookie/issues/39 was reported, the solution will be to do this

import { BaseCookieOptions, CookieService, CookieOptions } from 'angular2-cookie/core';
{ provide: CookieOptions, useClass: BaseCookieOptions }

Unfortunately, this only works on JIT mode not on AOT mode.

brendanalexdr commented 7 years ago

@exequiel09 Yes that worked many thx! Since I am only in development mode, I can go without AOT compilation for now.

Perezmarc commented 7 years ago

Any thoughts on how to make it work on AOT? I get the newOpts.merge error

psurrey commented 7 years ago

This workaround solved the issue for me:

export function cookieServiceFactory() {
  return new CookieService();
}

and within my Module:

providers: [
    { provide: CookieService, useFactory: cookieServiceFactory }
]
achimha commented 7 years ago

Any update on this? Also is there a reason the service is not provided as a module?

DennisSmolek commented 7 years ago

@psurrey's method worked for me as well.

If anyone is seeing: no provider for t! errors when using the Angular CLI this is where it came from for me. The CLI runs AOT checking by default, this means that even with JIT in dev in production it was doing AOT and I couldn't for the life of me find this error. I had to tear out all of our services and finally got this one.

ahmed-musallam commented 7 years ago

@DennisSmolek @psurrey that worked for me as well to fix no provider for t! but any idea why exactly this is happening?

Spawnrad commented 7 years ago

Any update please. All your solution doesn't work for me. Idk why but cookie doesn't work when i add options.

halfonf commented 7 years ago

Need some help here too. We have the no provider for t error when building angular cli in prod. Using ng build without prod works for now but we can't stay like that.

Thx

dlevkov commented 7 years ago

@psurrey method works just fine.

In Your app.module.ts add this { provide: CookieService, useFactory: cookieServiceFactory }, to providers array, like this: providers: [ // expose our Services and Providers into Angular's dependency injection ENV_PROVIDERS, APP_PROVIDERS, { provide: CookieService, useFactory: cookieServiceFactory } ] then just add this function somewhere at the bottom of app.module.ts export function cookieServiceFactory() { return new CookieService(); }

@Spawnrad , will it help?

psurrey commented 7 years ago

@dlevkov I think the issue @Spawnrad has is that he needs to provide the Options with the CookieService constructor. That is exactly the point that doesn't work - for whatever reason. And with my solution I was able to work around that. So the issue is, that as soon one wants to provide the Options via CookieService constructor it does still not work...

ahmed-musallam commented 7 years ago

@psurrey I think this project should export the source TS services in addition to UMD and ES2015 modules. I believe if you actually clone the raw repo and use the TS services directly, you wont have a problem with AOT. Though, it's a theory and I have not tried it :) Wish I have the time to actually make a PR for this... anyone reading this and would like to give it a shot, please let me know if it works.

dlevkov commented 7 years ago

@psurrey in my case CookieOptionsArgs fitted well my needs private setCookie(sValue, exdays, sDomain) { let key = this.sCookieName; let value = sValue; let opts: CookieOptionsArgs = { expires: new Date('2030-07-19') }; this._cookieService.put(key, value, opts); }

Mattee commented 7 years ago

@psurrey's method worked for me as well.

I got the "No provider for t!" exception when upgrading the angular-cli to 1.0.0-beta.32.3.

ghost commented 7 years ago

Just adding this to the providers section in my core module "fixed" the issue.

{ provide: CookieOptions, useValue: {} }
sreedharbukya commented 7 years ago

Adding below code worked in building AOT, but CookieService.

{ provide: CookieOptions, useValue: {} }

CookieService api like remove cookies not working

sreedharbukya commented 7 years ago

@elvirdolic and @psurrey , I tried to use the

{ provide: CookieOptions, useValue: {} }

for AOT configuration. It works for building aot build.js but actual functionality is not working.

ghost commented 7 years ago

Any solution to this? This issue was raised in December, including in other issues, but still no proper solution? @sreedharbukya @elvirdolic @psurrey

sebastianhaas commented 7 years ago

I mentioned this in another issue, I made the required changes in this branch.

I added a CookieModule that will take care of providing the CookieService and that can be imported easily. I also updated typescript and tsconfig to prepare it for a AOT build. If you want to try you can run npm run build and npm pack on my branch.

The thing is, I don't know gulp very well and the project structure feels very complicated to me, so I don't have the time to make a PR right now.

Btw I guess that doing something like I proposed would solve #51, #50, #47, #43 and #40.

salemdar commented 7 years ago

I will release a new version this weekend, which I'll introduce CookieModule.

@sebastianhaas thanks for your effort. I'll also do some modifications with project structure in order to simplify it

sebastianhaas commented 7 years ago

Cool, that's good news :)

salemdar commented 7 years ago

The new version is ready. I'll release it tonight after updating the docs and testing it with well known seed projects (and angular-cli of course).

It'll be released under name ngx-cookie.

exequiel09 commented 7 years ago

That closes #38 .

salemdar commented 7 years ago

I have released the new version, but I am having some issues with angular-cli.

@exequiel09 and @sebastianhaas maybe you could check the issue?

https://github.com/salemdar/ngx-cookie/issues/1

exequiel09 commented 7 years ago

@salemdar working on non-AOT and AOT-compiled code on @angular/cli.

Note: angular-cli has been renamed to @angular/cli

mukund19 commented 7 years ago

@exequiel09 @salemdar @elvirdolic @cacogr @nukuuk I tried the following import { CookieService, CookieOptions } from 'ngx-cookie';

and then

{ provide: CookieOptions, useValue: {} }

But I am getting the following error saying "CookieOptions only refers to a type but is being used as value here"

Could you please tell me what is the problem?

Majed93 commented 7 years ago

In my imports i added forChild() to CookieModule and that seemed to fix it for me. forRoot() also works.

songkl commented 6 years ago
import { BaseCookieOptions, CookieService, CookieOptions } from 'angular2-cookie';
{ provide: CookieOptions, useClass: BaseCookieOptions }