Skip to main content

Using Angular

Learn how to use Angular in the JAQ Stack ecosystem for building modern web applications.

Overview

Angular provides the frontend framework for JAQ Stack, offering a powerful and scalable solution for building single-page applications.

Getting Started

Prerequisites

  • Node.js 18 or higher
  • npm or yarn
  • Angular CLI

Installation

# Install Angular CLI globally
npm install -g @angular/cli

# Clone the repository
git clone https://github.com/jaqstack/jaqstack-angular.git

# Navigate to the project
cd jaqstack-angular

# Install dependencies
npm install

# Start the development server
ng serve

Core Features

  • Component-Based Architecture: Modular and reusable components
  • TypeScript Support: Type-safe development
  • Routing: Client-side navigation
  • HTTP Client: API integration
  • Forms: Reactive and template-driven forms
  • Testing: Unit and integration testing

Project Structure

src/
├── app/
│ ├── components/ # Reusable components
│ ├── services/ # Business logic and API calls
│ ├── models/ # TypeScript interfaces
│ ├── guards/ # Route guards
│ ├── interceptors/ # HTTP interceptors
│ └── shared/ # Shared utilities
├── assets/ # Static assets
├── environments/ # Environment configurations
└── styles/ # Global styles

Configuration

Environment Setup

// src/environments/environment.ts
export const environment = {
production: false,
apiUrl: 'http://localhost:8080/api',
appName: 'JAQ Stack',
version: '1.0.0'
};

Angular Module

// src/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { ReactiveFormsModule } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

Best Practices

  1. Component Design: Keep components small and focused
  2. Service Layer: Use services for business logic
  3. Type Safety: Leverage TypeScript features
  4. Performance: Use OnPush change detection strategy
  5. Accessibility: Follow WCAG guidelines

Examples

Creating a Component

// src/app/components/user-list/user-list.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../../services/user.service';
import { User } from '../../models/user.model';

@Component({
selector: 'app-user-list',
templateUrl: './user-list.component.html',
styleUrls: ['./user-list.component.css']
})
export class UserListComponent implements OnInit {
users: User[] = [];
loading = false;

constructor(private userService: UserService) { }

ngOnInit(): void {
this.loadUsers();
}

loadUsers(): void {
this.loading = true;
this.userService.getUsers().subscribe({
next: (users) => {
this.users = users;
this.loading = false;
},
error: (error) => {
console.error('Error loading users:', error);
this.loading = false;
}
});
}
}

Service Implementation

// src/app/services/user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { User } from '../models/user.model';

@Injectable({
providedIn: 'root'
})
export class UserService {
private apiUrl = 'http://localhost:8080/api/users';

constructor(private http: HttpClient) { }

getUsers(): Observable<User[]> {
return this.http.get<User[]>(this.apiUrl);
}

getUser(id: string): Observable<User> {
return this.http.get<User>(`${this.apiUrl}/${id}`);
}

createUser(user: User): Observable<User> {
return this.http.post<User>(this.apiUrl, user);
}

updateUser(id: string, user: User): Observable<User> {
return this.http.put<User>(`${this.apiUrl}/${id}`, user);
}

deleteUser(id: string): Observable<void> {
return this.http.delete<void>(`${this.apiUrl}/${id}`);
}
}

Model Definition

// src/app/models/user.model.ts
export interface User {
id?: string;
name: string;
email: string;
role: UserRole;
createdAt?: Date;
updatedAt?: Date;
}

export enum UserRole {
ADMIN = 'admin',
USER = 'user',
GUEST = 'guest'
}

Routing

// src/app/app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { UserListComponent } from './components/user-list/user-list.component';
import { UserDetailComponent } from './components/user-detail/user-detail.component';

const routes: Routes = [
{ path: '', redirectTo: '/users', pathMatch: 'full' },
{ path: 'users', component: UserListComponent },
{ path: 'users/:id', component: UserDetailComponent },
{ path: '**', redirectTo: '/users' }
];

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

Testing

Unit Test Example

// src/app/services/user.service.spec.ts
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { UserService } from './user.service';

describe('UserService', () => {
let service: UserService;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule]
});
service = TestBed.inject(UserService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});

Troubleshooting

Common Issues

  1. Module Not Found: Check import paths and module declarations
  2. CORS Errors: Configure CORS on the backend
  3. Build Errors: Ensure all dependencies are installed
  4. Performance Issues: Use Angular DevTools for profiling

Getting Help

Next Steps