zoukankan      html  css  js  c++  java
  • angular2 表单拆成多个组件及提交验证问题

     

    angular2表单最常用的方法就是在input或者textarea里直接添加formControlName或者formGroupName进行数据双向绑定并验证。 

     1 <form [formGroup]="goodsFormInfo">      
     2    <input type="text" formControlName="book_file" readonly="" />   
     3    <!--或者-->  
     4    <dl formGroupName="book_isbn">
     5     <dt>
     6      <span>*</span>ISBN号:
     7     </dt>
     8     <dd>
     9      <input id="book_isbn1" td-focus="" formControlName="book_isbn1" [patterninput]="'^[0-9]+$'" class="isbn" type="text" maxlength="3" />
    10      <span>-</span>
    11      <input id="book_isbn2" td-focus="" formControlName="book_isbn2" [patterninput]="'^[0-9]+$'" class="isbn" type="text" maxlength="1" />
    12      <span>-</span>
    13      <input id="book_isbn3" td-focus="" formControlName="book_isbn3" [patterninput]="'^[0-9]+$'" class="isbn" type="text" maxlength="7" />
    14      <span>-</span>
    15      <input id="book_isbn4" td-focus="" formControlName="book_isbn4" [patterninput]="'^[0-9]+$'" class="isbn" type="text" maxlength="6" />
    16      <span>-</span>
    17      <input id="book_isbn5" td-focus="" formControlName="book_isbn5" [patterninput]="'^[0-9]+$'" class="isbn" type="text" maxlength="1" />
    18      <p class="warn-mark" *ngIf="mesg('book_isbn1') || mesg('book_isbn2') || mesg('book_isbn3') || mesg('book_isbn4') || mesg('book_isbn5') || mesg('book_isbn')"> {{ mesg('book_isbn1') || mesg('book_isbn2') || mesg('book_isbn3') || mesg('book_isbn4') || mesg('book_isbn5') || mesg('book_isbn') }}</p>
    19     </dd>
    20    </dl>
    21   </form>

    不过最近遇到一个比较复杂的表单提交, 如果全部写在一个组件里,代码可读性太差,所以把表单拆成了多个组件,通过formControlName进行数据的双向绑定。

    举个简单的例子(核心代码):

    一、form表单-html代码

    1   <dl>
    2    <dt> 商品定时下架:</dt>
    3    <dd>
    4     <tl-goods-sold-out-timing formControlName="auto_off_date"></tl-goods-sold-out-timing>
    5     <p class="color-grey">系统会在该时间自动执行下架</p>
    6     <p class="warn-mark warn-date" *ngIf="mesg('auto_off_date')">{{mesg('auto_off_date')}}</p>
    7    </dd>
    8   </dl>
    9  <button class="btn btn-blue" (click)="submit()">保存</button>
    二、tl-goods-sold-out-timing子组件 - html代码
    1   <div class="clearfix"> 
    2    <tl-check-box [labelname]="'设定'" [(ngmodel)]="isChecking" (onselectedfn)="selectedFn($event)"></tl-check-box> 
    3    <div class="position-relative"> 
    4     <tl-calendar [calendarobj]="calendarObj" [(ngModel)]="startDate" (ngModelChange)="selectDate($event)"></tl-calendar> 
    5    </div> 
    6   </div>
    看到这里一定很奇怪,为什么同时写了ngModel和ngModelChange,ngModelChange在ts文件里会用到,这个日历组件的值改变后会需要我们调用一个change事件的,往下看。
    三、tl-goods-sold-out-timing子组件 - ts代码
    import { Component, OnInit, Output, Input, EventEmitter, forwardRef } from '@angular/core';
    import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
    import { CalendarObj } from '../../../../../shared'
    @Component({
      selector: 'tl-goods-sold-out-timing',
      templateUrl: './goods-sold-out-timing.component.html',
      styleUrls: ['./goods-sold-out-timing.component.css'],
      providers: [
        {
          provide: NG_VALUE_ACCESSOR,
          useExisting: forwardRef(() => GoodsSoldOutTimingComponent),
          multi: true
        }
      ]
    })
    export class GoodsSoldOutTimingComponent implements OnInit {
      public calendarObj: CalendarObj;
      public isChecking: boolean;
      public startDate: Date;
      private change = (value) => { };      // 重点
      constructor() {
        this.calendarInit();
      }
      ngOnInit() { }
      get auto_off_date() {      // 父组件的formControlName接收这块return的数据 get的auto_off_date名称和下面this.change(this.auto_off_date);括号中的值名称一样
        console.log(this.startDate);
        if (!this.isChecking) {
          return {
            date: '',
            set: this.isChecking
          }
        }
        return  {
          date: this.startDate ? this.formatDate(this.startDate) : '',
          set: this.isChecking
        }
      }
      registerOnChange(fn) {     
        this.change = fn;
      }
      registerOnTouched(fn) { }
      writeValue(value) {     //  初始时如果父组件有值传入,就从这里写入组件。
        console.log(value);
        if (!value) {
          this.isChecking = false;
        } else {
          this.startDate = new Date(value.substr(0, 10));  // startDate为日历组件数据de双向绑定
          this.isChecking = true;
          console.log(this.startDate);
        }
      }
      // check-box事件
      selectedFn(event) {
        this.change(this.auto_off_date);
      }
      // 日期改变
      selectDate(date) {      // 数据一但改变,就调用一次change事件,如果上面html文件中没有写ngModelChange,这里日期改变就无法传值给父组件
        console.log(date);
        this.startDate = date;
        this.change(this.auto_off_date);    
      }
      // 日期格式转化
      formatDate = function (date) {
        var y = date.getFullYear();
        var m = date.getMonth() + 1;
        m = m < 10 ? '0' + m : m;
        var d = date.getDate();
        d = d < 10 ? ('0' + d) : d;
        return y + '-' + m + '-' + d;
      };
    // 日历组件初始化
      calendarInit() {
        this.calendarObj = new CalendarObj();
        this.calendarObj.placeholder = '开始日期';
        this.calendarObj.readonly = true;
        this.calendarObj.yearNavigator = true;
        this.calendarObj.monthNavigator = true;
        this.calendarObj.showOtherMonths = true;
        this.calendarObj.style = { 'width': '93px' };
        this.calendarObj.inputStyle = { 'width': '93px', 'background-position': '87px 1px', 'border': '1px solid #c7c7c7' };
      }
    }
    
    四、form表单-ts代码
    formControlName="auto_off_date"接收到数据后,我们需要验证一下数据。
      submit(){
       console.log(this.goodsFormInfo.value);   //  打印表单接收到的数据
       if(this.goodsFormInfo.valid){
       // 如果通过验证就提交
       }
      }
      // 表单验证 
      formInfoInit() {
        this.goodsFormInfo= this.fb.group({ 
          'auto_off_date': ['', [this.validDate()]], 
        })
      }
      mesg(field: string) {
        return this.formUtil.mesg(field);
      }
     // 错误提示
      private validMessages = { 
        'auto_off_date': { 'dateError': '请选择定时下架时间' }, 
      };
      // 验证 - 定时下架
      reqDate() {
        return ((control) => {
          console.log(control);
          if (control.value && control.value.set) {
            if (control.value.date == '') {
              return { dateError: false };
            } }
        });
      }
     
    (本文原创,转载请注明出处!!)

     

  • 相关阅读:
    DateTime.Now.ToString("yyyy/MM/dd") 时间格式化中的MM为什么是大写的?
    新入门PGSQL数据库(尝试利用PGPOOL实现分布式),摘录笔记
    MongoDB入门教程之C#驱动操作实例
    使用MongoDB C#官方驱动操作MongoDB
    【OOAD】OOAD概述
    【OOAD】设计模式概述
    【OOAD】面向对象设计原则概述
    【OOAD】OOP的主要特征
    深入浅出设计模式——访问者模式(Visitor Pattern)
    深入浅出设计模式——模板方法模式(Template Method Pattern)
  • 原文地址:https://www.cnblogs.com/yanliujun-tangxianjun/p/7605198.html
Copyright © 2011-2022 走看看