Repository navigation
'$locationShim': Not a valid '@angular/upgrade' application. #46211
Description
Description
I'm getting issues implementing ngUpgrade according to the official docs.
I am at the stage when everything works, except navigation from Angular 1 to Angular 13.
It is not clear from the docs where this code should be put:
angular.module('rxntBillingApp')
.factory('$location', downgradeInjectable($locationShim));
I tried putting it before app.bootstrap(el) in LazyLoaderService, but this results in an error:
lazy-loader.service.ts:21 Error: Error while instantiating injectable '$locationShim': Not a valid '@angular/upgrade' application. Did you forget to downgrade an Angular module or include it in the AngularJS application?
This is a valid angular upgrade application because when this $locationShim downgrade is removed, everything works fine. The reason to introduce location shim is to unify routing, so that AngularJS application can route back to Angular 13 app.
It's not very clear from the docs, but I changed this.upgrade.bootstrap inside app.module.ts to bootstrap a regular AppComponent, which then has <router-outlet> and routes to Angular 13 test component or to AngularJS component which lazily loads all the static assets and performs the bootstrap.
// app-routing.module.ts
export const routes: Routes = [
// Routes rendered by Angular
{ path: 'test-component', component: TestComponent },
// AngularJS routes
{ path: '**', component: AngularJSComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }// angular-js.component.ts
export class AngularJSComponent implements OnInit, OnDestroy {
constructor(
private lazyLoader: LazyLoaderService,
private elRef: ElementRef
) {}
ngOnInit() {
this.lazyLoader.load(this.elRef.nativeElement);
}
ngOnDestroy() {
this.lazyLoader.destroy();
}
}And here is the code for LazyLoaderService, which is following the official example:
import { Injectable } from '@angular/core';
import angular from 'angular';
import { downgradeInjectable } from '@angular/upgrade/static';
import { $locationShim } from '@angular/common/upgrade';
@Injectable({
providedIn: 'root'
})
export class LazyLoaderService {
private app: angular.auto.IInjectorService | undefined;
load(el: HTMLElement): void {
import(/* webpackChunkName: "main.legacy" */ '../../app/index').then(app => {
try {
angular.module('rxntBillingApp')
.factory('$location', downgradeInjectable($locationShim)); // tried adding this code:
this.app = app.bootstrap(el);
} catch (e) {
console.error(e);
}
});
}
destroy() {
if (this.app) {
this.app.get('$rootScope').$destroy();
}
}
}app.bootstrap code is as follows:
export function bootstrap(el: HTMLElement) {
return angular.bootstrap(el, ['rxntBillingApp']);
}Please advise if you can see anything wrong with the above implementation.
What is the affected URL?
https://angular.io/guide/upgrade#using-the-unified-angular-location-service
Please provide the steps to reproduce the issue
No response
Please provide the expected behavior vs the actual behavior you encountered
No response
Please provide a screenshot if possible
No response
Please provide the exception or error you saw
No response
Is this a browser-specific issue? If so, please specify the device, browser, and version.
No response
Activity
vzakharov-rxnt commentedon Jun 1, 2022
I realized that by changing
this.upgrade.bootstraptoapp.bootstrap, it is no longer considered anngUpgradeapplication. So for exampledowngradeComponentalso fails, meaning the issue is not specific to$locationShim.Now, problem with
this.upgrade.bootstrapis that it does not return anything, so I cannot assign the result tothis.app, in order for destroy function to run correctly, according to the docs. Still not sure if I am on the right track, I'll continue the investigation.gkalpak commentedon Jun 1, 2022
You are right that you cannot use things like
downgradeInjectable()if you do not bootstrap the app withUpgradeModule#bootstrap()(since it will not be a hybrid, ngUpgrade app).It would definitely make sense to have UpgradeModule#bootstrap() return the AngularJS injector to align with angular.bootstrap(). In the meantime, you can use the AngularJS injector via UpgradeModule#$injector (after the app has been bootstrapped with
UpgradeModule#bootstrap()).vzakharov-rxnt commentedon Jun 1, 2022
@gkalpak Can you give an example with source code, or a link to it?
This doesn't look like valid JS/TS syntax:
gkalpak commentedon Jun 1, 2022
Sorry, it was supposed to be a Markdown link. I fixed my comment.
vzakharov-rxnt commentedon Jun 1, 2022
@gkalpak Are you saying this:
should be changed to this
?
gkalpak commentedon Jun 1, 2022
Something like that.
upgrade.$injectorcould be undefined (for example, if you haven't bootstrapped an AngularJS app yet), so you could have something like:this.upgrade.$injector?.get('$rootScope').destroy()vzakharov-rxnt commentedon Jun 2, 2022
@gkalpak Thank you, George. Please update the official docs when you can, this section:
angular-automatic-lock-bot commentedon Jul 4, 2022
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.