angular-hybrid: "No provider for UrlService" error since version 3.1.3 (Angular CLI based app in AOT mode)

I’ve got hybrid app based on Angular CLI. When running app in AOT mode (ng serve -o --aot=true) when this piece of code is run:

platformBrowserDynamic().bootstrapModule(AppModule)
  .then(platformRef => {
            const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
            upgrade.bootstrap(document.body, ['app'], {strictDi: false});

            const url: UrlService = platformRef.injector.get(UrlService);
            url.listen();
            url.sync();
    });

I am getting: "Unhandled Promise rejection: No provider for UrlService! ; Zone: <root> ; Task: Promise.then ; Value: Error: No provider for UrlService!"

Both AOT/JIT version works fine with version 3.1.2. Version 3.1.3/3.1.4 works only in JIT mode.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 6
  • Comments: 18 (2 by maintainers)

Most upvoted comments

@adamlubek remove ‘uirouter/angular’ and ‘uirouter/angularjs’ in your package.json file, only use ‘uirouter/angular-hybrid’

I found this is the working example : https://github.com/ui-router/sample-app-angular-hybrid/tree/e4b1144d5e3e3451f0f0cc640175bb7055294fdd you can try download and build it

@artaommahe so I changed code from:

    const url: UrlService = platformRef.injector.get(UrlService);

    url.listen();
    url.sync();

to


    const url: UrlService = getUIRouter(platformRef.injector).urlService;;

    url.listen();
    url.sync();

this compiles indeed but it completely breaks routing, states which were working aren’t recognized anymore

For anyone coming to this issue looking to resolve the “no provider” errors, make sure that you do not have multiple copies of the @uirouter/* packages nested in your node_modules directory.

One easy way to find out is to run these commands:

npm list @uirouter/core
npm list @uirouter/angular
npm list @uirouter/angularjs
npm list @uirouter/angular-hybrid

For each one, make sure there is only one version of the uirouter packages in the output.

good output

For example, for @uirouter/core only version 6.0.1 is listed in the output:

npm list @uirouter/core
sample-app-angular-hybrid@1.0.2 ~/projects/uirouter/sample-app-angular-hybrid
└─┬ @uirouter/angular-hybrid@9.0.0
  ├─┬ @uirouter/angular@5.0.0
  │ └── @uirouter/core@6.0.1  deduped
  ├─┬ @uirouter/angularjs@1.0.23
  │ └── @uirouter/core@6.0.1  deduped
  └── @uirouter/core@6.0.1

bad output

If there are multiple versions of a uirouter library, the output will look something like this:

npm list @uirouter/core
sample-app-angular-hybrid@1.0.2 ~/projects/uirouter/sample-app-angular-hybrid
├─┬ @uirouter/angular-hybrid@9.0.0
│ ├─┬ @uirouter/angular@5.0.0
│ │ └── @uirouter/core@6.0.1
│ ├─┬ @uirouter/angularjs@1.0.23
│ │ └── @uirouter/core@6.0.1
│ └── @uirouter/core@6.0.1
└── @uirouter/core@6.0.3

Note that versions 6.0.1 and 6.0.3 are both present


note: If you use yarn package manager, the command is yarn why @uirouter/core

@adamlubek i use it like so

deferAndSyncUiRouter(AppMainOldModule);

platformBrowserDynamic()
  .bootstrapModule(AppMainModule)
  .then(platformRef => bootstrapWithUiRouter(platformRef, AppMainOldModule));

export function deferAndSyncUiRouter(angularjsModule: ng.IModule): void {
  angularjsModule
    .config([ "$urlServiceProvider", ($urlServiceProvider: UrlRouterProvider) => $urlServiceProvider.deferIntercept()])
    .run(["$$angularInjector", $$angularInjector => {
      const url: UrlService = getUIRouter($$angularInjector).urlService;
      url.listen();
      url.sync();
    }]);
}

export function bootstrapWithUiRouter(platformRef: NgModuleRef<any>, angularjsModule: ng.IModule): void {
  const injector = platformRef.injector;
  const upgradeModule = injector.get(UpgradeModule);

  upgradeModule.bootstrap(document.body, [ angularjsModule.name ], { strictDi: true });
}