JHipster一知半解- 4.6.10 webapp-account目錄

回文集目錄:JHipster一知半解

概述與模塊說明

經(jīng)過前面對共享模塊,布局部分的剖析可以看出JHipster的頁面模塊劃分了,剩余的機構(gòu)子模塊,都只是根據(jù)不同的路由,替換掉主頁上<outlet>部分,已完成不同的具體功能。  
account目錄包含賬戶管理的功能,有JHipster實現(xiàn)了一套簡單而標準的模型,用戶可以實現(xiàn)(注冊-激活)、(忘記密碼-修改)、密碼修改、用戶信息修改功能。  
按照前后端分離的策略,后端僅提供API接口的調(diào)用響應(yīng),用戶界面的展現(xiàn),邏輯都在前端進行。主題上可以分為API服務(wù)調(diào)用,路由控制,組件邏輯與展現(xiàn)3個部分。
在看具體的子功能前,先查看AccountModule的部分。
@NgModule({
    //引入共享模塊,并forChild加載accountState路由
    imports: [
        JhipsterSampleApplicationNg2SharedModule,
        RouterModule.forChild(accountState)
    ],
    //聲明內(nèi)部的組件(相對簡單,沒有指令)
    declarations: [
        ActivateComponent,
        RegisterComponent,
        PasswordComponent,
        PasswordStrengthBarComponent,
        PasswordResetInitComponent,
        PasswordResetFinishComponent,
        SettingsComponent
    ],
    //聲明內(nèi)部的服務(wù),都是與后端通訊的封裝
    providers: [
        Register,
        ActivateService,
        PasswordService,
        PasswordResetInitService,
        PasswordResetFinishService
    ],
    //已分析過,支持‘-‘命名
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class JhipsterSampleApplicationNg2AccountModule {}

路由配置

每個component組件都需占主體部分,因此path各不相同。

activate.route.ts

export const activateRoute: Route = {
    //路徑名我active
    path: 'activate',
    component: ActivateComponent,
    data: {
        //無需權(quán)限
        authorities: [],
        pageTitle: 'activate.title'
    },
    //路由守衛(wèi)為UserRouteAccessService,由于authorities是空數(shù)組,始終是允許的。但是守衛(wèi)會調(diào)用principal.identity()從后端獲取用戶信息。
    canActivate: [UserRouteAccessService,]
};

password.route.ts

password-reset-finish.route.ts

password-reset-init.route.ts

settings.route.ts

這幾個路由也類似,password和setting增加需要“'ROLE_USER'”權(quán)限

register.route.ts

export const registerRoute: Route = {
    path: 'register',
    component: RegisterComponent,
    data: {
        authorities: [],
        pageTitle: 'register.title'
    }
};
可以看到registerRoute并沒有聲明路由守衛(wèi),因為要注冊,那么必然沒有用戶信息,也就無需獲取用戶信息了。

服務(wù)調(diào)用

activate.service.ts

@Injectable()
export class ActivateService {
    //注入封裝過的http客戶端
    constructor(private http: Http) {}
    //設(shè)置params,調(diào)用通訊API,返回Observable
    get(key: string): Observable<any> {
        const params: URLSearchParams = new URLSearchParams();
        params.set('key', key);

        return this.http.get(SERVER_API_URL + 'api/activate', {
            search: params
        }).map((res: Response) => res);
    }
}

password.service.ts

password-reset-finish.service.ts

password-reset-init.service.ts

register.service.ts.ts

代碼也類似,十分簡單。值得注意的是setting并沒單獨的service。用戶信息保存是AccountService的一部分,直接調(diào)用即可。

功能組件

組件都使用模板表單的構(gòu)造方式,通過在html中定義ngModel進行數(shù)據(jù)綁定,通過定義內(nèi)部狀態(tài),控制表單的提示信息。以下僅分析register組件源碼

register.component.ts

export class RegisterComponent implements OnInit, AfterViewInit {

    confirmPassword: string;
    doNotMatch: string;
    error: string;
    errorEmailExists: string;
    errorUserExists: string;
    registerAccount: any;
    success: boolean;
    modalRef: NgbModalRef;
    //注入語言服務(wù),登錄框,注冊服務(wù),以及標簽本身,繪制器
    constructor(
        private languageService: JhiLanguageService,
        private loginModalService: LoginModalService,
        private registerService: Register,
        private elementRef: ElementRef,
        private renderer: Renderer
    ) {
    }

    ngOnInit() {
        this.success = false;
        this.registerAccount = {};
    }
    //默認激活login按鈕
    ngAfterViewInit() {
        this.renderer.invokeElementMethod(this.elementRef.nativeElement.querySelector('#login'), 'focus', []);
    }

    register() {
        //并非實時判斷兩個input的匹配程度,提交的時候才會判斷,如果不匹配,就提示錯誤
        if (this.registerAccount.password !== this.confirmPassword) {
            this.doNotMatch = 'ERROR';
        } else {
            //兩個密碼框相符,則進行注冊接口調(diào)用。
            this.doNotMatch = null;
            this.error = null;
            this.errorUserExists = null;
            this.errorEmailExists = null;
            this.languageService.getCurrent().then((key) => {
                this.registerAccount.langKey = key;
                this.registerService.save(this.registerAccount).subscribe(() => {
                    this.success = true;
                }, (response) => this.processError(response));
            });
        }
    }
    //通用的登錄框顯示
    openLogin() {
        this.modalRef = this.loginModalService.open();
    }
    //錯誤的response處理,出錯時候返回type表示不同錯誤
    private processError(response) {
        this.success = null;
        if (response.status === 400 && response.json().type === LOGIN_ALREADY_USED_TYPE) {
            this.errorUserExists = 'ERROR';
        } else if (response.status === 400 && response.json().type === EMAIL_ALREADY_USED_TYPE) {
            this.errorEmailExists = 'ERROR';
        } else {
            this.error = 'ERROR';
        }
    }
}

register.component.html

<div>
    <div class="row justify-content-center">
        <div class="col-md-8">
            <h1 jhiTranslate="register.title">Registration</h1>
            <!-- 成功提示,僅當注冊成功時顯示 -->
            <div class="alert alert-success" *ngIf="success" jhiTranslate="register.messages.success">
                <strong>Registration saved!</strong> Please check your email for confirmation.
            </div>
            <!-- 失敗提示,僅當注冊失敗時顯示 -->
            <div class="alert alert-danger" *ngIf="error" jhiTranslate="register.messages.error.fail">
                <strong>Registration failed!</strong> Please try again later.
            </div>
            <!-- 失敗提示,僅當注冊失敗,且服務(wù)器返回用戶已存在時顯示 -->
            <div class="alert alert-danger" *ngIf="errorUserExists" jhiTranslate="register.messages.error.userexists">
                <strong>Login name already registered!</strong> Please choose another one.
            </div>
            <!-- 失敗提示,僅當注冊失敗,且服務(wù)器返回注冊Email已存在時顯示 -->
            <div class="alert alert-danger" *ngIf="errorEmailExists" jhiTranslate="register.messages.error.emailexists">
                <strong>Email is already in use!</strong> Please choose another one.
            </div>
            <!-- 失敗提示,僅當兩個密碼輸入框不符時顯示 -->
            <div class="alert alert-danger" *ngIf="doNotMatch" jhiTranslate="global.messages.error.dontmatch">
                The password and its confirmation do not match!
            </div>
        </div>
    </div>
    <div class="row justify-content-center">
        <div class="col-md-8">
            <!-- 窗體form定義,提交方法為register,如果注冊成功,就不顯示了 -->
            <form name="form" role="form" (ngSubmit)="register()" #registerForm="ngForm" *ngIf="!success">
                <div class="form-group">
                    <label class="form-control-label" for="login" jhiTranslate="global.form.username">Username</label>
                    <!-- 標準的模板方式生成窗體方式,使用ngModel綁定值到login,后面定義了一系列angular的驗證器 -->
                    <input type="text" class="form-control" [(ngModel)]="registerAccount.login" id="login" name="login" #login="ngModel" placeholder="{{'global.form.username.placeholder' | translate}}" required minlength="1" maxlength="50" pattern="^[_'.@A-Za-z0-9-]*$">
                    <!-- 統(tǒng)一的錯誤提示div,包含多個small提示,根據(jù)不同的錯誤類型,有不同的提示 -->
                    <div *ngIf="login.dirty && login.invalid">
                        <small class="form-text text-danger" *ngIf="login.errors.required" jhiTranslate="register.messages.validate.login.required">
                            Your username is required.
                        </small>
                        <small class="form-text text-danger" *ngIf="login.errors.minlength" jhiTranslate="register.messages.validate.login.minlength">
                            Your username is required to be at least 1 character.
                        </small>
                        <small class="form-text text-danger" *ngIf="login.errors.maxlength" jhiTranslate="register.messages.validate.login.maxlength">
                            Your username cannot be longer than 50 characters.
                        </small>
                        <small class="form-text text-danger" *ngIf="login.errors.pattern" jhiTranslate="register.messages.validate.login.pattern">
                            Your username can only contain lower-case letters and digits.
                        </small>
                    </div>
                </div>
                <!-- 省略email,密碼,確認密碼框 -->
                
                <!-- 如果窗體不合法,就disable提交按鈕 -->
                <button type="submit" [disabled]="registerForm.form.invalid" class="btn btn-primary" jhiTranslate="register.form.button">Register</button>
            </form>
            <p></p>
            <!-- 窗體之外,增加默認用戶的說明 -->
            <div class="alert alert-warning">
                <span jhiTranslate="global.messages.info.authenticated.prefix">If you want to </span>
                <a class="alert-link" (click)="openLogin()" jhiTranslate="global.messages.info.authenticated.link">sign in</a><span jhiTranslate="global.messages.info.authenticated.suffix">, you can try the default accounts:<br/>- Administrator (login="admin" and password="admin") <br/>- User (login="user" and password="user").</span>
            </div>
        </div>
    </div>
</div>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容