利用angular创建一个可复用的弹框组件

需求是当用户修改某个敏感字段的时候,此时弹出弹框需要高等级用户输入账号密码来进行确认,于是将此弹框写成可复用的组件。首先请看:dual-approval.component.html

<div class=" modal-rs" style="margin-top: -24px;margin-left: -24px;margin-right: -24px;">
  <div class="modal-content"style="background-color: #E3001A" >
    <h4 mat-dialog-title style="color: #FFFFFF;font-weight:bolder;margin-top: 35px;text-align: center">DUAL APPROVAL REQUIRED</h4>
  </div>
</div>
<p style="margin-top: 5px;color: #7f7f7f;text-align: center">In order to confirm this change,a second admin's approval is required</p>
<div style="margin-top: 130px">
  <form class="login-form-column d-flex flex-column"  [formGroup]="confirmForm" target="myframe" autocomplete="off">
    <div class="login-credentials d-flex flex-column justify-content-center align-items-center" style="height: 50%;">
      <!--username alert-->
      <div class="login-alert-wrapper">
        <div>
          <span class="login-error-alert" *ngIf="this.isFormInputInvalid('username') && this.confirmForm.get('username').hasError('required')">Second Approval's Username is required <a class="login-error-icon"></a></span>
          <span class="login-error-alert" *ngIf="this.isFormInputInvalid('username') && !this.confirmForm.get('username').hasError('required') && this.confirmForm.get('username').errors.minlength">Second Approval's Username must be at least 5 characters<a class="login-error-icon"></a></span>
          <span class="login-error-alert" *ngIf="this.isFormInputInvalid('username') && !this.confirmForm.get('username').errors.minlength  && !this.confirmForm.get('username').hasError('required') && this.confirmForm.get('username').hasError('pattern')">Second Approval's Username cannot have invalid characters<a class="login-error-icon"></a></span>
        </div>
      </div>
      <!-- username field -->
      <div class="input-group login-form">
               <span class="input-group-addon" >
                <a class="login-icon-user" ></a></span>
        <input type="text"  class="form-control" placeholder="Second Approval's Username"  required formControlName = "username"  autocomplete="off" minlength="5" maxlength="64">
      </div>
      <!-- password alert -->
      <div class="login-alert-wrapper">
        <span class="login-error-alert" *ngIf="this.isFormInputInvalid('password') && this.confirmForm.get('password').hasError('required')">Second Approval's Password is required <a class="login-error-icon"></a></span>
        <span class="login-error-alert" *ngIf="this.isFormInputInvalid('password') && !this.confirmForm.get('password').hasError('required') && this.confirmForm.get('password').errors.minlength">Second Approval's Password must be at least 5 characters <a class="login-error-icon"></a></span>
        <span class="login-error-alert" *ngIf="this.isFormInputInvalid('password') && !this.confirmForm.get('password').errors.minlength  && !this.confirmForm.get('password').hasError('required') && this.confirmForm.get('password').hasError('pattern')">Second Approval's Password cannot have invalid characters<a class="login-error-icon"></a></span>
      </div>
      <!-- password field -->
      <div class="input-group login-form">
              <span class="input-group-addon">
                <a class="login-icon-password"></a></span>
        <input type="text" class="form-control text-security" placeholder="Second Approval's Password" id="password" required formControlName="password" minlength="5" maxlength="64">
      </div>
      <!-- reason alert -->
      <div class="login-alert-wrapper">
        <span class="login-error-alert" *ngIf="this.isFormInputInvalid('reason') && this.confirmForm.get('reason').hasError('required')">Reason is required <a class="login-error-icon"></a></span>
      </div>
      <div class="input-group login-form" style="margin-top: 20px">
        <textarea id="reason" name="reason" rows="8" class="form-control"  formControlName="reason" minlength="1" maxlength="399" placeholder="Please describe your reason for this change..." required></textarea>
      </div>
    </div>
  </form>
  <div mat-dialog-actions >
    <input class="btn btn-red-rs6" type="submit" (click)="onConfirm()" [disabled]="!confirmForm.valid" value="Confirm" style="margin-left: 80px;margin-bottom: 30px">
    <input class="btn btn-red-rs6" type="button" (click)="onClose()"  value="Cancel" style="margin-left: 205px;margin-bottom: 30px;width: 77px">
  </div>
  <iframe name="myframe" hidden ></iframe>
</div>


接下来是dual-approval.component.ts文件
 

import {Component, Inject} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {DialogService} from '../../service/dialog.service';
import {Utility} from '../../utility/utility';
import {DualApprovalService} from '../../service/dual-approval.service';
import {DualApproval} from '../../model/dual-approval.model';
import {Audit} from '../../model/audit.model';
import {ObjectType} from '../../model/object-type.model';
import {OperationType} from '../../model/operation-type.model';
@Component({
  selector: 'app-dual-approval',
  templateUrl: './dual-approval.component.html'
})
export class DualApprovalComponent {
  confirmForm: FormGroup;
  model: DualApproval = {username: '', password: '', reason: ''};

  targetUser = '';

  constructor(private fb: FormBuilder,
              public dialog: MatDialog, public dialogRef: MatDialogRef<DualApprovalComponent>,
              public dualApprovalService: DualApprovalService, @Inject(MAT_DIALOG_DATA) public data: any) {
    this.createForm();
  }

  private createForm() {
    this.confirmForm = this.fb.group({
      username: ['', [Validators.required,
        Validators.pattern(/^((?![<>/\\~"{}\[\]*'|`:;,\s]).){5,64}$/g.source)]],
      password: ['', [Validators.required,
        Validators.pattern(/^((?![<>/\\~"{}\[\]*'|`:;,\s]).){5,64}$/g.source)]],
      reason: []
    });
  }

  updateModel() {
    this.model.username = this.confirmForm.get('username').value;
    this.model.password = this.confirmForm.get('password').value;
    this.model.reason = this.confirmForm.get('reason').value;
  }

  /**
   * Submit the form after you click on onConfirm button in html.
   */
  onConfirm() {
    this.updateModel();
    this.targetUser = this.data['targetUserName'];
    this.dualApprovalService.verifyHierarchy(this.targetUser, this.model.username,
      this.model.password).toPromise().then((res) => {
      this.dialogRef.close(res);
      const result = Utility.isDualApprovalResponseSuccess(res);
      if (result) {
        this.sendAuditLog().toPromise().then();
      }
    });
  }

  /**
   * Close the dual approval pop-up.
   */
  onClose() {
    this.dialogRef.close();
  }

  /**
   * Verify the validity of input box contents.
   * @param input The contents of input box.
   * @returns Return value here is true if the input is valid and false otherwise.
   */
  isFormInputInvalid(input: string): boolean {
    return Utility.isFormInputInvalid(input, this.confirmForm);
  }

  /**
   * Collect the audit info to send a post request to backend.
   * @returns creating a audit logs of the operations.
   */
  sendAuditLog() {
    const audit = new Audit();
    audit.objectId = this.data['objectId'];
    if (this.data['objectType'].match('Organization')) {
      audit.objectType = ObjectType.Organization;
      audit.operation = OperationType.UpdateOrganization;
    } else if (this.data['objectType'].match('User')) {
      audit.objectType = ObjectType.User;
      audit.operation = OperationType.UpdateUser;
    } else {
      audit.objectType = ObjectType.Unknown;
    }
    audit.field = this.data['fieldName'];
    audit.oldValue = this.data['oldValue'];
    audit.newValue = this.data['newValue'];
    audit.details = this.model.reason;

    return this.dualApprovalService.auditLog(audit); // 请求后端保存日志
  }
}

Utility.ts:
 

import {Injectable} from '@angular/core';
import {FormGroup} from '@angular/forms';

@Injectable()
export class Utility {

  constructor() {
  }

static isFormInputInvalid(input: string, form: FormGroup): boolean {
    return form.get(input).touched && form.get(input).status === 'INVALID';
  }

/**
   * Determine if the dual approval's verify hierarchy is successful.
   * @param response response object of dual approval's verify hierarchy.
   * @returns  dual approval's verify hierarchy successfully return true,
   *           dual approval's verify hierarchy failed return false.
   */
  static isDualApprovalResponseSuccess(response: any): boolean {
    if (response['body']['rsErrorCode'] === undefined) {
      return true;
    } else {
      return false;
    }
  }
}

dual-approval.component.spec.ts


import {async, TestBed} from '@angular/core/testing';
import {Observable} from 'rxjs/Observable';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {DualApprovalComponent} from './dual-approval.component';
import {DialogService} from '../../service/dialog.service';
import {DualApprovalService} from '../../service/dual-approval.service';
import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
import {HttpResponse} from '@angular/common/http';
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material';

describe('DualApprovalComponent', () => {
  beforeEach(async(() => {
    class DialogServiceStub {
      openDialog(title, msg) {
        return Observable.of('OK');
      }
    }

    class DualApprovalServiceStub {
      verifyHierarchy(targetUser: string, userName: string, password: string) {
        const response = new HttpResponse({body: {message: 'Response Message'}});
        return Observable.of(
          response
        );
      }
    }

    class MatDialogStub {

    }

    class MatDialogRefStub {

    }

    TestBed.configureTestingModule({
      imports: [FormsModule, ReactiveFormsModule],
      declarations: [DualApprovalComponent],
      providers: [
        {provide: DialogService, useClass: DialogServiceStub},
        {provide: DualApprovalService, useClass: DualApprovalServiceStub},
        {provide: MatDialog, useClass: MatDialogStub},
        {provide: MAT_DIALOG_DATA, useValue: {}},
        {provide: MatDialogRef, useClass: MatDialogRefStub}
      ],
      schemas: [CUSTOM_ELEMENTS_SCHEMA]
    })
      .compileComponents();
  }));

  it('should create DualApprovalComponent', () => {
    const fixture = TestBed.createComponent(DualApprovalComponent);
    const comp = fixture.debugElement.componentInstance;

    expect(comp).toBeTruthy();
  });

  it('should return the correct response from verifyHierarchy', () => {
    const fixture = TestBed.createComponent(DualApprovalComponent);
    const result = fixture.componentInstance.dualApprovalService.verifyHierarchy('', '', '');
    result.subscribe((response: HttpResponse<{ message: string }>) => {
      expect(response.body.message).toEqual('Response Message');
    });
  });

  it('should verify username', () => {
    const fixture = TestBed.createComponent(DualApprovalComponent);
    const comp = fixture.debugElement.componentInstance;

    fixture.detectChanges();
    comp.confirmForm.get('username').setValue('');
    expect(comp.confirmForm.get('username').invalid).toBe(true, 'Second Approval\'s Username is required');

    comp.confirmForm.get('username').setValue('<>/');
    expect(comp.confirmForm.get('username').invalid).toBe(true, 'Second Approval\'s Username cannot have invalid characters');

    comp.confirmForm.get('username').setValue('user');
    expect(comp.confirmForm.get('username').invalid).toBe(true, 'Second Approval\'s Username must be at least 5 characters');

  });

  it('should verify password', () => {
    const fixture = TestBed.createComponent(DualApprovalComponent);
    const comp = fixture.debugElement.componentInstance;

    fixture.detectChanges();
    comp.confirmForm.get('password').setValue('');
    expect(comp.confirmForm.get('password').invalid).toBe(true, 'Second Approval\'s Username is required');

    comp.confirmForm.get('password').setValue('<>/');
    expect(comp.confirmForm.get('password').invalid).toBe(true, 'Second Approval\'s Username cannot have invalid characters');

    comp.confirmForm.get('password').setValue('1111');
    expect(comp.confirmForm.get('password').invalid).toBe(true, 'Second Approval\'s Username must be at least 5 characters');

  });

  it('should verify reason', () => {
    const fixture = TestBed.createComponent(DualApprovalComponent);
    const comp = fixture.debugElement.componentInstance;

    fixture.detectChanges();
    comp.confirmForm.get('reason').setValue('');
    expect(comp.confirmForm.get('password').invalid).toBe(true, 'Reason is required');
  });
});


希望对其他人也有所帮助!博主能力有限,若有不足之处还请批评指出,谢谢!

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值