Reputation: 693
Let me start by stating that I am very novice to Angular 4.
We have a very long process for a user to register in our system where they will have to go through several process of entering and/or verifying their basic information, education, work history, etc... For that purpose, I am trying to implement wizard steps like process.
I seem to have some issue with router_outlet that I can't find way to overcome.
I have a wizard like process where wizard steps are being displayed on all pages and router_outlet will change the steps below the wizard steps as seen below.
and here is where I start: app.routing.ts
const appRoutes: Routes = [
{ path: '', redirectTo: 'app1', pathMatch: 'full' }
];
app.routing is included in app.module
import { NgModule } from '@angular/core';
import { APP_BASE_HREF } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
/*App Root*/
import { AppComponent } from './app.component';
import { ModalModule } from './Modals/app.modals.module'
import {App1Module} from './Features/Certification/app1.module'
//import { Ng2Bs3ModalModule } from 'ng2-bs3-modal/ng2-bs3-modal';
import { HttpModule } from '@angular/http';
import { applicationRouting } from './app.routing';
@NgModule({
imports: [BrowserModule, ReactiveFormsModule, HttpModule, applicationRouting, /*Ng2Bs3ModalModule*/ NgbModule.forRoot(), ModalModule, App1Module],
declarations: [AppComponent],
providers: [{ provide: APP_BASE_HREF, useValue: '/' }],
bootstrap: [AppComponent]
})
Here is my App1 module which contains its own routing:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { CustomerInformationService } from '../../Services/cusrtomerInformation.service'
import { App1Routing } from './app1.routing'
import {App1Component} from './app1.component'
import { App1HomeComponent } from './01-Home/app1.home.component';
import { App1EmploymentHistory } from './02-employment/app1.employment.component'
@NgModule({
imports: [BrowserModule, ReactiveFormsModule, App1Routing],
declarations: [App1Component, App1HomeComponent, App1EmploymentHistory],
providers: [CustomerInformationService],
exports:[RouterModule]
})
export class App1Module{}
Here is my app1.routing
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import {App1Component} from './app1.component';
import { App1HomeComponent } from './01-Home/app1.home.component';
import { App1EmploymentHistory} from './02-employment/app1.employment.component';
const appRoutes: Routes = [
{
path: 'app1', component: App1Component, children:
[
{path: 'app1home', component:App1HomeComponent},
{ path: 'employment', component: App1EmploymentHistory }
]
},
{path:'', component:App1Component}
];
export const App1Routing: ModuleWithProviders =
RouterModule.forChild(appRoutes);
My problem starts with App1Component itself.. where I want to keep my wizard steps always visible and then load the child components one at a time when someone clicks on next and previous.
Here is my App1.component template:
<div *ngIf="displayContents != null && displayContents == true">
<ul class='nav nav-wizard'>
<li><a href='#step1' data-toggle="tab">1 - Personal Details</a></li>
<li><a href='#step2' data-toggle="tab">Step 2</a></li>
<li><a href="/fgdf">Step 3</a></li>
<li class="active"><a href="/fgdf">Step 4</a></li>
<li><a href="/fgdf">Step 5</a></li>
<li><a href="/fgdf">Step 6</a></li>
<li><a href="/fgdf">Step 7</a></li>
</ul>
<hr />
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade" id="step1">
<p>Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.</p>
</div>
<div class="tab-pane fade active in" id="step2">
<p>Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.</p>
</div>
</div>
</div>
<router-outlet></router-outlet>
As you can see, my router_outlet is right below the wizard steps.. Now when someone visit /app1, I want to automatically load the App1Home component in a router outlet and when they click on next, I want to remove the App1Home component and load the next component which is App1EmploymentHistory. I also want to take a lazy load approach of App1EmploymentHistory component only upon click so that it doesn't have to load the component during app initialization
I tried putting "selector" in App1HomeComponent but when I put that selector in my App1Component, it loads App1HomeComponent but it doesnh't remove that component when I navigate to the App1EmploymentHistory component using the next button on App1HomeComponent..
I am sure I am missing some concept somewhere since I am very novice to angular 4.
I will appreciate if someone suggest solution to this problem.
If there is something available that mimics the Wizard steps and lazy load the steps only upon clicking the next/previous button, I certainly will not have to invent the wheel. I will appreciate any ready-made suggestions as well that I can adapt into my project.
Upvotes: 1
Views: 2541
Reputation: 3911
Your top navigation can be changed to this:
<ul class='nav nav-wizard'>
<li routerLink="/app1home" routerLinkActive="active" data-toggle="tab">
<span class="link-text-not-active">Step 1</span>
<span class="link-text-active">Step 1 - Personal Details</span>
</li>
<li routerLink="/step2" routerLinkActive="active" data-toggle="tab">
<span class="link-text-not-active">Step 2</span>
<span class="link-text-active">Step 2 - some longer title</span>
</li>
...
</ul>
Then the css for the nav:
.active .link-text-not-active {
display: none;
}
.link-text-active {
display: none;
}
.active .link-text-active {
display: block !important;
}
To redirect on load, add this to your router:
{ path: '', redirectTo: '/app1home', pathMatch: 'full' },
To navigate from your controller, add this to your controller:
import { Router } from '@angular/router';
...
constructor(private router: Router)
...
//in method
this.router.navigate('/app1home');
Upvotes: 0
Reputation: 6821
@Sam Answer looks right to me.
I will just add some code for your next and previous button:
<button [routerLink]="nextLink()"> next </button>
<button [routerLink]="previousLink()"> previous </button>
and in your component.ts:
stepLinks = ['/step1','/step2','/step3','/step4']
constructor(router:Router) {
router.events.subscribe((url: any) => this.url = url);
}
// I don't remember well what gives this.url so check it with a console.log before
nextLink(){
const index = this.stepLinks.indexOf(this.url);
if (index === this.stepLinks.length-1){ return `${this.stepLinks[index]}`}
return `${this.stepLinks[index + 1]}`
}
You need to adapt the code for the previousLink()
Upvotes: 1