<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Angular響應式表單及封裝表單控件

      響應式表單也叫模型驅動型表單。

      有三個重要元素FormControl,FormGroup和FormBuilder。還有一個FormArray。

      驗證器和異步驗證器。

      動態指定驗證器。條件改變驗證方式改變。

      自定義FormControl。用于表單過于復雜之后,邏輯難以理清楚。把復雜問題拆成若干簡單問題永遠是萬能鑰匙。用于簡化form表單自己的邏輯。

      一、登錄表單

      多個validators:

      Validators.compose([Validators.required, Validators.email])返回ValidatorFn。
      動態指定validator: 
      一開始可以不指定validator,在某些條件下動態指定validator:
       this.form.controls['email'].setValidators(this.validate);
      查看errors:
      <mat-error>{{form.controls['email'].errors | json}}</mat-error>
      模板:
      <form [formGroup]="form" (ngSubmit)="onSubmit(form,$event)">
          <mat-card class="example-card">
              <mat-card-header>
                  <mat-card-title>登錄:</mat-card-title>
              </mat-card-header>
              <mat-card-content>
                  <mat-form-field class="example-full-width" class="full-width">
                      <input type="text" formControlName="email" matInput placeholder="您的email" style="text-align: right">
                      <mat-error>{{form.controls['email'].errors | json}}</mat-error>
                  </mat-form-field>
                  <mat-form-field class="example-full-width" class="full-width">
                      <input type="password" formControlName="password"  matInput placeholder="您的密碼" style="text-align: right">
                  </mat-form-field>
                  <button mat-raised-button type="submit" color="primary" [disabled]="!form.valid">登錄</button>
      
              </mat-card-content>
              <mat-card-actions class="text-right">
                  <p>還沒有賬戶?<a routerLink="/register">注冊</a></p>
                  <p>忘記密碼?<a href="">找回</a></p>
              </mat-card-actions>
          </mat-card>
      
          <mat-card class="example-card">
              <mat-card-header>
                  <mat-card-title>每日佳句</mat-card-title>
                  <mat-card-subtitle>滿足感在于不斷的努力,而不是現有成就。全心努力定會勝利滿滿。</mat-card-subtitle>
              </mat-card-header>
              <img mat-card-image src="/assets/images/quote_fallback.jpg" alt="">
              <mat-card-content>
                  Satisfaction lies in the effort, not in the attainment. Full effort is full victory.
              </mat-card-content>
          </mat-card>
      </form>
      View Code

      組件:

      export class LoginComponent implements OnInit {
        form: FormGroup;
        constructor(private fb: FormBuilder) {
          // this.form = new FormGroup({
          //   email: new FormControl("wang@163.com", Validators.compose([Validators.required, Validators.email])),
          //   password: new FormControl("",Validators.required),
          // })
      
          //formBuilder不需要顯示的new FormControl
          this.form = this.fb.group({
            email: ["wang@163.com", Validators.compose([Validators.required, Validators.email, this.validate]) ],
            password:["",Validators.required]
      
          })
        }
      
        ngOnInit(): void {
         
        }
      
        onSubmit(form: FormGroup, event: Event) {
          event.preventDefault();
          console.log(JSON.stringify(form.value));
          console.log(form.valid);
        }
      
        validate(c:FormControl):{[key:string]:any} | null{
          if(!c.value){
            return null;
          }
          const pattern=/^wang+/;
          if(pattern.test(c.value)){
            return null;
          }else{
            return {
              emailNotValid: 'The email must start with wang'
            }
          }
        }
      
      }
      View Code

       

       二、封裝自定義表單控件

      把注冊表單中的圖片列表抽成一個獨立組件。

       

       

       ng g c shared/image-list-select生成組件

      •  實現ControlValueAccessor接口。實現writeValue(),registerOnChange()和registerOnTouched()
      • 定義一個providers,令牌NG_VALUE_ACCESSOR和NG_VALIDATORS。用useExisting加forwardRef。并且設置multi為true。

       在image-list-select中可以放開的屬性有很多,有沒有必要一一放開?需要權衡。

       如果想要充分的自由度的話,可以用transclude嵌入組件<ng-content></ng-content>。

       在image-list-select中隔離封裝,放開有限的屬性。

      模板:

      <div>
        <span>{{title}}</span>
        <mat-icon class="avatar" [svgIcon]="selected" *ngIf="useSvgIcon else imgSelect"> </mat-icon>
        <ng-template #imgSelect>
          <img [src]="selected" alt="image selected" class="cover">
        </ng-template>
      </div>
      
      <div class="scroll-container">
        <mat-grid-list [cols]="cols" [rowHeight]="rowHight">
          <mat-grid-tile *ngFor="let item of items; let i = index">
            <div class="image-container" (click)="onChange(i)">
              <mat-icon class="avatar" [svgIcon]="item" *ngIf="useSvgIcon else imgItem"></mat-icon>
              <ng-template #imgItem>
                <img [src]="item" alt="image item" [ngStyle]="{'width': itemWidth}">
              </ng-template>
              
              <div class="after">
                <div class="zoom">
                  <mat-icon>checked</mat-icon>
                </div>
              </div>
            </div>
        
          </mat-grid-tile>
        </mat-grid-list>
      </div>
      View Code

      組件:

      import { Component, forwardRef, Input, OnInit } from '@angular/core';
      import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
      
      @Component({
        selector: 'app-image-list-select',
        templateUrl: './image-list-select.component.html',
        styleUrls: ['./image-list-select.component.scss'],
        providers: [
          {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => ImageListSelectComponent),
            multi: true
          },
          {
            provide: NG_VALIDATORS,
            useExisting: forwardRef(() => ImageListSelectComponent),
            multi: true
          }
        ]
      })
      export class ImageListSelectComponent implements ControlValueAccessor {
        @Input() title = "選擇"
        @Input() cols = 6;
        @Input() rowHight = '64px'
        @Input() items: string[] = [];
        @Input() useSvgIcon: boolean = false;
        @Input() itemWidth = '80px';
        selected: string = '';
        constructor() { }
      
        private propagateChange = (_: any) => { };
      
        //寫值,設置控件的值form中setValue設置初始值,通過表單控件的writeValue方法設值。
        writeValue(obj: any): void {
          this.selected = obj;
        }
        //控件view發生變化,把變化emit給表單
        registerOnChange(fn: any): void {
          this.propagateChange = fn;
        }
        //什么狀態算touched,告訴表單
        registerOnTouched(fn: any): void {
        }
      
        onChange(i: number) {
          this.selected = this.items[i];
          this.propagateChange(this.selected); //變化通知表單
        }
      
        validate(c: FormControl): { [key: string]: any } | null {
          return this.selected ? null : {
            imageListInvalid: {
              valid: false
            }
          }
        }
      
      }
      View Code

      1,UI布局 

      圖片鼠標劃過去如果沒有任何反應,用戶會無法感知到有沒有選中,所以

       <div class="image-container" (click)="onChange(i)">
              <mat-icon class="avatar" [svgIcon]="avator"></mat-icon>
              <div class="after">
                <div class="zoom">
                  <mat-icon>checked</mat-icon>
                </div>
              </div>
      </div>

      讓組件既處理icon又處理圖片。用useSvgIcon控制,通過條件子句判斷。

      <mat-icon class="" [svgIcon]="selected" *ngIf="useSvgIcon else imgSelect"> </mat-icon>
      <ng-template #imgSelect></ng-template>

      list太多支持滾動。包在.scroll-container容器中。

      .scroll-container {
          overflow-y: scroll;
          height: 200px;
      }

       2,實現表單控件

      可以通過 formContrlName來操作

       實現ControlValueAccessor接口。

      private propagateChange = (_: any) => { };
      
        //寫值,設置控件的值form中setValue設置初始值,通過表單控件的writeValue方法設值。
        writeValue(obj: any): void {
          this.selected = obj;
        }
        //控件view發生變化,把變化emit給表單
        registerOnChange(fn: any): void {
          this.propagateChange = fn;
        }
        //什么狀態算touched,告訴表單
        registerOnTouched(fn: any): void {
          throw new Error('Method not implemented.');
        }
      
        onChange(i: number) {
          this.selected = this.items[i];
          this.propagateChange(this.selected); //變化通知表單
        }

      providers中定義自己的provider,把自己注冊進去。

      包括NG_VALUE_ACCESSOR和NG_VALIDATORS。

      providers: [
          {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => ImageListSelectComponent),
            multi: true
          },
          {
            provide: NG_VALIDATORS,
            useExisting: forwardRef(() => ImageListSelectComponent),
            multi: true
          }
        ]
      
      validate(c: FormControl): { [key: string]: any } | null {
          return this.selected ? null : {
            imageListInvalid: {
              valid: false
            }
          }
        }

       3,調用/使用

      在sharedModule中導出ImageListSelectComponent。

      <app-image-list-select
                [useSvgIcon]="true"
                [cols]="6"
                [title]="'選擇頭像:'"
                [items]="items"
                formControlName="avatar">
      </app-image-list-select>

       

       

       

       

       

       

      2019-04-07

      posted @ 2021-02-18 08:15  starof  閱讀(553)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 五月婷婷激情视频俺也去淫| 少妇激情一区二区三区视频小说| 亚洲久久色成人一二三区| 亚洲欧美综合一区二区三区| 精品一卡2卡三卡4卡乱码精品视频| 老色鬼在线精品视频在线观看| 无码一区二区三区av在线播放| 日韩精品一区二区蜜臀av| 国产成人无码免费视频在线| 久久久久国产精品人妻| 99久久精品久久久久久婷婷| 在线观看国产成人av天堂| 久久影院九九被窝爽爽| a级国产乱理伦片在线观看al| 国产一区二区在线观看粉嫩| 麻豆一区二区三区精品视频| 大胸美女吃奶爽死视频| 日本道精品一区二区三区| 狠狠躁日日躁夜夜躁欧美老妇 | 国产午夜精品亚洲精品国产| 国产成人综合网在线观看| 国产一区二区不卡在线| 人妻有码av中文字幕久久琪 | 亚洲爆乳WWW无码专区| 亚洲熟妇丰满多毛xxxx| 欧洲精品码一区二区三区| 中文国产人精品久久蜜桃| 久久国产精品老女人| 中文精品无码中文字幕无码专区| 国产成人AV男人的天堂| 亚洲第一极品精品无码久久| 在线视频中文字幕二区| 亚洲av无码国产在丝袜线观看| 亚洲国产在一区二区三区| 久久九九精品99国产精品| 免费无码av片在线观看网站| 久久月本道色综合久久| 久久精品国产99精品国产2021| 国产乱久久亚洲国产精品| 国产精品夫妇激情啪发布| 久久99热只有频精品8|