2

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?

Chic
  • 9,836
  • 4
  • 33
  • 62

1 Answers1

2

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.

Chic
  • 9,836
  • 4
  • 33
  • 62
  • 1
    Also have encountered this problem. It's mystifying. I can route to my state correctly, URL is updated as expected, but no matter what I try, can not render a template. Not even a template string. Suggested solution doesn't seem to be working. – pccjamie Mar 13 '18 at 17:09
  • 1
    It's the year 2020 and I'm currently working on a hybrid Angular/Angular.js application using downgraded Angular components. Seem to be running into the issue as described by the OP and the proposed solution here doesn't seem to work. I can't seem to target any ui-view that is being rendered from a downgraded Angular component's template. Any recent insights? – Princeton Collins Apr 24 '20 at 17:49
  • This solution works if the parent component is AngularJS (not new Angular) – Tang Thanh Tam Feb 25 '23 at 08:36