I'm looking for similar solution to ui-router abstract state in Angular2 Router.
To have "virtual" parent state to resolve some common things for child states.
A route doesn't need to be associated with a component. It can just have children with an empty path. You can use this "empty" route for things like guards or resolves.
One thing I didn't know until testing right now, is that Resolve
s (it's data) will trickle down to child routes. So if you want to "resolve some common things for child states", this might be the place to do it.
{
path: '',
resolve: {
data: DummyResolve
},
children: [
{ path: 'one', component: Child1Component },
{ path: 'two', component: Child2Component }
]
}
Here is the complete test I used to test with
import { Component, Injectable, OnInit } from '@angular/core';
import { Router, Resolve, ActivatedRoute } from '@angular/router';
import { By } from '@angular/platform-browser';
import { Location, CommonModule } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';
import { TestBed, inject, fakeAsync, tick, ComponentFixture } from '@angular/core/testing';
@Injectable()
class DummyResolve implements Resolve<string> {
resolve() {
return 'Hello Routing';
}
}
@Component({
template: `
<router-outlet></router-outlet>
`
})
class RoutingComponent {
}
@Component({
template: `
<h1>Child One</h1>
<span>{{ data }}</span>
`
})
class Child1Component implements OnInit {
data: string;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.data.forEach((data: { data: string }) => {
this.data = data.data;
console.log(`data from child 1: ${this.data}`);
});
}
}
@Component({
template: `
<h1>Child Two</h1>
<span>{{ data }}</span>
`
})
class Child2Component implements OnInit {
data: string;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.route.data.forEach((data: { data: string }) => {
this.data = data.data;
console.log(`data from child 2: ${this.data}`);
});
}
}
describe('component: RoutingComponent', function () {
let fixture: ComponentFixture<RoutingComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
CommonModule,
RouterTestingModule.withRoutes([
{
path: '',
resolve: {
data: DummyResolve
},
children: [
{ path: 'one', component: Child1Component },
{ path: 'two', component: Child2Component }
]
}
])
],
providers: [ DummyResolve ],
declarations: [ RoutingComponent, Child1Component, Child2Component ]
});
fixture = TestBed.createComponent(RoutingComponent);
fixture.detectChanges();
});
it('should go to child one',
fakeAsync(inject([Router, Location], (router: Router, location: Location) => {
router.navigate(['/one']);
tick();
fixture.detectChanges();
let debugEl = fixture.debugElement;
expect(debugEl.query(By.css('h1')).nativeElement.innerHTML).toEqual('Child One');
expect(debugEl.query(By.css('span')).nativeElement.innerHTML).toEqual('Hello Routing');
})));
it('should go to child two',
fakeAsync(inject([Router, Location], (router: Router, location: Location) => {
router.navigate(['/two']);
tick();
fixture.detectChanges();
let debugEl = fixture.debugElement;
expect(debugEl.query(By.css('h1')).nativeElement.innerHTML).toEqual('Child Two');
expect(debugEl.query(By.css('span')).nativeElement.innerHTML).toEqual('Hello Routing');
})));
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With