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?
When using a
ui-view
directive inside of a downgraded component, wrap theui-view
directive in a div.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.