Angular表單控件須要類型和實際值類型不一致時實現雙向綁定

適用Angular版本爲:>=2。本文一樣適用於Ionic這類的基於Angular實現的框架。
本文的思路也適用於控件顯示的值和實際的值不同時實現雙向綁定。javascript

1. 問題描述

在使用md2的datepicker控件時,遇到這樣的問題,datepicker綁定的類型要求是Date類型,可是傳輸後臺須要的類型是基於YYYY-MM-DD的日期字符串,可是Date類型默認轉換爲字符串是這樣的:Fri Jun 02 2017 16:03:50 GMT+0800 (China Standard Time),致使後臺沒有正確的處理日期。
這個問題能夠從後臺處理,提供對應格式的反序列化,可是不是最佳方案。日期類型基於不一樣的語言區域平臺,其默認生成的格式也是不同的。
那麼如何在前端從根源上處理呢?html

2. 思路分析

剛開始考慮了兩種方案:
一、經過聲明gettersetter方法,綁定對應的gettersetter屬性,可是這樣會形成綁定時髒檢查的死循環問題,因此否認這種方案;
二、經過Pipe,來實現將字符串轉換爲Date類型,實現綁定,可是這隻能解決單向綁定,對於雙向綁定也無能爲力。
最後,考慮可否結合以上兩種方案呢?
好的,結果是成功的,咱們下面就來介紹如何一步一步的解決這個問題。前端

3. 問題解決

3.1. 示例model定義

這裏定義一個People的示例model,只有一個屬性birthday,爲string類型。java

import * as moment from 'moment';

export class People
{
    birthday: string = "";

    set ParseBirthday(val: Date){
        this.birthday = moment(val).format("YYYY-MM-DD");
    }
}

在這裏咱們生成了一個setter方法,用來將Date類型數據轉換爲對應格式的string類型。shell

3.2. 定義string類型單向綁定的pipe

代碼以下:npm

import { Pipe, PipeTransform } from '@angular/core';
import * as moment from 'moment';

@Pipe({
  name: 'stringToDate',
})
export class StringToDatePipe implements PipeTransform {
  
  transform(value: string, format: string, ...args) {
    if(!format) format = "YYYY-MM-DD";
    if(!!value && moment(value, format).isValid()){
      var dVal = moment(value, format);
      return dVal.toDate();
        }
        return null;
  }
}

這個Pipe的目的就是將String類型轉換爲Date,這裏能夠傳遞一個format參數,爲String類型對應的日期格式。框架

3.3. 最後咱們進行一種改造的雙向綁定

<md2-datepicker [ngModel]="p.birthday | stringToDate:'YYYY-MM-DD'" (ngModelChange)="p.ParseBirthday=$event" type='date' format='y-M-d'></md2-datepicker>

上面咱們將本來基於[(ngModel)]的雙向綁定,拆分紅了一個單向綁定[ngModel]和一個ngModelChange事件處理,其中[ngModel]的單向綁定,是經過3.2節中定義的PipeString類型的birthday轉換爲Date類型進行綁定;而後當數據改變時,經過(ngModelChange)事件,經過setter方法將Date類型從新轉換爲String,並賦值給birthdaythis

OK,問題解決了,完工。雙向綁定

附錄

本文中使用了Moment.js來進行日期格式處理,能夠經過以下命令安裝相關依賴:code

npm install moment --save
相關文章
相關標籤/搜索