Search code examples
angularjsangularangular-upgrade

Angular UpgradeComponent cannot find $scope


I have a hybrid angular-cli that roughly follows Victor Savkin's Lazy Loaded AngularJS guide. AngularJS is bootstraped in the constructor of a LazyLoaded Angular module. The main difference between my app and the guide is that I am trying to wrap the <ui-view> directive inside of some Angular components. Because of how my layout is structured the <ui-view> element will not be available when AngularJS is bootstrapped and may be added or removed at any time.

import { Component, Directive, ElementRef, Injector } from '@angular/core';
import { UpgradeComponent } from '@angular/upgrade/static';
import * as angular from 'angular';

@Component({
  template: `
  <layout-wrapper>
    <my-toolbar></my-toolbar>
    <layout-contents>
      <ng2-ui-view>
        <h3 class="text-center">AngularJS page not loaded</h3>
      </ng2-ui-view>
    </layout-contents>
  </layout-wrapper>
  `,
})
export class LegacyOutputComponent { }

@Directive({selector: 'ng2-ui-view'})
export class UpgradedUiViewComponent extends UpgradeComponent {
  constructor(ref: ElementRef, inj: Injector) {
    super('uiViewWrapper', ref, inj);
  }
}

export const routerPatchModule = 'arcs.router.patch';

// We need to define a wrapper for ui-view because we can only upgrade
// components with only one definition. uiView cannot be automatically
// upgraded because its definition is too complex
angular.module(routerPatchModule, ['ui.router'])
.component('uiViewWrapper', { template: '<ui-view></ui-view>'})

When I run the code a Error: No provider for $scope! error is thrown. Checking the stack trace I can see that it is thrown in the UpgradeComponent super class. The injector tries to get $scope and


Solution

  • This setup will not work. AngularJS needs to be able to load in the root of your application in order for the scope to be defined correctly.

    A better way to approach this problem is to use the <div ui-view> directive in the root of your application (as in the upgrade guide) and then to downgrade a layout component from Angular into AngularJS to wrap your content.