تماس با ما

Angular

فریم‌ورک کامل از Google بر پایه‌ی TypeScript؛ routing، فرم، HTTP، DI و تست همگی داخل خودش هست.

فریم‌ورک کامل از Google بر پایه‌ی TypeScript؛ routing، فرم، HTTP، DI و تست همگی داخل خودش هست.

npm i -g @angular/cli
ng new my-app
cd my-app && ng serve        # http://localhost:4200
ng generate component user-card
ng build
ng test

ساختار

  • Component: کلاس + template + استایل
  • Service: منطق/داده‌ی مشترک (با Dependency Injection)
  • Route: مسیرها
  • Angular مدرن: standalone components (بدون NgModule) و Signals.

Component

import { Component, signal, computed } from "@angular/core";

@Component({
  selector: "app-counter",
  standalone: true,
  template: `
    <button (click)="inc()">{{ count() }}</button>
    <p>دو برابر: {{ double() }}</p>
  `,
  styles: [`button { padding: .5rem 1rem; }`],
})
export class CounterComponent {
  count = signal(0);
  double = computed(() => this.count() * 2);
  inc() { this.count.update(n => n + 1); }
}

Signals

const n = signal(0);
n();                 // خواندن
n.set(5);
n.update(v => v + 1);
const d = computed(() => n() * 2);
effect(() => console.log(n()));       // اثر جانبی

Template

<p>{{ title }}</p>
<img [src]="url" [alt]="desc" />                 <!-- property binding -->
<button (click)="save()">ذخیره</button>          <!-- event binding -->
<input [(ngModel)]="name" />                     <!-- two-way (FormsModule) -->
<div [class.active]="isActive" [style.color]="color"></div>

@if (user) {
  <p>{{ user.name }}</p>
} @else {
  <p>مهمان</p>
}

@for (item of items; track item.id) {
  <li>{{ item.name }}</li>
} @empty {
  <li>خالی</li>
}

@switch (status) {
  @case ('ok') { <b>موفق</b> }
  @default { <i>نامشخص</i> }
}

(سینتکس control flow جدید @if/@for؛ قدیمی: *ngIf, *ngFor.)

Input / Output

import { input, output } from "@angular/core";

export class CardComponent {
  title = input.required<string>();     // Input signal
  closed = output<void>();               // Output
}
<app-card title="سلام" (closed)="onClose()" />

Dependency Injection و Service

@Injectable({ providedIn: "root" })
export class UserService {
  private http = inject(HttpClient);
  getUsers() { return this.http.get<User[]>("/api/users"); }
}

@Component({ /* ... */ })
export class UsersComponent {
  private svc = inject(UserService);
  users = toSignal(this.svc.getUsers(), { initialValue: [] });
}

تنظیم HTTP: provideHttpClient() در app.config.ts.

RxJS

Angular از Observable استفاده می‌کند (HTTP، فرم، router).

import { of, fromEvent, debounceTime, map, switchMap, catchError } from "rxjs";

search$.pipe(
  debounceTime(300),
  switchMap(q => this.http.get<Item[]>(`/api/search?q=${q}`)),
  catchError(() => of([])),
).subscribe(items => this.items = items);

در template: {{ data$ | async }} یا toSignal() برای unsubscribe خودکار.

Router

export const routes: Routes = [
  { path: "", component: HomeComponent },
  { path: "users/:id", component: UserComponent },
  { path: "admin", loadComponent: () => import("./admin.component").then(m => m.AdminComponent), canActivate: [authGuard] },
  { path: "**", component: NotFoundComponent },
];
<a routerLink="/users/5">کاربر</a>
<router-outlet />

فرم‌ها

form = new FormGroup({
  email: new FormControl("", [Validators.required, Validators.email]),
  password: new FormControl("", [Validators.required, Validators.minLength(8)]),
});
submit() { if (this.form.valid) console.log(this.form.value); }
<form [formGroup]="form" (ngSubmit)="submit()">
  <input formControlName="email" />
  @if (form.controls.email.errors?.['email']) { <small>ایمیل نامعتبر</small> }
  <button [disabled]="form.invalid">ورود</button>
</form>

Reactive Forms برای فرم‌های جدی توصیه می‌شن؛ Template-driven (ngModel) برای ساده.

Pipe و Directive

{{ price | currency }} {{ date | date:'short' }} {{ text | uppercase }}
@Pipe({ name: "truncate", standalone: true })
export class TruncatePipe implements PipeTransform {
  transform(v: string, n = 20) { return v.length > n ? v.slice(0, n) + "…" : v; }
}

Directive: @Directive({ selector: "[appHighlight]" }).

Lifecycle

ngOnInit, ngOnChanges, ngOnDestroy, ngAfterViewInit (و DestroyRef برای cleanup).

تست

Jasmine/Karma یا Jest/Vitest؛ TestBed برای کامپوننت‌ها؛ Playwright/Cypress برای E2E (E2E).

SSR

ng add @angular/ssr برای رندر سمت سرور و hydration (meta-frameworks-ssr-ssg).

تمرین

۱. برنامه‌ی لیست کار با signals و سرویس. ۲. فرم ثبت‌نام با Reactive Forms و اعتبارسنجی. ۳. جستجوی زنده با RxJS (debounceTime + switchMap).

ایده‌ای دارید؟ برایمان بگویید

مشاوره و پیشنهاد اولیه رایگان است.

تماس با ما