- NativeScript for Angular Mobile Development
- Nathan Walker Nathanael J. Anderson
- 750字
- 2021-07-02 18:41:50
Integrating DialogService into our component
Let's open up track-list.component.ts and inject DialogService for use in our record method. We will also need to determine if the user is logged in to conditionally display a login dialog or confirm prompt, so let's also inject AuthService:
// angular
import { Component, Input } from '@angular/core';
// app
import { ITrack } from '../../../core/models';
import { AuthService, LogService, DialogService } from '../../../core/services';
import { PlayerService } from '../../services/player.service';
@Component({
moduleId: module.id,
selector: 'track-list',
templateUrl: 'track-list.component.html'
})
export class TrackListComponent {
constructor(
private authService: AuthService,
private logService: LogService,
private dialogService: DialogService,
public playerService: PlayerService
) { }
public record(track: ITrack, usernameAttempt?: string) {
if (AuthService.CURRENT_USER) {
this.dialogService.confirm(
'Are you sure you want to re-record this track?'
).then((ok) => {
if (ok) this._navToRecord(track);
});
} else {
this.authService.promptLogin(
'Provide an email and password to record.',
usernameAttempt
).then(
this._navToRecord.bind(this, track),
(usernameAttempt) => {
// initiate sequence again
this.record(track, usernameAttempt);
}
);
}
}
private _navToRecord(track: ITrack) {
// TODO: navigate to record screen
this.logService.debug('yes, re-record', track);
}
}
The record method now first checks to see whether a user is authenticated via the static AuthService.CURRENT_USER reference, which is set when AuthService is first constructed via Angular's dependency injection upon app launch (see Chapter 2, Feature Modules).
If a user is authenticated, we present a confirmation dialog to ensure the action was intentional.
If the user is not authenticated, we want to prompt the user to log in. To reduce the overload for this book, we will assume the user is already registered via a backend API, so we won't be asking the user to register.
We need to implement the promptLogin method in AuthService to persist the user's login credentials, so every time they return to the app, it will automatically log them in. The record method now provides an extra optional argument usernameAttempt, which will be useful to repopulate the username field of the login prompt when reinitiating the login sequence after a user input validation error. We won't do a thorough validation of user input here, but we can at least do a lightweight check for a valid email.
To maintain a clean separation of concerns, open app/modules/core/services/auth.service.ts to implement promptLogin. Here's the entire service with the modifications:
// angular
import { Injectable } from '@angular/core';
// lib
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
// app
import { DatabaseService } from './database.service';
import { DialogService } from './dialog.service';
import { LogService } from './log.service';
@Injectable()
export class AuthService {
// access our current user from anywhere
public static CURRENT_USER: any;
// subscribe to authenticated state changes
public authenticated$: BehaviorSubject<boolean> =
new BehaviorSubject(false);
constructor(
private databaseService: DatabaseService,
private dialogService: DialogService,
private logService: LogService
) {
this._init();
}
public promptLogin(msg: string, username: string = '')
: Promise<any> {
return new Promise((resolve, reject) => {
this.dialogService.login(msg, username, '')
.then((input) => {
if (input.result) { // result = false when canceled
if (input.userName &&
input.userName.indexOf('@') > -1) {
if (input.password) {
// persist user credentials
this._saveUser(
input.userName, input.password
);
resolve();
} else {
this.dialogService.alert(
'You must provide a password.'
).then(reject.bind(this, input.userName));
}
} else {
// reject, passing userName back
this.dialogService.alert(
'You must provide a valid email address.'
).then(reject.bind(this, input.userName));
}
}
});
});
}
private _saveUser(username: string, password: string) {
AuthService.CURRENT_USER = { username, password };
this.databaseService.setItem(
DatabaseService.KEYS.currentUser,
AuthService.CURRENT_USER
);
this._notifyState(true);
}
private _init() {
AuthService.CURRENT_USER =
this.databaseService
.getItem(DatabaseService.KEYS.currentUser);
this.logService.debug(
`Current user: `, AuthService.CURRENT_USER
);
this._notifyState(!!AuthService.CURRENT_USER);
}
private _notifyState(auth: boolean) {
this.authenticated$.next(auth);
}
}
We use the dialogService.login method to open a native login dialog, allowing the user to input a username and password. Once they choose ok, we do minimal validation of the input and, if successful, proceed to persist the username and password via DatabaseService. Otherwise, we simply alert the user of an error and reject our promise, passing along the username that was entered. This allows us to help the user out by redisplaying the login dialog with the failed username they entered, so they can more easily make corrections.
With these service level details complete, the track-list component is looking pretty good. However, there is one additional step we should take while we are working on this. If you recall, our TrackModel contains an order property that will help the user order the tracks in any way they'd like for convenience.
- Moodle Administration Essentials
- Learning Data Mining with Python
- Building a Recommendation Engine with Scala
- Interactive Applications Using Matplotlib
- Visual Basic學(xué)習(xí)手冊(cè)
- Selenium Testing Tools Cookbook(Second Edition)
- Unity&VR游戲美術(shù)設(shè)計(jì)實(shí)戰(zhàn)
- Cocos2d-x Game Development Blueprints
- Java Web從入門到精通(第3版)
- Programming Microsoft Dynamics? NAV 2015
- Everyday Data Structures
- 高效使用Greenplum:入門、進(jìn)階與數(shù)據(jù)中臺(tái)
- ROS機(jī)器人編程實(shí)戰(zhàn)
- 從零開始學(xué)算法:基于Python
- Less Web Development Cookbook