Angular2:如何使用带有NgModel双向绑定的JavaScript Date Object

sti*_*rts 53 javascript angular

我正在使用Angular 2,我有这个代码:

JS,此代码启动模板的employee-variable:

handleEmployee(employee : Employee){
        this.employee = employee;
        this.employee.startDate = new Date('2005/01/01');
        console.log(this.employee);
    }
Run Code Online (Sandbox Code Playgroud)

模板:

...
<div>
    <label>Start date: </label>
    <input [(ngModel)]="employee.startDate" type="date" name="startDate"/>
  </div>
  <div>
...
Run Code Online (Sandbox Code Playgroud)

其他数据如firstname正确显示.但是到了我得到的日期:

mm/dd/yyyy
Run Code Online (Sandbox Code Playgroud)

在input元素中,应该是一个日期.

我怎样才能做到这一点?

Ank*_*ngh 94

更新:

当我写这个答案DatePipe不存在时,现在你可以这样做

<input [ngModel]="startDate | date:'yyyy-MM-dd'" (ngModelChange)="startDate = $event" type="date" name="startDate"/>
Run Code Online (Sandbox Code Playgroud)

`


旧答案:

PLUNKER

你需要转换date objectinput type="date"是格式yyyy-mm-dd,这是它如何工作

模板:

<input [(ngModel)]="humanDate" type="date" name="startDate"/>
Run Code Online (Sandbox Code Playgroud)

组件(TS):

export class App {
  startDate: any;

  constructor() {
    this.startDate = new Date(2005, 1, 4);
  }

  set humanDate(e){
    e = e.split('-');
    let d = new Date(Date.UTC(e[0], e[1]-1, e[2]));
    this.startDate.setFullYear(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());
  }

  get humanDate(){
    return this.startDate.toISOString().substring(0, 10);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 我不得不修改它以使用本月的'parseInt(e [1] -1)`,否则每次选择日期时都会增加一个月.我想这是因为月份为零 - 在Date构造函数中编入索引. (2认同)

mbr*_*int 18

读取管道ngModel 以及我的deсision:

<input type="date" class="form-control" id="myDate" [ngModel]="myDate | date:'y-MM-dd'" (ngModelChange)="myDate = $event" name="birthday">
Run Code Online (Sandbox Code Playgroud)

  • OP应该_读你的desicion_?一个好的答案**将始终解释所做的事情以及为什么以这种方式完成,不仅对于OP而且对于未来的SO访问者. (3认同)
  • 在进行双向数据绑定时不起作用. (3认同)

Joh*_*ppe 8

FormControls(模板驱动和反应)通过实现的指令订阅值和写入值ControlValueAccessor.看一下相关方法selectValueAccessor,它在所有必要的指令中使用.正常输入控件(例如<input type="text">)或textareas由DefaultValueAccessor处理.另一个例子是CheckboxValueAccessor,它应用于复选框输入控件.

这项工作根本不复杂.我们只需要为日期输入控件实现一个新的值访问器.
DateValueAccessor是一个很好的名字:

// date-value-accessor.ts

import { Directive, ElementRef, HostListener, Renderer, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

export const DATE_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => DateValueAccessor),
  multi: true
};

/**
 * The accessor for writing a value and listening to changes on a date input element
 *
 *  ### Example
 *  `<input type="date" name="myBirthday" ngModel useValueAsDate>`
 */
@Directive({
  selector: '[useValueAsDate]',
  providers: [DATE_VALUE_ACCESSOR]
})
export class DateValueAccessor implements ControlValueAccessor {

  @HostListener('input', ['$event.target.valueAsDate']) onChange = (_: any) => { };
  @HostListener('blur', []) onTouched = () => { };

  constructor(private _renderer: Renderer, private _elementRef: ElementRef) { }

  writeValue(value: Date): void {
    this._renderer.setElementProperty(this._elementRef.nativeElement, 'valueAsDate', value);
  }

  registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
  registerOnTouched(fn: () => void): void { this.onTouched = fn; }

  setDisabledState(isDisabled: boolean): void {
    this._renderer.setElementProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
  }
}
Run Code Online (Sandbox Code Playgroud)

我们将附加DateValueAccessor到多提供者DATE_VALUE_ACCESSOR,以便selectValueAccessor可以找到它.

唯一的问题是,应该使用哪个选择器.我决定选择加入解决方案.
这里DateValueAccessor选择属性"useValueAsDate".

<input type="date" name="myBirthday" ngModel useValueAsDate>

OR

<input type="date" name="myBirthday" [(ngModel)]="myBirthday" useValueAsDate>

OR

<input type="date" formControlName="myBirthday" useValueAsDate>
Run Code Online (Sandbox Code Playgroud)

也可以修复默认实现.
以下选择器会神奇地激活该功能.

// this selector changes the previous behavior silently and might break existing code
selector: 'input[type=date][formControlName],input[type=date][formControl],input[type=date][ngModel]'
Run Code Online (Sandbox Code Playgroud)

但请注意,这可能会破坏依赖旧行为的现有实现.所以我会去选择加入版本!

这一切都在NPM和Github上

为方便起见,我angular-data-value-accessor在Github上创建了这个项目.
还有一个NPM包:

npm install --save angular-date-value-accessor
Run Code Online (Sandbox Code Playgroud)

然后只需通过NgModule导入模块:

// app.module.ts

import { DateValueAccessorModule } from 'angular-date-value-accessor';

@NgModule({
  imports: [
    DateValueAccessorModule
  ]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)

现在,您可以将"useValueAsDate"应用于日期输入控件.

演示

当然,还有一个演示:http: //johanneshoppe.github.io/angular-date-value-accessor/