Fading Coder

One Final Commit for the Last Sprint

Home > Notes > Content

Angular Development Coding Conventions

Notes May 14 1

Angular Development Coding Conventions

1. Project Structure

Top-Level Directories
  • src/: Houses all source code.
  • src/app/: Contains the main app module and core components.
  • src/assets/: Stores static resources (e.g., images, fonts).
  • src/environments/: Holds environment-specific configurations.
Feature Modules
  • Organize each feature into a dedicated folder.
  • Leverage feature modules to partition the app for better scalability.
src/ 
├── app/ 
│   ├── core/       # Singleton services, global components (e.g., navbar) 
│   ├── shared/     # Reusable components, directives, pipes 
│   ├── dashboard/  # Feature module: Dashboard 
│   ├── settings/   # Feature module: Settings 
│   └── app.module.ts  # Root module 
├── assets/ 
├── environments/ 
└── main.ts 
Module Substructure

Each feature module should include subfolders for components, services, models, etc.

dashboard/ 
├── components/ 
│   ├── stats-card/ 
│   │   ├── stats-card.component.ts 
│   │   ├── stats-card.component.html 
│   │   ├── stats-card.component.scss 
│   │   └── stats-card.component.spec.ts 
│   └── chart-widget/ 
├── services/ 
│   └── dashboard-data.service.ts 
├── models/ 
│   └── dashboard-metric.model.ts 
├── pipes/ 
│   └── number-format.pipe.ts 
└── directives/ 
    └── hover-highlight.directive.ts 

2. Naming Conventions

File Naming
  • Use kebab-case for filenames.
  • Example: user-dashboard.component.ts, data-fetcher.service.ts.
Classes and Interfaces
  • Use PascalCase for class and interface names.
  • Example: UserDashboardComponent, DataFetcherService.
Variables and Functions
  • Use camelCase for variable and function names.
  • Example: userName, fetchUserProfile().
Component Selectors
  • Use kebab-case with an app prefix for component selectors.
  • Example: app-user-dashboard.
Enums
  • Enum names use PascalCase; enum values use UPPER_SNAKE_CASE.
export enum UserRole { 
    ADMIN = 'ADMIN', 
    EDITOR = 'EDITOR' 
}

3. Code Style

Quotes
  • Prefer single quotes ('); use double quotes (") only when a string contains single quotes.
  • Example: const message = 'Hello, "Angular"!';
Indentation and Whitespace
  • Use 2 spaces for indentation (avoid tabs).
  • Add a single space after commas, colons, and semicolons in style/configuration files.
Semicolons
  • Terminate all statements with a semicolon.
Arrow Functions
  • Use arrow functions to preserve this context (e.g., in callbacks).
const users = [1, 2, 3].map(id => this.getUser(id)); 
Template Strings
  • Use backticks (`) for multi-line or dynamic strings.
const html = `<div class="user-card">${user.name}</div>`; 
Comments
  • Add comments for complex logic or critical business rules (avoid redundant comments).
// Check if user has admin permissions (role ID: 100) 
if (user.roleId === 100) { 
    // ... 
}
Empty Lines
  • Insert empty lines between code blocks (e.g., imports, class methods, logical sections) to improve readability.
Line Length
  • Limit lines to 120 characters; break long lines for clarity.

4. Components & Templates

Component Classes
  • Each component should have a single responsibility.
  • Use the OnInit lifecycle hook for initialization logic.
import { Component, OnInit } from '@angular/core'; 
import { UserService } from '../services/user.service'; 
import { User } from '../models/user.model'; 

@Component({
    selector: 'app-user-details', 
    templateUrl: './user-details.component.html', 
    styleUrls: ['./user-details.component.scss'] 
})
export class UserDetailsComponent implements OnInit { 
    currentUser: User | null = null; 

    constructor(private userService: UserService) {} 

    ngOnInit(): void { 
        this.userService.fetchUser().subscribe(user => { 
            this.currentUser = user; 
        }); 
    } 
}
Template Files
  • Use either inline templates (template) or external files (templateUrl).
  • Keep template expressions simple; move complex logic to component methods.
<div *ngIf="currentUser"> 
    <h2>{{ currentUser.name }}</h2> 
    <p>{{ currentUser.email }}</p> 
</div> 
Styles
  • Use SCSS for styling; scope styles to the component using :host or component-specific classes.
.user-details { 
    h2 { 
        color: #2c3e50; 
    } 
}
Data Binding
  • Prefer one-way binding ([property]) for most cases; use two-way binding ([(ngModel)]) only when necessary.
<input [value]="user.name" (input)="updateUserName($event)"> 
Event Binding
  • Use (event) syntax for event handlers.
<button (click)="submitForm()">Submit</button> 
Directives & Pipes
  • Define custom directives/pipes in a shared module (export them for reuse).
  • Leverage built-in directives (e.g., *ngIf, *ngFor) and pipes (e.g., | date).
@Pipe({ name: 'titleCase' }) 
export class TitleCasePipe implements PipeTransform { 
    transform(value: string): string { 
        return value.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' '); 
    } 
}

5. Services & Dependency Injection

Service Classes
  • Mark services with @Injectable and specify providedIn to manage scope.
import { Injectable } from '@angular/core'; 
import { HttpClient } from '@angular/common/http'; 
import { Observable } from 'rxjs'; 
import { User } from '../models/user.model'; 

@Injectable({
    providedIn: 'root' // Provides a singleton instance 
})
export class UserService { 
    constructor(private http: HttpClient) {} 

    fetchUser(): Observable<User> { 
        return this.http.get<User>('/api/user'); 
    } 
}
Dependency Injection
  • Inject services via the constructor (Angular’s DI system handles instantiation).
export class UserDetailsComponent { 
    constructor(private userService: UserService) {} 
}
Provider Scope
  • Provide services at the module level (via @NgModule.providers) or component level (via @Component.providers).

6. Modules

NgModule Structure
  • Each module (root, feature, shared) should be a dedicated @NgModule.
  • Limit the number of declarations/imports per module for maintainability.
import { NgModule } from '@angular/core'; 
import { CommonModule } from '@angular/common'; 
import { UserDetailsComponent } from './components/user-details/user-details.component'; 
import { UserListComponent } from './components/user-list/user-list.component'; 
import { UserService } from './services/user.service'; 

@NgModule({
    declarations: [UserDetailsComponent, UserListComponent], 
    imports: [CommonModule], 
    providers: [UserService], 
    exports: [UserDetailsComponent] 
})
export class UserModule { } 
Shared Module
  • A shared module declares and exports reusable components, directives, and pipes.
@NgModule({
    declarations: [CommonButtonComponent, HighlightDirective, TitleCasePipe], 
    exports: [CommonButtonComponent, HighlightDirective, TitleCasePipe], 
    imports: [CommonModule] 
})
export class SharedModule { } 
Core Module
  • The core module contains singleton services (e.g., authentication, API) and global components.
@NgModule({
    providers: [AuthService, ApiService], 
    declarations: [NavbarComponent], 
    exports: [NavbarComponent] 
})
export class CoreModule { } 

7. Routing

Route Configuration
  • Define routes in a dedicated module (e.g., AppRoutingModule).
  • Use lazy loading for feature modules to optimize initial load time.
import { NgModule } from '@angular/core'; 
import { RouterModule, Routes } from '@angular/router'; 

const routes: Routes = [ 
    { 
        path: 'dashboard', 
        loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule) 
    }, 
    { 
        path: 'settings', 
        loadChildren: () => import('./settings/settings.module').then(m => m.SettingsModule) 
    }, 
    { path: '', redirectTo: '/dashboard', pathMatch: 'full' } 
]; 

@NgModule({
    imports: [RouterModule.forRoot(routes)], 
    exports: [RouterModule] 
})
export class AppRoutingModule { } 

8. Testing

  • Write unit tests for components, services, and pipes using Angular testing utilities (e.g., TestBed, ComponentFixture).
  • Place test files alongside the component/service (e.g., user-details.component.spec.ts).

9. Documentation & Comments

  • Document public APIs (components, services) using JSDoc-style comments.
  • Add inline comments for complex algorithms or non-obvious logic.

10. Version Control

  • Add a .gitignore file to exclude build artifacts (e.g., dist/, node_modules/).
  • Commit frequently with descriptive messages (e.g., "feat: Add user dashboard component").

Related Articles

Designing Alertmanager Templates for Prometheus Notifications

How to craft Alertmanager templates to format alert messages, improving clarity and presentation. Alertmanager uses Go’s text/template engine with additional helper functions. Alerting rules referenc...

Deploying a Maven Web Application to Tomcat 9 Using the Tomcat Manager

Tomcat 9 does not provide a dedicated Maven plugin. The Tomcat Manager interface, however, is backward-compatible, so the Tomcat 7 Maven Plugin can be used to deploy to Tomcat 9. This guide shows two...

Skipping Errors in MySQL Asynchronous Replication

When a replica halts because the SQL thread encounters an error, you can resume replication by skipping the problematic event(s). Two common approaches are available. Methods to Skip Errors 1) Skip a...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.