CS5220 Advanced Topics in Web Programming Angular – Services Chengyu Sun California State University, Los Angeles
Services Classes that implement business logic of an application Angular can make service classes available to other parts of the application via dependency injection
How Dependency Injection Works Declare something to be injectable Determine where to inject Have some mechanism to perform injection Injectables Inject Recipients
Dependency Injection in Spring Any bean can be injected into other beans Annotations, e.g. @Component Bean configuration file, e.g. <bean> Any bean can receive injection Auto wiring (default by type) Bean configuration file, e.g. property and ref Injection means Field, Setter, and Constructor
Dependency Injection in Angular Injectables (usually service classes and data) are either declared in providers of @NgModule, or decorated with @Injectable Injection via constructor Auto wiring by token
Declare Injectables in @NgModule Type Token providers: [ { provide: UserService, useClass: UserService }, { provide: 'SECRET', useValue: 'abcd' } ] String Token providers: [ UserService, { provide: 'SECRET', useValue: 'abcd' } ]
Declare Injectables Using @Injectable Inject using the application's root injector @Injectable({ providedIn: 'root' }) export class UserService { … } Angular's dependency injection system is hierarchical – injection can be done at the root, module, and component level
Constructor Injection Class HomeComponent { constructor( private UserService: userService, @Inject('SECRET') private secret: string ) {} }
Example: GuestBook … App Component entries[] @Input @Output GuestBook AddEntry Component
… Example: GuestBook App Component GuestBook Component AddEntry REST API Data Service
GuestBook Backend A simple Node.js server application generated using Express Generator Use a global array to hold GuestBook entries Two endpoints at /api/guestbook GET: get all entries POST: add an entry
Set Up Proxy During Development … NG Server at Port 4200 Angular App Browser REST API Call API Server at Port 3000 (or 8080) For security reasons, browsers enforce same-origin policy on XMLHttpRequest Localhost
… Set Up Proxy During Development … NG Server at Port 4200 Angular App REST API Call Browser API Server at Port 3000 (or 8080) Localhost
… Set Up Proxy During Development Create proxy configuration file proxy.conf.json, e.g. { "/api": { "target": "http://localhost:3000", "secure": false } Change start script in package.json ng serve --proxy-config proxy.conf.json
Create DataService Use Angular CLI to generate a service ng generate service <name> Naming conventions Inject it to component classes
Use HttpClient to Access REST API Import HttpClientModule from @angular/common/http Provides an HttpClient service that can be used to make HTTP requests Inject HttpClient services into the service class that will use it to make REST API calls
Get GuestBook Entries from Server In DataService: ?? getEntries(): Observable<GuestBookEntry[]> { return this.http.get<GuestBookEntry[]>('/api/guestbook'); } Angular automatically converts the response body into an array of GuestBookEntry Send a GET request In GuestBookComponent: ngOnInit() { this.dataService.getEntries().subscribe(entries => { this.entries = entries; }); } ??
Observable and Subscription An Observable represents a value or a set of values that change over time A Subscription allows a subscriber to be notified whenever the value(s) of an observable changes
Asynchronous Programming Paradigms Callback Function for event handling Promise for something that eventually produces a single result Observable for continuously changing data / data stream
Implement AddEntry The server API returns the newly added entry, but how do we notify GuestBookComponent to update its display?
Implementation Strategy Keep a local entries array in DataService and make it observable Add the newly added entry to the local entries array after the POST call GuestBookComponent subscribes to the local entries array to automatically get the new data when the array changes
A Bit More RxJS Observer Observer Observable Subject … … Observer … … Observer A Subject is a special type of Observable that allows values to be multicasted to many Observers.
Some Subject Methods next(value) emits the next value error(err) emits an error complete() indicates that the data stream has ended and all subscribers are unsubscribed
BehaviorSubject What if some subscriber comes in late (i.e. after some values are already emitted)? BehaviorSubject is a type of Subject that keeps the latest value vs ReplaySubject
Readings Angular HttpClient Guide RxJS Overview