Theory
ચતુર navigation અને વહેંચાયેલી state
પાયાનું routing કોઈ URL ને component સાથે જોડે છે. ખરાં apps ને એથી વધુ જોઈએ: ભારે pages ની મુલાકાત લેવાય ત્યારે જ એમને લાવવાં, વગર અધિકારવાળા વપરાશકર્તાઓને કોઈ page સુધી પહોંચતાં રોકવા, અડધું ભરેલું form છોડતાં પહેલાં ચેતવવું, અને page દેખાય એ જ ક્ષણે data તૈયાર રાખવો. વળી app માં ફેલાયેલાં components ને ઘણી વાર એક જ બદલાતી state વહેંચવી પડે છે, જેમ કે કોણ login થયેલું છે.
Angular આ માટે ચાર સાધનો આપે છે: lazy loading, route guards, resolvers અને RxJS Subjects. આ પાઠ દરેકનો પરિચય આપે છે, જેથી FestConnect સમજદારીથી navigate કરી શકે અને પોતાની state મેળમાં રાખી શકે.
At a glance
| સાધન | એ શું કરે છે |
|---|---|
| Lazy loading | Route નો code વપરાશકર્તા ત્યાં જાય ત્યારે જ લાવે છે (શરૂઆતનું ભારણ ઓછું) |
| CanActivate guard | Route માં પ્રવેશ મળે કે નહીં એ નક્કી કરે છે (દા.ત. login થયેલું હોવું જોઈએ) |
| CanDeactivate guard | વપરાશકર્તા બહાર નીકળી શકે કે નહીં એ નક્કી કરે છે (દા.ત. સાચવ્યા વગરના ફેરફારની ચેતવણી) |
| Resolver | Route ચાલુ થાય એ પહેલાં data લાવે છે, જેથી page પાસે એ તૈયાર હોય |
| RxJS Subject અને BehaviorSubject | Components વચ્ચે બદલાતી state વહેંચે છે (BehaviorSubject હાલની કિંમત પણ સાચવે છે) |
Practical
Lazy loading અને functional route guard વાપરવાં
import { Routes } from '@angular/router';
import { inject } from '@angular/core';
import { AuthService } from './auth.service';
// A functional CanActivate guard (Angular 17 style)
const authGuard = () => inject(AuthService).isLoggedIn();
export const routes: Routes = [
{ path: 'events', loadComponent: () => // lazy: loaded on demand
import('./events/events.component').then(m => m.EventsComponent) },
{ path: 'profile', canActivate: [authGuard], // blocked unless logged in
loadComponent: () =>
import('./profile/profile.component').then(m => m.ProfileComponent) },
];Theory
Guards, resolvers અને એ કેમ મદદ કરે છે
CanActivate route load થાય એ પહેલાં ચાલે છે અને true કે false પાછું આપે છે: FestConnect વપરાશકર્તા login ન થયો હોય ત્યાં સુધી /profile રોકી શકે છે. CanDeactivate વપરાશકર્તા બહાર નીકળવા જાય ત્યારે ચાલે છે: જો registration ના form માં એના સાચવ્યા વગરના ફેરફારો હોય, તો એ પહેલાં ચેતવી શકે છે. Resolvers route નો data અગાઉથી લાવી આપે છે, એટલે events નું page ખૂલે ત્યારે એની યાદી પહેલેથી જ ભરાયેલી હોય છે, અને કોરી screen નો ઝબકારો દેખાતો નથી.
એ ત્રણેય મળીને navigation ને વિચારેલું અને સલામત બનાવે છે: સાચી વ્યક્તિ સાચા page પર, સાચા સમયે, અને data તૈયાર હોય એ સ્થિતિમાં પહોંચે છે.
Practical
વહેંચાયેલી state માટે BehaviorSubject (હાલનો વપરાશકર્તા)
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class AuthService {
// BehaviorSubject holds a CURRENT value and emits it to new subscribers
private userSubject = new BehaviorSubject<string | null>(null);
user$ = this.userSubject.asObservable();
login(name: string) { this.userSubject.next(name); } // push a new value
logout() { this.userSubject.next(null); }
}
// Any component can subscribe to user$ and always get the latest logged-in user.Quiz
તમારે login ન થયેલા વપરાશકર્તાઓને `/profile` ખોલતાં રોકવા છે. કયું routing નું સાધન બંધબેસે?
- Resolver, કારણ કે એ data લાવે છે
- CanActivate guard, જે route માં પ્રવેશ મળે કે નહીં એ નક્કી કરે છે
- Lazy loading, કારણ કે એ page છુપાવે છે
- CanDeactivate guard, કારણ કે એ બહાર નીકળવા પર કાબૂ રાખે છે
Show the answer
CanActivate guard, જે route માં પ્રવેશ મળે કે નહીં એ નક્કી કરે છે
CanActivate guard route માં પ્રવેશ થાય એ પહેલાં ચાલે છે અને true કે false પાછું આપે છે, એટલે વપરાશકર્તા login ન થાય ત્યાં સુધી /profile ને રોકનારું બરાબર એ જ છે. વિકલ્પ A, એટલે કે resolver, route માટે data અગાઉથી લાવે છે; પ્રવેશ આપવો કે નહીં એ એ નક્કી કરતું નથી. વિકલ્પ C, એટલે કે lazy loading, route નો code ક્યારે લવાય એના પર (જરૂર પડ્યે) કાબૂ રાખે છે, અને એ performance માટે છે; એ પ્રવેશના નિયમો લાગુ પાડતું નથી. વિકલ્પ D, એટલે કે CanDeactivate, route માંથી બહાર નીકળવા પર કાબૂ રાખે છે (જેમ કે સાચવ્યા વગરના ફેરફારની ચેતવણી), એટલે એ આપણને જોઈએ છે એનાથી ઊંધી દિશા છે. Route માં પ્રવેશ CanActivate સંભાળે છે; એમાંથી બહાર નીકળવું CanDeactivate સંભાળે છે.
Think first
App ની વહેંચાયેલી state માટે સાદા Subject કરતાં BehaviorSubject કેમ સારું?
Subject અને BehaviorSubject, બંને કિંમતો પ્રસારે છે. તો હાલના વપરાશકર્તા જેવી state માટે BehaviorSubject કેમ પસંદ કરાય? વિચારીને પછી tap કરો.
Show the answer
કારણ કે BehaviorSubject પોતાની હાલની કિંમત યાદ રાખે છે અને પછીથી subscribe કરનારા દરેક component ને એ તરત આપી દે છે, જ્યારે સાદું Subject તો કિંમત ધકેલાય એ ક્ષણે જે સાંભળતા હોય એમને જ મોકલે છે.
FestConnect માં login થયેલા વપરાશકર્તાનો દાખલો લો. ધારો કે વપરાશકર્તા વહેલો login થઈ ગયો, અને પછી બીજે ક્યાંક કોઈ component (navbar કે profile widget) જાણવા માટે subscribe કરે છે કે કોણ login થયેલું છે. સાદા Subject સાથે એ મોડું subscribe કરનારને હવે પછી કિંમત ધકેલાય ત્યાં સુધી કશું સંભળાય જ નહીં, એટલે ફરી login કે logout ન થાય ત્યાં સુધી એને વપરાશકર્તાની ખબર જ ન પડે, અને UI મેળ બહાર રહી જાય.
એની સામે BehaviorSubject હાલની કિંમત સાથે બને છે (કે એને સાચવે છે) અને દરેક નવા subscriber ને એ subscribe કરે એ જ ક્ષણે છેલ્લી કિંમત ફરી મોકલે છે, એટલે navbar ને તરત જ ખબર પડી જાય છે કે વપરાશકર્તા પહેલેથી login થયેલો છે.
'હાથ પર હંમેશા હાલની કિંમત હોવી' એ વર્તન બરાબર એ જ છે જે વહેંચાયેલી state ને જોઈએ: state એવી વસ્તુ છે જેની કિંમત દરેક ક્ષણે હોય છે, અને પૂછનારા દરેક component ને હાલની કિંમત મળવી જોઈએ, ફક્ત ભવિષ્યના ફેરફારો નહીં. સાદું Subject એક વખતની ઘટનાઓ માટે વધુ સારું છે (button નું click, notification), જ્યાં ફરી મોકલવા જેવી કોઈ અર્થપૂર્ણ 'હાલની કિંમત' હોતી જ નથી.
અંગૂઠાનો નિયમ આ રહ્યો: state માટે BehaviorSubject (જ્યાં હાલની કિંમત મહત્ત્વની છે), ઘટનાઓ માટે Subject (જ્યાં ફક્ત એ ક્ષણ મહત્ત્વની છે). હાલની કિંમત ફરી મોકલવાની આ ખાસિયત જ BehaviorSubject ને app ની state માટે યોગ્ય સાધન બનાવે છે.
Summary
Key takeaways
- Lazy loading route નો code વપરાશકર્તા ત્યાં જાય ત્યારે જ લાવે છે, જેથી શરૂઆતનું bundle નાનું રહે છે.
- CanActivate guards route માં પ્રવેશ મળે કે નહીં એ નક્કી કરે છે (દા.ત. login થયેલું હોવું જોઈએ); Angular 17 functional guards વાપરે છે.
- CanDeactivate guards વપરાશકર્તા બહાર નીકળી શકે કે નહીં એ નક્કી કરે છે (દા.ત. સાચવ્યા વગરના ફેરફારની ચેતવણી).
- Resolvers route ચાલુ થાય એ પહેલાં એનો data લાવે છે, જેથી page ખૂલે ત્યારે data તૈયાર હોય.
- RxJS Subjects components વચ્ચે બદલાતી state વહેંચે છે; BehaviorSubject હાલની કિંમત પણ સાચવે છે.
- BehaviorSubject app ની state (જેમ કે હાલનો વપરાશકર્તા) માટે બંધબેસે છે, કારણ કે એ નવા subscribers ને છેલ્લી કિંમત ફરી મોકલે છે.
- યાદ રાખવાની કડી: ઝડપ માટે lazy loading, પ્રવેશ માટે guards, data માટે resolvers, અને વહેંચાયેલી state માટે BehaviorSubject.