Best Practices Folder Structure In Angular
In this article, we will learn how to organize an Angular Application's folder structure. It's critical to choose the correct folder structure for your real-world Angular application. If you don't have the right structure in place, finding a specific component or file gets increasingly difficult as your App grows in features.
Folder for each Angular Module
To gather together relevant functionalities, Angular employs the concept of Angular Modules. This offers us a good place to begin organizing the folder structure. Each Module should have its own folder with the same name as the Module.
The Angular framework does not distinguish between Modules. However, we may categorize our modules into the four categories below based on how we use them.
- Root Module
- Feature Module
- Shared Module
- Core Module
Root Module
As soon as the application starts, one module must be loaded. This is referred to as the root module. The root module is responsible for loading the root component as well as all other modules.
The root module is usually referred to as AppModule and is located in the /src/app.folder.
Feature Modules
The Features module implements a certain application feature. The module contains all of the components, pipes, and directives that implement the feature.
Feature Modules require all components to be stored in a directory named after the module. /src/app/ModuleName>, for example. We make it easier to find a component that belongs to the module by doing so.
Under the module folder, you can build subfolders for directives and pipes.
You can make a components folder in which you can store all of your components. Alternatively, within the components folder, create a subdirectory for each component.
Another way to make a page folder is to use a text editor. Each route is represented by a page. The route path is used to name the folder. There could be more than one component in the route. They're all in the same page folder. The shared components should go in the separate components folder.
├── src │ ├── app │ │ ├── admin │ │ │ ├── components │ │ │ │ ├── shared.component.ts │ │ │ ├── directives │ │ │ │ ├── first.directive.ts │ │ │ │ ├── another.directive.ts │ │ │ ├── pages │ │ │ │ ├── dashboard │ │ │ │ │ ├── dashboard.component.ts │ │ │ │ ├── rights │ │ │ │ │ ├── rights.component.ts │ │ │ │ ├── user │ │ │ │ │ ├── user.component.ts │ │ │ │ ├── admin.component.ts │ │ │ │ ├── admin.component.html │ │ │ │ ├── admin.component.css │ │ │ │ ├── index.ts │ │ │ ├── pipes │ │ │ │ ├── first.pipe.ts │ │ │ │ ├── another.pipe.ts │ │ │ ├── admin.module.ts │ │ │ ├── admin.routing.module.ts │ │ │ ├── index.ts
Shared Module
├── src │ ├── app │ │ ├── shared │ │ │ ├── layout │ │ │ │ ├── footer │ │ │ │ │ ├── footer.component.ts │ │ │ │ │ ├── footer.component.html │ │ │ │ ├── header │ │ │ │ │ ├── header.component.ts │ │ │ │ │ ├── header.component.html │ │ │ ├── index.ts
Alternatively, as seen below, you can create directories such as components, pipelines, and directives.
├── src │ ├── app │ │ ├── shared │ │ │ ├── components │ │ │ │ ├── footer │ │ │ │ │ ├── footer.component.ts │ │ │ │ │ ├── footer.component.html │ │ │ │ ├── header │ │ │ │ │ ├── header.component.ts │ │ │ │ │ ├── header.component.html │ │ │ ├── pipes │ │ │ │ ├── pipe1 │ │ │ │ │ ├── pipe1.pipe.ts │ │ │ ├── index.ts
Core Module
@NgModule({}) export class CoreModule { constructor(@Optional() @SkipSelf() core:CoreModule ){ if (core) { throw new Error("You should import core module only in the root module") } } }
Folder Structure Example
ng new --routing --style css ModuleDemo
Feature Modules
Admin Module
import { NgModule } from '@angular/core'; import { AdminRoutingModule } from './admin.routing.module'; import { UserComponent,RightsComponent,DashboardComponent, AdminComponent } from './pages'; @NgModule({ declarations: [UserComponent,RightsComponent,DashboardComponent,AdminComponent], imports: [ AdminRoutingModule, ], providers: [], }) export class AdminModule { }
Add the following code under the admin.routing.module.ts file:
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { UserComponent , RightsComponent ,DashboardComponent, AdminComponent } from './pages'; const routes: Routes = [ { path: 'admin', component: AdminComponent, children :[ { path: 'dashboard', component: DashboardComponent}, { path: 'user', component: UserComponent}, { path: 'rights', component: RightsComponent}, ] }, ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class AdminRoutingModule { }
import { Component} from '@angular/core'; @Component({ selector: 'app-admin', templateUrl: './admin.component.html', styleUrls: ['./admin.component.css'] }) export class AdminComponent { }
Add the following code under the admin.component.html file:
<ul> <li><a routerlink="dashboard">dashboard</a></li> <li><a routerlink="user">User</a></li> <li><a routerlink="rights">Rights</a></li> </ul> <router-outlet></router-outlet>
import { Component } from '@angular/core'; @Component({ template: `<h1>Dashboard Component</h1>`, }) export class DashboardComponent { title = ''; }
Add the following code under the /app/src/admin/pages/rights/rights.component.ts.
import { Component } from '@angular/core'; @Component({ template: '<h1>Rights Component</h1>', }) export class RightsComponent { title = ''; }
Add the following code under the /app/src/admin/pages/user/user.component.ts.
import { Component } from '@angular/core'; @Component({ template: '<h1>User Component</h1>', }) export class UserComponent { title = ''; }
Add the following code under the /app/src/admin/pages/index.ts.
export * from './dashboard/dashboard.component'; export * from './rights/rights.component'; export * from './user/user.component'; export * from './admin.component';
Add the following code under the /app/src/admin/index.ts.
export * from './pages'; export * from './github.module';
Github Module
import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { GitHubService } from '../../../core'; import { repos} from '../../../core'; @Component({ templateUrl: './repo-list.component.html', }) export class RepoListComponent { userName: string ="angular" repos: repos[]; loading: boolean=false; errorMessage; constructor(private githubService: GitHubService) { } public getRepos() { this.loading=true; this.errorMessage=""; this.githubService.getRepos(this.userName) .subscribe((response) => {this.repos=response;}, (error) => {this.errorMessage=error; this.loading=false; }, () => {this.loading=false;}) } }
Add the following code under the /app/src/github/pages/list/repo-list.component.html:
<h1 class="heading"><strong>HTTP </strong>Demo</h1> <div class="form-group"> <label>GitHub User Name</label> <input class="form-control" name="userName" ngmodel="" type="text" username="" /> </div> <div class="form-group"> <button click="" getrepos="" type="button">Get Repos</button> </div> <div ngif="loading">loading...</div> <div class="alert alert-warning" ngif="errorMessage"> <strong>Warning!</strong> {{errorMessage}} </div> <div class="table-responsive"> <table class="table"> <thead> <tr> <th>ID</th> <th>Name</th> <th>HTML Url</th> <th>description</th> </tr> </thead> <tbody> <tr ngfor="let repo of repos;"> <td>{{repo.id}}</td> <td>{{repo.name}}</td> <td>{{repo.html_url}}</td> <td>{{repo.description}}</td> </tr> </tbody> </table> </div>
Add the following code under the /app/src/github/pages/index.ts:
export * from './repolist/repo-list.component';
Add the following code under the /app/src/github/github-routing.module.ts:
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { RepoListComponent } from './pages'; const routes: Routes = [ { path: 'github', component: RepoListComponent, children :[ { path: 'list', component: RepoListComponent}, ] } ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class GithubRoutingModule {}
Add the following code under the /app/src/github/github.module.ts:
import { NgModule } from '@angular/core'; import { GithubRoutingModule } from './github-routing.module'; import { RepoListComponent } from './pages'; import { SharedModule } from '../shared'; @NgModule({ imports: [ GithubRoutingModule,SharedModule ], providers: [ ], declarations: [RepoListComponent] }) export class GithubModule { }
Add the following code under the /app/src/github/index.ts:
export * from './pages'; export * from './github.module';
Home Module
import { Component } from '@angular/core'; @Component({ template: `Anout Us`, }) export class AboutUsComponent { }
Add the following code under the src/app/home/pages/contact-us.component.ts:
import { Component } from '@angular/core'; @Component({ template: `Contact Us`, }) export class ContactUsComponent { }
Add the following code under the src/app/home/pages/home.component.ts:
import { Component } from '@angular/core'; @Component({ template: `<h1> Welcome To Module Demo</h1>`, }) export class HomeComponent { }
Add the following code under the src/app/home/pages/index.ts:
export * from './aboutus/about-us.component'; export * from './contactus/contact-us.component'; export * from './home/home.component';
Add the following code under the src/app/home/home-routing.module.ts:
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { AboutUsComponent,ContactUsComponent,HomeComponent } from './pages'; const routes: Routes = [ { path: '', component: HomeComponent}, { path: 'contactus', component: ContactUsComponent}, { path: 'aboutus', component: AboutUsComponent}, ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class HomeRoutingModule {}
Add the following code under the src/app/home/home.module.ts:
import { NgModule } from '@angular/core'; import { HomeRoutingModule } from './home-routing.module'; import { AboutUsComponent,ContactUsComponent,HomeComponent } from './pages'; import { SharedModule } from '../shared'; @NgModule({ imports: [ HomeRoutingModule,SharedModule ], providers: [ ], declarations: [AboutUsComponent,ContactUsComponent,HomeComponent] }) export class HomeModule { }
Add the following code under the src/app/home/index.ts:
export * from './pages'; export * from './home.module';
Core Module
export class repos { id: string; name: string; html_url: string; description: string; }
Add the following code under the src/app/core/models/index.ts:
export * from './repos';
Add the following code under the src/app/core/models/services/github.service.ts:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { repos} from '../models'; @Injectable() export class GitHubService { baseURL:string="https://api.github.com/"; constructor(private http:HttpClient){ } getRepos(userName:string): Observable<repos> { return this.http.get<repos>(this.baseURL + 'users/' + userName + '/repos') } }
Add the following code under the src/app/core/models/services/index.ts:
export * from './github.service';
Add the following code under the src/app/core/models/core.module.ts:
import { NgModule, Optional, SkipSelf } from '@angular/core'; import { GitHubService } from './services/github.service'; @NgModule({ imports: [ ], providers: [ GitHubService ], declarations: [] }) export class CoreModule { constructor(@Optional() @SkipSelf() core:CoreModule ){ if (core) { throw new Error("You should import core module only in the root module") } } }
Add the following code under the src/app/core/models/index.ts:
export * from './core.module'; export * from './services'; export * from './models';
Shared Module
<p>(c) All Rights Reserved</p>
Add the following code under the /src/app/shared/layout/footer/footer.component.ts:
import { Component } from '@angular/core'; @Component({ selector: 'app-footer', templateUrl: './footer.component.html' }) export class FooterComponent { }
Add the following code under the /src/app/shared/layout/header/header.component.html:
<ul> <li> <a class="navbar-brand" routerlink="/">home</a> </li> <li> <a class="navbar-brand" routerlink="/github/list">GitHub</a> </li> <li> <a class="navbar-brand" routerlink="/admin">Admin</a> </li> <li> <a class="navbar-brand" routerlink="/aboutus">About</a> </li> <li> <a class="navbar-brand" routerlink="/contactus">Contact</a> </li> </ul>
Add the following code under the /src/app/layout/header/header.component.css:
ul { list-style-type: none; margin: 0; padding: 0; overflow: hidden; background-color: #333333; } li { float: left; } li a { display: block; color: white; text-align: center; padding: 16px; text-decoration: none; } li a:hover { background-color: #111111; }
Add the following code under the /src/app/layout/header/header.component.ts:
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.css'] }) export class HeaderComponent { }
Add the following code under the /src/app/layout/index.ts:
export * from './footer/footer.component'; export * from './header/header.component';
Add the following code under the /src/app/shared/shared.module.ts:
import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { HttpClientModule } from '@angular/common/http'; import { RouterModule } from '@angular/router'; import { HeaderComponent, FooterComponent } from './layout'; @NgModule({ imports: [ CommonModule, FormsModule, ReactiveFormsModule, HttpClientModule, RouterModule ], declarations: [ HeaderComponent,FooterComponent ], exports: [ CommonModule, FormsModule, ReactiveFormsModule, HttpClientModule, RouterModule, HeaderComponent,FooterComponent ] }) export class SharedModule { }
Add the following code under the /src/app/shared/index.ts:
export * from './shared.module'; export * from './layout';
Final Folder Structure
├── src │ ├── app │ │ ├── admin │ │ │ ├── directives │ │ │ ├── pages │ │ │ │ ├── dashboard │ │ │ │ │ ├── dashboard.component.ts │ │ │ │ ├── rights │ │ │ │ │ ├── rights.component.ts │ │ │ │ ├── user │ │ │ │ │ ├── user.component.ts │ │ │ │ ├── admin.component.ts │ │ │ │ ├── admin.component.html │ │ │ │ ├── admin.component.css │ │ │ │ ├── index.ts │ │ │ ├── pipes │ │ │ ├── admin.module.ts │ │ │ ├── admin.routing.module.ts │ │ │ ├── index.ts │ │ ├── core │ │ │ ├── models │ │ │ │ ├── index.ts │ │ │ │ ├── repos.ts │ │ │ ├── services │ │ │ │ ├── github.service.ts │ │ │ │ ├── index.ts │ │ │ ├── core.module.ts │ │ │ ├── index.ts │ │ ├── github │ │ │ ├── pages │ │ │ │ ├── repolist │ │ │ │ │ ├── repolist.component.ts │ │ │ │ │ ├── repolist.component.html │ │ │ ├── github.routing.module.ts │ │ │ ├── github.module.ts │ │ │ ├── index.ts │ │ ├── home │ │ │ ├── pages │ │ │ │ ├── aboutus │ │ │ │ │ ├── about-us.component.ts │ │ │ │ ├── contactus │ │ │ │ │ ├── contact-us.component.ts │ │ │ │ ├── home │ │ │ │ │ ├── home-us.component.ts │ │ │ │ ├── index.ts │ │ │ ├── home-routing.module.ts │ │ │ ├── home.module.ts │ │ │ ├── index.ts │ │ ├── shared │ │ │ ├── layout │ │ │ │ ├── footer │ │ │ │ │ ├── footer.component.ts │ │ │ │ │ ├── footer.component.html │ │ │ │ ├── header │ │ │ │ │ ├── header.component.ts │ │ │ │ │ ├── header.component.html │ │ │ ├── index.ts │ ├── app-routing.module.ts │ ├── app-wildcard-routing.module.ts │ ├── app.component.css │ ├── app.component.html │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── not-found.component.ts