Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular mat-datepicker with date mask

I write custom datepicker input component imlements ControlValueAccessor in Angular5 using mat-datepicker.

date-picker.component.html:

<mat-form-field>
    <input matInput [matDatepicker]="picker" [(ngModel)]="value" (blur)="onBlur()">
    <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
    <mat-datepicker (selectedChanged)="onChange($event)" #picker></mat-datepicker>
</mat-form-field>

date-picker.component.ts :

import { Component, OnInit, Input, Output, forwardRef, EventEmitter } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
import { MAT_MOMENT_DATE_FORMATS, MomentDateAdapter } from '@angular/material-moment-adapter';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

const noop = () => {
};

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

@Component({
  selector: 'app-date-picker',
  templateUrl: './date-picker.component.html',
  styleUrls: ['./date-picker.component.css'],
  providers: [
    { provide: MAT_DATE_LOCALE, useValue: 'he-IL' },
    { provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
    { provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS },
    CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR
  ],
})
export class DatePickerComponent implements OnInit, ControlValueAccessor {

  @Input()
  required: boolean;

  @Output()
  change: EventEmitter<Date> = new EventEmitter<Date>();

  innerValue: Date = new Date();

  //Placeholders for the callbacks which are later provided
  //by the Control Value Accessor
  private onTouchedCallback: () => void = noop;
  private onChangeCallback: (_: any) => void = noop;


  //get accessor
  get value(): Date {
    return this.innerValue;
  };

  //set accessor including call the onchange callback
  set value(v: Date) {
    if (v !== this.innerValue) {
      this.innerValue = v;
    }
  }

  constructor(private adapter: DateAdapter<any>) { }

  ngOnInit() {
    this.adapter.setLocale('he');
  }

  //Occured value changed from module
  writeValue(value: any): void {
    if (value !== this.innerValue) {
      this.innerValue = value;

      //invoke value change event
      this.change.emit(this.innerValue);
    }
  }
  registerOnChange(fn: any): void {
    this.onChangeCallback = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouchedCallback = fn;
  }

  onChange(event) {
    this.value = event;
    this.onBlur();
  }

  onBlur() {
    this.onChangeCallback(this.innerValue);
    //invoke value change event
    this.change.emit(new Date(this.innerValue));
    //this.onTouchedCallback();
  }
}

I want to add ability to enforce date mask like 'dd/MM/yyyy'

I found matching example, but it written in angularJS and md datepicker:

Angular Material Datepicker and ngMask

Any idea for implementation in Angular?

Edit:

Attached live demo, Based on Vivek Doshi nice answer, This demo not work due to [textMask] attribute.

Live Demo

like image 951
Stack Overflow Avatar asked Jan 15 '18 07:01

Stack Overflow


People also ask

How can I get date from Mat datepicker?

Connecting a date-picker to an inputThe date-picker is made up of text input and a calendar pop-up, which is linked via the mat-Date-picker property to the text input. It also has an optional date-picker toggle button that gives the user a simple method to open the date-picker pop-up window.

How do you use a mat datepicker?

mat-datepicker exampleAdd a template reference variable mat-datepicker element. Connect mat-datepicker to input element via [matDatepicker] property. Finally add date picker toggle button to display or hide calender popup by using mat-datepicker-toggle element.

What is Mat-datepicker-toggle?

A datepicker is composed of a text input and a calendar pop-up, connected via the matDatepicker property on the text input. There is also an optional datepicker toggle button that gives the user an easy way to open the datepicker pop-up.


2 Answers

You can achieve that with the help of angular2-text-mask

Component side :

public mask = {
    guide: true,
    showMask : true,
    mask: [/\d/, /\d/, '/', /\d/, /\d/, '/',/\d/, /\d/,/\d/, /\d/]
  };

Template Side :

<mat-form-field>
  <input matInput [textMask]="mask" [matDatepicker]="picker" placeholder="Choose a date">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

WORKING DEMO

Now all you need to do is bind the logic and validations ,

Here is the WORKING DEMO with the solution of ControlValueAccessor.


3rd Demo , with your code

WORKING DEMO

like image 69
Vivek Doshi Avatar answered Sep 19 '22 16:09

Vivek Doshi


If i've understood your problem, why don't you try with a pipe? like this:

"{{yourDateModel | date: 'dd/MM/yyyy'}}"

in your html date-picker component

like image 40
Luca Taccagni Avatar answered Sep 20 '22 16:09

Luca Taccagni