Angular 18 Cheat Sheet
This cheat sheet covers essential aspects of Angular 18 to get you started and ensure you're familiar with key concepts and practices.
### Project Setup
- **Create New Project:**
```bash
ng new my-app
cd my-app
ng serve
```
- **Generate Component:**
```bash
ng generate component my-component
```
- **Generate Service:**
```bash
ng generate service my-service
```
### Modules
- **App Module (`app.module.ts`):**
```typescript
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { MyComponent } from './my-component/my-component.component';
@NgModule({
declarations: [AppComponent, MyComponent],
imports: [BrowserModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
```
### Components
- **Component Decorator:**
```typescript
import { Component } from '@angular/core';
@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponent {
title = 'My Component';
}
```
- **Component Template:**
```html
<h1>{{ title }}</h1>
<button (click)="doSomething()">Click me</button>
```
- **Component Styles:**
```css
h1 {
color: blue;
}
```
### Data Binding
- **Interpolation:**
```html
<p>{{ myVariable }}</p>
```
- **Property Binding:**
```html
<img [src]="imageUrl">
```
- **Event Binding:**
```html
<button (click)="handleClick()">Click Me</button>
```
- **Two-Way Binding:**
```typescript
import { Component } from '@angular/core';
@Component({
selector: 'app-example',
template: `<input [(ngModel)]="name"> <p>{{name}}</p>`
})
export class ExampleComponent {
name: string = '';
}
```
### Directives
- **Structural Directives:**
```html
<div *ngIf="condition">Conditionally shown</div>
<div *ngFor="let item of items">{{ item }}</div>
```
- **Attribute Directives:**
```html
<div [ngClass]="{ 'my-class': isTrue }"></div>
```
### Services and Dependency Injection
- **Creating a Service:**
```typescript
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class MyService {
getValue() {
return 'Hello from service!';
}
}
```
- **Using a Service in a Component:**
```typescript
import { Component } from '@angular/core';
import { MyService } from './my-service.service';
@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponent {
value: string;
constructor(private myService: MyService) {
this.value = myService.getValue();
}
}
```
### Routing
- **App Routing Module:**
```typescript
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'about', component: AboutComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
```
- **Router Outlet in Template:**
```html
<nav>
<a routerLink="/">Home</a>
<a routerLink="/about">About</a>
</nav>
<router-outlet></router-outlet>
```
### Forms
- **Reactive Forms:**
```typescript
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.css']
})
export class FormComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
name: ['', Validators.required],
email: ['', [Validators.required, Validators.email]]
});
}
onSubmit() {
console.log(this.form.value);
}
}
```
- **Form Template:**
```html
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<input formControlName="name" placeholder="Name">
<input formControlName="email" placeholder="Email">
<button type="submit">Submit</button>
</form>
```
### HTTP Client
- **Making HTTP Requests:**
```typescript
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) {}
getData(): Observable<any> {
return this.http.get('https://api.example.com/data');
}
}
```
- **Using HTTP Client in a Component:**
```typescript
import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';
@Component({
selector: 'app-data',
templateUrl: './data.component.html',
styleUrls: ['./data.component.css']
})
export class DataComponent implements OnInit {
data: any;
constructor(private dataService: DataService) {}
ngOnInit() {
this.dataService.getData().subscribe(response => {
this.data = response;
});
}
}
```
### Pipes
- **Using Built-in Pipes:**
```html
<p>{{ today | date }}</p>
<p>{{ price | currency }}</p>
```
- **Creating a Custom Pipe:**
```typescript
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'customPipe'
})
export class CustomPipe implements PipeTransform {
transform(value: string): string {
return value.toUpperCase();
}
}
```
### Advanced Topics
- **Lazy Loading Modules:**
```typescript
const routes: Routes = [
{
path: 'feature',
loadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule)
}
];
```
- **State Management with NgRx:**
```bash
ng add @ngrx/store
```
```typescript
// store/app.state.ts
import { ActionReducerMap } from '@ngrx/store';
import { counterReducer } from './counter.reducer';
export interface AppState {
counter: number;
}
export const reducers: ActionReducerMap<AppState> = {
counter: counterReducer
};
```
```typescript
// store/counter.reducer.ts
import { createReducer, on } from '@ngrx/store';
import { increment, decrement, reset } from './counter.actions';
export const initialState = 0;
const _counterReducer = createReducer(
initialState,
on(increment, state => state + 1),
on(decrement, state => state - 1),
on(reset, state => 0)
);
export function counterReducer(state, action) {
return _counterReducer(state, action);
}
```
```typescript
// store/counter.actions.ts
import { createAction } from '@ngrx/store';
export const increment = createAction('[Counter] Increment');
export const decrement = createAction('[Counter] Decrement');
export const reset = createAction('[Counter] Reset');
```
```typescript
// app.module.ts
import { StoreModule } from '@ngrx/store';
import { reducers } from './store/app.state';
@NgModule({
imports: [
StoreModule.forRoot(reducers)
]
})
```
### Testing
- **Writing Unit Tests:**
```typescript
import { TestBed } from '@angular/core/testing';
import { MyService } from './my-service.service';
describe('MyService', () => {
let service: MyService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(MyService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
```
- **Writing Component Tests:**
```typescript
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MyComponent } from './my-component.component';
describe('MyComponent', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MyComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
```
### Miscellaneous
- **Environment Configuration:**
```typescript
// src/environments/environment.ts
export const environment = {
production: false,
apiUrl: 'https://dev.api.com'
};
```
```typescript
// src/environments/environment.prod.ts
export const environment = {
production: true,
apiUrl: 'https://api.com'
};
```
- **Using Environment Variables:**
```typescript
import { environment } from '../environments/environment';
const apiUrl = environment.apiUrl;
```
Comments
Post a Comment