1. Pengantar Angular dan NgRx
Angular adalah framework front-end yang dikembangkan oleh Google untuk membangun aplikasi web yang dinamis dan scalable. NgRx adalah pustaka state management yang terinspirasi dari Redux, khusus dibuat untuk Angular, yang membantu mengelola state aplikasi secara terstruktur dan predictable.
Dalam ebook ini, Anda akan belajar bagaimana membangun aplikasi Angular dari nol dan mengintegrasikan NgRx untuk mengelola state aplikasi secara efektif.
2. Persiapan Lingkungan Pengembangan
Sebelum mulai coding, pastikan Anda sudah menginstal beberapa tools berikut:
Node.js (versi terbaru LTS)
Angular CLI (install dengan
npm install -g @angular/cli
)
Code Editor seperti Visual Studio Code
Git untuk version control
Setelah itu, buat proyek Angular baru dengan perintah:
npx @angular/cli new master-angular-ngrx --routing --style=scss
Masuk ke folder proyek:
cd master-angular-ngrx
Jalankan aplikasi dengan:
ng serve --open
3. Struktur Proyek Angular
Setelah membuat proyek, Anda akan melihat struktur folder seperti berikut:
src/app/
- Tempat semua kode aplikasi
src/assets/
- File statis seperti gambar dan stylesheet
angular.json
- Konfigurasi proyek Angular
package.json
- Daftar dependencies dan script
Fokus utama kita adalah folder
src/app/
karena di sini kita akan membuat komponen, service, dan state management.
4. Membuat Komponen Angular
Komponen adalah blok bangunan utama aplikasi Angular. Untuk membuat komponen baru, gunakan Angular CLI:
ng generate component components/todo-list
Contoh kode komponen
todo-list.component.ts
:
import { Component } from '@angular/core';
@Component({
selector: 'app-todo-list',
templateUrl: './todo-list.component.html',
styleUrls: ['./todo-list.component.scss']
})
export class TodoListComponent {
todos = [
{ id: 1, title: 'Belajar Angular', completed: false },
{ id: 2, title: 'Pelajari NgRx', completed: false },
];
toggleComplete(todo: any) {
todo.completed = !todo.completed;
}
}
Template HTML
todo-list.component.html
:
5. Routing dan Navigasi
Angular Router memungkinkan navigasi antar halaman dalam aplikasi SPA. Contoh konfigurasi routing di
app-routing.module.ts
:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TodoListComponent } from './components/todo-list/todo-list.component';
import { AboutComponent } from './components/about/about.component';
const routes: Routes = [
{ path: '', component: TodoListComponent },
{ path: 'about', component: AboutComponent },
{ path: '**', redirectTo: '' }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
Tambahkan navigasi di
app.component.html
:
Todo List
About
6. Pengenalan NgRx
NgRx adalah pustaka untuk mengelola state aplikasi Angular menggunakan pola Redux. NgRx membantu membuat state aplikasi lebih terstruktur, mudah di-debug, dan scalable.
Konsep utama NgRx:
Store:
Tempat penyimpanan state aplikasi
Actions:
Perintah untuk mengubah state
Reducers:
Fungsi yang mengubah state berdasarkan action
Selectors:
Fungsi untuk mengambil data dari store
Effects:
Menangani side effects seperti API call
7. Setup NgRx di Proyek Angular
Install paket NgRx dengan perintah:
npm install @ngrx/store @ngrx/effects @ngrx/store-devtools
Tambahkan konfigurasi Store dan Effects di
app.module.ts
:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { AppComponent } from './app.component';
import { todoReducer } from './store/todo.reducer';
import { TodoEffects } from './store/todo.effects';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
StoreModule.forRoot({ todos: todoReducer }),
EffectsModule.forRoot([TodoEffects]),
StoreDevtoolsModule.instrument({ maxAge: 25 }),
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
8. State Management dengan NgRx Store
Buat file
todo.actions.ts
untuk mendefinisikan actions:
import { createAction, props } from '@ngrx/store';
export const addTodo = createAction(
'[Todo] Add Todo',
props<{ title: string }>()
);
export const toggleTodo = createAction(
'[Todo] Toggle Todo',
props<{ id: number }>()
);
Buat file
todo.reducer.ts
untuk mengelola state:
import { createReducer, on } from '@ngrx/store';
import { addTodo, toggleTodo } from './todo.actions';
export interface Todo {
id: number;
title: string;
completed: boolean;
}
export const initialState: ReadonlyArray<Todo> = [];
export const todoReducer = createReducer(
initialState,
on(addTodo, (state, { title }) => [
...state,
{ id: state.length + 1, title, completed: false }
]),
on(toggleTodo, (state, { id }) =>
state.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
)
);
Gunakan store di komponen:
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { addTodo, toggleTodo } from '../store/todo.actions';
import { Todo } from '../store/todo.reducer';
@Component({
selector: 'app-todo-list',
templateUrl: './todo-list.component.html',
styleUrls: ['./todo-list.component.scss']
})
export class TodoListComponent {
todos$: Observable<Todo[]>;
newTodoTitle = '';
constructor(private store: Store<{ todos: Todo[] }>) {
this.todos$ = store.select('todos');
}
addTodo() {
if (this.newTodoTitle.trim()) {
this.store.dispatch(addTodo({ title: this.newTodoTitle.trim() }));
this.newTodoTitle = '';
}
}
toggleComplete(id: number) {
this.store.dispatch(toggleTodo({ id }));
}
}
Template HTML
todo-list.component.html
:
Tambah
9. Menggunakan NgRx Effects untuk Side Effects
Effects digunakan untuk menangani operasi asynchronous seperti API call. Contoh membuat effect untuk menyimpan todo ke server:
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { addTodo } from './todo.actions';
import { tap } from 'rxjs/operators';
@Injectable()
export class TodoEffects {
saveTodo$ = createEffect(() =>
this.actions$.pipe(
ofType(addTodo),
tap(action => {
// Simulasi simpan ke server
console.log('Menyimpan todo ke server:', action.title);
})
),
{ dispatch: false }
);
constructor(private actions$: Actions) {}
}
Jangan lupa daftarkan
TodoEffects
di
app.module.ts
seperti sebelumnya.
10. Selector dan Memoization
Selector digunakan untuk mengambil data dari store dengan efisien dan memoized. Contoh membuat selector:
import { createSelector, createFeatureSelector } from '@ngrx/store';
import { Todo } from './todo.reducer';
export const selectTodos = createFeatureSelector<Todo[]>('todos');
export const selectCompletedTodos = createSelector(
selectTodos,
(todos) => todos.filter(todo => todo.completed)
);
Gunakan selector di komponen:
this.completedTodos$ = this.store.select(selectCompletedTodos);
11. Contoh Proyek Nyata: Todo App dengan NgRx
Berikut adalah ringkasan kode lengkap untuk aplikasi Todo sederhana menggunakan Angular dan NgRx:
todo.actions.ts
import { createAction, props } from '@ngrx/store';
export const addTodo = createAction(
'[Todo] Add Todo',
props<{ title: string }>()
);
export const toggleTodo = createAction(
'[Todo] Toggle Todo',
props<{ id: number }>()
);
todo.reducer.ts
import { createReducer, on } from '@ngrx/store';
import { addTodo, toggleTodo } from './todo.actions';
export interface Todo {
id: number;
title: string;
completed: boolean;
}
export const initialState: ReadonlyArray<Todo> = [];
export const todoReducer = createReducer(
initialState,
on(addTodo, (state, { title }) => [
...state,
{ id: state.length + 1, title, completed: false }
]),
on(toggleTodo, (state, { id }) =>
state.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
)
);
todo.effects.ts
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { addTodo } from './todo.actions';
import { tap } from 'rxjs/operators';
@Injectable()
export class TodoEffects {
saveTodo$ = createEffect(() =>
this.actions$.pipe(
ofType(addTodo),
tap(action => {
console.log('Menyimpan todo ke server:', action.title);
})
),
{ dispatch: false }
);
constructor(private actions$: Actions) {}
}
todo.selectors.ts
import { createSelector, createFeatureSelector } from '@ngrx/store';
import { Todo } from './todo.reducer';
export const selectTodos = createFeatureSelector<Todo[]>('todos');
export const selectCompletedTodos = createSelector(
selectTodos,
(todos) => todos.filter(todo => todo.completed)
);
todo-list.component.ts
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { addTodo, toggleTodo } from '../store/todo.actions';
import { Todo } from '../store/todo.reducer';
@Component({
selector: 'app-todo-list',
templateUrl: './todo-list.component.html',
styleUrls: ['./todo-list.component.scss']
})
export class TodoListComponent {
todos$: Observable<Todo[]>;
newTodoTitle = '';
constructor(private store: Store<{ todos: Todo[] }>) {
this.todos$ = store.select('todos');
}
addTodo() {
if (this.newTodoTitle.trim()) {
this.store.dispatch(addTodo({ title: this.newTodoTitle.trim() }));
this.newTodoTitle = '';
}
}
toggleComplete(id: number) {
this.store.dispatch(toggleTodo({ id }));
}
}
todo-list.component.html
Tambah
12. Sumber Belajar dan Channel Pembelajaran
Berikut beberapa sumber dan channel yang sangat membantu untuk belajar Angular dan NgRx secara mendalam:
13. Penutup dan Tips Lanjutan
Selamat! Anda telah mempelajari dasar-dasar Angular dan NgRx serta bagaimana mengembangkan aplikasi nyata dengan state management yang baik.
Tips lanjutan untuk meningkatkan kemampuan Anda:
Pelajari Angular Forms (Template-driven dan Reactive Forms)
Gunakan Angular Material untuk UI yang konsisten dan modern
Optimalkan performa dengan lazy loading module
Gunakan NgRx Entity untuk mengelola koleksi data yang kompleks
Pelajari testing unit dan e2e untuk aplikasi Angular
Teruslah berlatih dengan membuat proyek-proyek nyata dan eksplorasi fitur-fitur Angular dan NgRx yang lebih dalam.