ng new my-app | Create new project |
ng serve | Start dev server |
ng build | Build project |
ng build --configuration=production | Production build |
ng test | Run unit tests |
ng e2e | Run e2e tests |
ng generate component name | Generate component |
ng g c name | Short form |
ng g s name | Generate service |
ng g m name | Generate module |
ng g pipe name | Generate pipe |
ng g directive name | Generate directive |
ng add @angular/material | Add library |
ng update | Update dependencies |
@Component({
selector: 'app-hello',
templateUrl: './hello.component.html',
styleUrls: ['./hello.component.css']
})
export class HelloComponent {
name = 'World';
} @Component({
selector: 'app-hello',
template: `<h1>Hello, {{name}}!</h1>`,
styles: [`h1 { color: blue; }`]
}) @Component({
selector: 'app-hello',
standalone: true,
imports: [CommonModule],
template: `...`
}) @Input() name: string = '';
// In parent template:
<app-child [name]="parentValue"></app-child> @Output() clicked = new EventEmitter<string>();
onClick() {
this.clicked.emit('data');
}
// In parent:
<app-child (clicked)="handleClick($event)"></app-child> @Input() value: string = '';
@Output() valueChange = new EventEmitter<string>();
// Usage:
<app-input [(value)]="data"></app-input> ngOnInit(): void {
// Called once after first ngOnChanges
} ngOnChanges(changes: SimpleChanges): void {
// Called when input properties change
} ngOnDestroy(): void {
// Cleanup before component is destroyed
} ngAfterViewInit(): void {
// After view is initialized
} {{ expression }}
{{ user.name }}
{{ getValue() }} [property]="expression"
[disabled]="isDisabled"
[src]="imageUrl" (event)="handler()"
(click)="onClick()"
(input)="onInput($event)" [(ngModel)]="value" [attr.aria-label]="label" [class.active]="isActive"
[ngClass]="{'active': isActive}" [style.color]="textColor"
[ngStyle]="{'color': textColor}" <div *ngIf="condition">Shown</div>
<div *ngIf="condition; else elseBlock">True</div>
<ng-template #elseBlock>False</ng-template> <li *ngFor="let item of items; index as i; trackBy: trackById">
{{i}}: {{item.name}}
</li> <div [ngSwitch]="value">
<p *ngSwitchCase="1">One</p>
<p *ngSwitchCase="2">Two</p>
<p *ngSwitchDefault>Other</p>
</div> @if (condition) {
<p>True</p>
} @else {
<p>False</p>
} @for (item of items; track item.id) {
<li>{{ item.name }}</li>
} @empty {
<li>No items</li>
} <input #myInput>
<button (click)="doSomething(myInput.value)">Click</button> @ViewChild('myInput') inputRef!: ElementRef;
ngAfterViewInit() {
this.inputRef.nativeElement.focus();
} @ContentChild(ChildComponent) child!: ChildComponent; @Injectable({
providedIn: 'root'
})
export class DataService {
getData() {
return ['a', 'b', 'c'];
}
} constructor(private dataService: DataService) {}
// Or using inject function:
private dataService = inject(DataService); // In app.config.ts or module:
provideHttpClient() this.http.get<User[]>('/api/users')
.subscribe(users => this.users = users); this.http.post<User>('/api/users', userData)
.subscribe(user => console.log(user)); const headers = new HttpHeaders()
.set('Authorization', 'Bearer token');
this.http.get('/api/data', { headers }); this.http.get('/api/data').pipe(
catchError(error => {
console.error(error);
return of([]);
})
); const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'users', component: UsersComponent },
{ path: 'users/:id', component: UserDetailComponent },
{ path: '**', component: NotFoundComponent }
]; {
path: 'admin',
loadChildren: () => import('./admin/admin.module')
.then(m => m.AdminModule)
} <router-outlet></router-outlet> <a routerLink="/users">Users</a>
<a [routerLink]="['/users', user.id]">User</a> <a routerLink="/users" routerLinkActive="active">Users</a> this.router.navigate(['/users', id]); this.router.navigate(['/search'], {
queryParams: { q: 'angular' }
}); constructor(private route: ActivatedRoute) {
this.route.params.subscribe(params => {
this.id = params['id'];
});
} this.route.queryParams.subscribe(params => {
this.query = params['q'];
}); <form #myForm="ngForm" (ngSubmit)="onSubmit(myForm)">
<input name="email" [(ngModel)]="email" required email>
<button type="submit" [disabled]="myForm.invalid">Submit</button>
</form> <input name="email" [(ngModel)]="email" #emailInput="ngModel" required>
<div *ngIf="emailInput.invalid && emailInput.touched">
Email is required
</div> form = new FormGroup({
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', Validators.minLength(6))
}); form = this.fb.group({
email: ['', [Validators.required, Validators.email]],
password: ['', Validators.minLength(6)]
}); <form [formGroup]="form" (ngSubmit)="onSubmit()">
<input formControlName="email">
<input formControlName="password" type="password">
<button type="submit" [disabled]="form.invalid">Submit</button>
</form> this.form.value // all values
this.form.get('email')?.value // single value {{ date | date:'yyyy-MM-dd' }}
{{ date | date:'short' }} {{ price | currency:'USD' }}
{{ price | currency:'KRW':'symbol' }} {{ text | uppercase }}
{{ text | lowercase }}
{{ text | titlecase }} {{ observable$ | async }} {{ object | json }} {{ items | slice:0:5 }} @Pipe({
name: 'truncate',
standalone: true
})
export class TruncatePipe implements PipeTransform {
transform(value: string, limit: number = 20): string {
return value.length > limit
? value.substring(0, limit) + '...'
: value;
}
} {{ longText | truncate:50 }} count = signal(0); this.count() // 0 this.count.set(5); this.count.update(v => v + 1); doubleCount = computed(() => this.count() * 2); effect(() => {
console.log('Count:', this.count());
}); <p>Count: {{ count() }}</p>
<p>Double: {{ doubleCount() }}</p>