How to Make Angular Project Layout Which Requires Many Screens Including Header, Footer and Navbar Using Few Components.

Saran Gupta
The Startup
Published in
5 min readSep 29, 2020

Update! The code for this article is now available at GitHub. You can view the project, link is given below.

The structure is same because writing this blog and doing implementation parallelly for better understanding .

Preface

In my experience of Front end development in Angular, we divide the project into 3 categories as small, medium and big project with respect to number of screens (in most cases), module and the requirement of User. For small sized project hardly one will have to manage routing among 5–10 screens, can do it by defining path with respect to components in app-routing file. Big projects means, 5+ modules and each has number of components e.g. 5–10 components to handle their own requests and responses from server. Here we must use Lazy Loading concept to ensure better performance and modularity of code.

I am assuming developer needs to develop project such as 100 screens using 10 components. Each Screens has to show data in 1–2 table or any message or a form etc. Each component is independent by each other but screens are dependent on this components. Like Component-1 has screens name as Comp-1-Screen-1, Comp-1-Screen-2, Comp-1-Screen-3 and so on for Component-2. Header, Footer, Navigation Bar are also included in Layout. Please note here, Naming of components are just for reference. Make project as per your requirement.

Prerequisite

I am using Angular CLI 10.1.3 (need typescript 3.9+). This example is valid for any version of Angular 5+. Although to update your local Angular version here is the guide.

Let’s Start…

Create new Project

Go to the command prompt, in your workspace and create new project with this command. Here “SampleApp” is my project name.

ng new SampleApp

Add Plugins

Here i am using PrimeNg and Bootstrap Plugin because it has wide variety of readymade Components and it’s easy to use.

npm install @angular/animations --save
npm install primeng --save
npm install primeicons --save
npm i bootstrap --save

Add this configuration in angular.json file in style tag.

"styles": [
"src/styles.scss",
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"node_modules/primeng/resources/themes/arya-blue/theme.css",
"node_modules/primeng/resources/primeng.min.css",
"node_modules/primeicons/primeicons.css"
],

Import same configuration in global style.scss file

@import "~bootstrap/dist/css/bootstrap.css";
@import '../node_modules/primeng/resources/themes/arya-blue/theme.css';
@import '../node_modules/primeng/resources/primeng.min.css';
@import '~primeicons/primeicons.css';

Don’t forget to import BrowserAnimationsModule in app.module.ts file.

Layout

folder-structure

I recommend you to read a blog on Folder Structure standards for better code quality. For basic layout generate compoenents layout, header, footer, navbar, screens e.g. CompOne, CompTwo, CompThree… as per your requirement. Here we have only service named as ‘MessageShare’, in which we will use BehaviourSubject to pass our menu option from navbar component. Based on this message, we will navigate among components and screens. BehaviourSubject will hold the value of our current menu/screen option as message. Provide basic path structure in app-routing.module.ts file as usual. You can choose your header from Bootstrap Navbar examples in header component. For complete code go to GitHub repo, mentioned below. Generate following component using cli.

ng g c ui/layout
ng g c ui/header
ng g c ui/footer
ng g c ui/navbar
ng g c components/screens/compOne
ng g c ui/components/screens/compTwo
ng g c ui/components/screens/compThree
ng g s service/messageShare

Open ‘app.component.html’ to define Header at top, Footer at bottom. In between both of them define your content in layout. If you are using header as navigation bar, don’t need to generate navbar component. Use same configuration as per layout component.

<app-header></app-header>
<app-layout>
</app-layout>
<app-footer></app-footer>

Make ‘layout.component.html’ with division of the PrimeNg Grid by 3 (navbar)– 9 (content of screen) ratio.

<div class="ui-g">
<div class="row">
<div class="ui-g-3">
<app-navbar></app-navbar>
</div>
<div class="ui-g-9">
<router-outlet></router-outlet>
</div>
</div>
</div>

Open ‘navar.component.html’ file and use Panel Menu for Navigation bar, because it is very handy to manage large number like 50+ items or screens, so is highly scalable. Make sure to import PanelMenuModule in ‘app.module.ts’ file.

<p-panelMenu [model]="items"></p-panelMenu>

Define the MenuItem of PanelMenu in ngOnInit() of ‘navbar.component.ts’.

this.items = [{
label: 'Component One',
icon: 'pi pi-pw pi-file',
items: [
{ label: 'Screen One', icon: 'pi pi-fw', command: (event) => {
this.goToComp1_Scr1(); } },
{ label: 'Screen Two', icon: 'pi pi-fw', command: (event) => {
this.goToComp1_Scr2() } },
]
},
label: 'Component Two',
icon: 'pi pi-pw pi-file',
items: [
{ label: 'Screen Two', icon: 'pi pi-fw', command: (event) => {
this.goToComp2_Scr1(); } },
{ label: 'Screen Two', icon: 'pi pi-fw', command: (event) => {
this.goToComp2_Scr2() } },
]
},
... and
],

Implement methods as below to route among components and subscribe the BehaviourSubject from MessageShareService to pass which screen to display by click on navbar item. Make sure to inject Router and MessageShareService in ‘navbar component.ts’ constructor.

goToComp1_Scr1() {
this.router.navigateByUrl('Component_One');
this.service.goToSubMenu('CompOne_ScreenOne');
}
goToComp1_Scr2() {
this.router.navigateByUrl('Component_One');
this.service.goToSubMenu('CompOne_ScreenTwo');
}

In ‘message-share.service.ts’ implement goToSubMenu method as follow. BehaviorSubject returns initial value if subscribed immediately or current value if emitted first then subscribed, while Subject will return always current value once it is emitted. Without emitting first, subject will not be subscribed. It will manage your screen address and Route.

private subMenu = new BehaviorSubject<string>('CompOne_ScreenOne');
currentMenu = this.subMenu.asObservable();
goToSubMenu(path: string) {
this.subMenu.next(path);
}

Define routing in ‘app-routing.module.ts’ as per path and repective component.

const routes: Routes = [
{ path: 'Component_One', component: CompOneComponent },
{ path: 'Component_Two', component: CompTwoComponent },
{ path: 'Component_Three', component: CompThreeComponent },
];

Follow, below code procedure in every component you have generated under screen folder like ‘comp-one.component.ts’. Implement ngOnInit(), to call currentMenu Observable, you will get message as which screen user wants to view e.g CompOne_ScreenOne.

ngOnInit(): void {
this.service.currentMenu.subscribe(message => {
this.subMenu = message;
});
}

Define constructor, to trick the Router into believing it’s last link that was not previously loaded. This will help your component to not use your last screen again and get a fresh initialization. If, we don’t reuse component, all the DOM elements present in screen will be override by previous screen DOM element.

//Initialize properties
routerSubscription: Subscription;
subMenu: string;
//Define Constructor
constructor(private service: MessageShareService, private router: Router) {
this.router.routeReuseStrategy.shouldReuseRoute = function () {
return false;
};
this.routerSubscription = this.router.events.subscribe((event) => { if (event instanceof NavigationEnd) {
this.router.navigated = false;
}
});
}

Don’t forget to unsubscribe the routerSubscription in ngOnDestroy().

ngOnDestroy() {
if (this.routerSubscription) {
this.routerSubscription.unsubscribe();
}
}

Now implement all the .html file of component under screen folder. Implement your body content under div by replacing Screen name like(CompOne_ScreenOne).

<div *ngIf="subMenu==='CompOne_ScreenOne'">
Component One - Screen One
</div>
<div *ngIf="subMenu==='CompOne_ScreenTwo'">
Component One - Screen Two
</div>
<div *ngIf="subMenu==='CompOne_ScreenTwo'">
Component One - Screen One
</div>
Working Page with routing on different screens.

Here is the woorking project.

You can download or view the code in git -https://github.com/sarangpta/Sample-App.git

After download the code, go into project folder and install required libraries by ‘npm install’ to get ‘node_modules’ libraries. Then run the project by ‘ng serve -o’ and enjoy your learning.

--

--