Подтвердить что ты не робот

Angular2: как использовать объект Date JavaScript с привязкой к NgModel

Я работаю с Angular 2, и у меня есть этот код:

JS, этот код инициирует переменную employee для шаблона:

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

Шаблон:

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

Другие данные, такие как firstname, отображаются правильно. Но на дату, которую я только что получил:

mm/dd/yyyy

В элементе ввода, который должен быть датой.

Как я могу это сделать?

4b9b3361

Ответ 1

UPDATE:

когда я написал этот ответ DatePipe не существовал, теперь вы можете просто сделать это

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

`


Старый ответ:

PLUNKER

Вам нужно преобразовать date object в формат input type="date", который равен yyyy-mm-dd, вот как он будет работать

Шаблон:

<input [(ngModel)]="humanDate" type="date" name="startDate"/>

Компонент (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);
  }
}

Ответ 2

Прочтите pipes и ngModel и мое решение:

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

Ответ 3

FormControls (как управляемые шаблонами, так и реактивные) подписываются на значения и записывают значения через директивы, которые реализуют ControlValueAccessor. Посмотрите на соответствующий метод selectValueAccessor, который используется во всех необходимых директивах. Регуляторы нормального ввода (например, <input type="text">) или текстовые поля обрабатываются 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);
  }
}

Мы присоединяем DateValueAccessor к мульти-провайдеру DATE_VALUE_ACCESSOR, так что

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

OR

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

OR

<input type="date" formControlName="myBirthday" useValueAsDate>

Также можно исправить реализацию по умолчанию.
Следующий селектор активирует функцию магически.

// 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]'

Но, пожалуйста, имейте в виду, что это может нарушить существующие реализации, которые полагаются на старое поведение. Поэтому я бы выбрал вариант выбора!

Все это на NPM и Github

Для вашего удобства я создал проект в Github.
Существует также пакет NPM:

npm install --save angular-date-value-accessor

Затем просто импортируйте модуль через NgModule:

// app.module.ts

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

@NgModule({
  imports: [
    DateValueAccessorModule
  ]
})
export class AppModule { }

Теперь вы можете применить "useValueAsDate" к элементам управления вводами даты.

Demo

Конечно, есть демо:

Ответ 4

Я начал пытаться реализовать решение Ankit Singh и столкнулся с несколькими проблемами с проверкой и временем. (Даже после того, как вы попробовали предложения в разделе комментариев этого ответа)

Вместо этого я решил использовать moment.js для обработки преобразования между строкой и датой с использованием строк даты формата ISO8601. У меня были отличные результаты в прошлом, используя moment.js, поэтому это было нелегкое решение. Кажется, хорошо работает для меня, надеюсь, кто-то еще найдет это полезным.

Для моего приложения Angular 2 я запустил npm install --save moment, а затем превратил решение Ankit в оболочку вокруг объекта js Date:

import * as moment from 'moment';

export class NgDate {

    date: any;

    constructor() {
        this.date = new Date();
    }

    set dateInput(e) {
        if (e != "") {
            var momentDate = moment(e, moment.ISO_8601).toDate();
            this.date = momentDate;
        }
        else {
            this.date = null;
        }
    }

    get dateInput() {
        if(this.date == null)
        {
            return "";
        }

        var stringToReturn = moment(this.date).format().substring(0, 10);
        return stringToReturn;
    }
}

Затем для HTML:

<input type="date" name="someDate" [(ngModel)]="ngDateModel.dateInput"/>

Ответ 5

Исправлено это с помощью этого кода:

handleEmployee(employee : Employee){
        this.employee = employee;

        let dateString : string = employee.startDate.toString();
        let days : number = parseInt(dateString.substring(8, 10));
        let months : number = parseInt(dateString.substring(5, 7));
        let years : number = parseInt(dateString.substring(0, 5));
        let goodDate : Date = new Date(years + "/" + months + "/" + days);
        goodDate.setDate(goodDate.getDate() + 2);
        this.date = goodDate.toISOString().substring(0, 10);
    }

Html:

<div>
    <label>Start date: </label>
    <input [(ngModel)]="date" type="date" name="startDate"/>
  </div>