Ui-router child state not loading inside downgraded Angular component

1.5k views Asked by At

I have a hybrid/lazy-loaded Angular/AngularJS application which uses both the new Angular router and ui-router version 0.4.2 with parallel outlets/views. To accomplish this I have followed Victor Savkin's Lazy Loaded AngularJS guide In general, this is working well and I can switch between Angular routes and AngularJS routes. However, I am running into an issue where ui-router child views are not shown when the page first opens.

This issue only affects states if trying to load the child state on boot. Navigating between routes does not encounter the same issue. I have also determined that it only occurs in routes when the parent state template is wrapped by a downgraded Ng2 component.

State and Template Definitions

@Component({ template: '<ng-content></ng-content>'})
export class TestDowngradedComponent { }

angular.module('routerPatchModule', ['ui.router'])
.directive('downgradedComp', downgradeComponent({ component: TestDowngradedComponent }))
.config(['$stateProvider', ($stateProvider) => {
  $stateProvider.state({
    name: 'parent',
    url: '/parent',
    template: '<downgraded-comp><ui-view></ui-view></downgraded-comp>',
  })
  .state({
    name: 'parent.test',
    url: '/test',
    template: 'The child route doesn't appear on load',
  })
}]);

/**
 * Ng2 Module which upgrades the legacy Ng1 module
 */
@NgModule({
  declarations: [
    EmptyTemplateComponent,
    TestDowngradedComponent,
  ],
  entryComponents: [
    TestDowngradedComponent,
  ],
  imports: [
    SharedModule,
    UpgradeModule,
    RouterModule.forChild([
      {path: '**', component: EmptyTemplateComponent},
    ]),
  ],
})
export class LegacyAppModule {
  constructor(upgrade: UpgradeModule) {
    upgrade.bootstrap(document.body, [ng1AppModule, 'routerPatchModule'], { strictDi: true });
    setUpLocationSync(upgrade);
  }
}

Tracking the state change events, I was able to determine that the child view is temporarily loaded but then removed.

State Event Log

$viewContent Loading undefined {"view":"@"}
$viewContent Loaded  undefined {"view":"@"}

$stateChange Start   state1.child
$stateChange Success state1.child
$viewContent Loading undefined {"view":"@"}
$viewContent Loading state1 {"view":"@state1"}
$viewContent Loaded  state1.child {"view":"@state1"} // child view temporarily loaded
$viewContent Loaded  state1 {"view":"@"} // child view gone!

// User clicks link to state2
$stateChange Start   state2
$stateChange Success state2
$viewContent Loading undefined {"view":"@"}
$viewContent Loading state2 {"view":"@state2"}
$viewContent Loaded  state2 {"view":"@state2"}
$viewContent Loaded  state2 {"view":"@"}
$stateChange Start   state2.child
$stateChange Success state2.child
$viewContent Loading state2 {"view":"@state2"}
$viewContent Loaded  state2.child {"view":"@state2"} // Child loaded successfully

// User clicks link to state1
$stateChange Start   state1
$stateChange Success state1
$viewContent Loading undefined {"view":"@"}
$viewContent Loading state1 {"view":"@state1"}
$viewContent Loaded  state1 {"view":"@state1"}
$viewContent Loaded  state1 {"view":"@"}
$stateChange Start   state1.child
$stateChange Success state1.child
$viewContent Loading state1 {"view":"@state1"}
$viewContent Loaded  state1.child {"view":"@state1"} // Child loaded after parent

What about using a component with <ng-content> causes the ui-router to not render correctly and what can I do to correct the issue?

1

There are 1 answers

3
Chic On BEST ANSWER

When using a ui-view directive inside of a downgraded component, wrap the ui-view directive in a div.

  $stateProvider.state({
    name: 'parent',
    url: '/parent',
    template: '<downgraded-comp><div><ui-view></ui-view></div></downgraded-comp>',
  })

I stumbled upon a solution by accident and am not sure exactly why it worked. I wonder if it is the result of dom elements being replaced by the @angular/upgrade library.