20

I want to open calendar where user chooses date from date-picker not only when user clicks on calendar icon, but also when clicks on input field. Material DatePicker. So I create directive for this, attaching it to <md-datepicker> and also watching for (click) event on input:

Html:

  <md-form-field class="field-half-width">
    <input mdInput [mdDatepicker]="picker2" placeholder="Galioja iki"
            formControlName="dateUntil" (click)="clickInp()">
    <md-datepicker-toggle  id="calendar" mdSuffix [for]="picker2" ></md-datepicker-toggle>
    <md-datepicker #picker2 manualClickRenderer></md-datepicker>
  </md-form-field> 

form-component:

import {ManualClickRerender} from '../shared/directives/manual-click.directive';

@Component({
  selector: 'form',
  providers: [ManualClickRerender]
})

export class FormComponent implements OnInit, OnChanges {
 ...
  clickInp() {
    this.manualClickRerender.botClick();
  }

Directive:

import { Directive, Renderer, ElementRef } from '@angular/core';
@Directive({
  selector: '[manualClickRenderer]'
})
export class ManualClickRerender {

  private nativeElement : Node;

  constructor( private renderer : Renderer, private element : ElementRef ) {
    this.nativeElement = element.nativeElement;
  }

  botClick() {    
    console.log(this.nativeElement); // logs the whole form, not the <md-datepicker>. I guess problem is here
    this.renderer.invokeElementMethod(this.nativeElement, 'click', []);
  }
}

This is my first custom directive ever, so not completaly sure how to import / provide it, etc. I imported it in main module and added to declarations, but after I imported it in my form component (I did that because need to pass click event to it) got error that there are no providers to ManualClickRerender. So added it as provider as well in form-component. So, yes, I imported it twice..

Also as you see, I use Rerender, not Rerender2, because it doesn't have invokeElementMethod method... But I bet there is a workaround, just dont know it..

Thanks in advance for any info.

5 Answers 5

52

There is no need for providers

<md-input-container>
     <input mdInput [mdDatepicker]="start" (click)="start.open()" [(ngModel)]="_start" [ngModelOptions]="{standalone: true}" placeholder="choisir date" (keydown)="false">
     <button mdSuffix [mdDatepickerToggle]="start"></button>
</md-input-container>
<md-datepicker #start></md-datepicker>
Sign up to request clarification or add additional context in comments.

4 Comments

Ok, open is a function... Great. But your code is not clean. I needed only (click)="start.open()" and (keydown)="false". Just one little problem - if I click on edge of the input, placeholder goes up, but calendar doesn't show up. I need to click more in the middle on the input. However, this solution is nice and clean.
Just one more information Angular material is IE10+.
@Melchia What a saviour!
(keydown)="false" prevents a keyboard user from typing in a date or manually opening the datepicker to make a selection. You can't even tab to the next field, actually - you get completely stuck. Big accessibility problem.
14

You dont need a directive for that. Just add (click)="picker2.open()" in the input field:

  <md-form-field class="field-half-width">
    <input mdInput [mdDatepicker]="picker2" placeholder="Galioja iki"
            formControlName="dateUntil" (click)="picker2.open()">
    <md-datepicker-toggle  id="calendar" mdSuffix [for]="picker2" ></md-datepicker-toggle>
    <md-datepicker #picker2></md-datepicker>
  </md-form-field> 

Here is a link to working demo.

1 Comment

I didnt realised, that open is a function.. Tried to change it as a property... Yes, stupid, but at least I learned quite a bit about directives :) Thanks
7

Just one little problem - if I click on edge of the input, placeholder goes up, but calendar doesn't show up. I need to click more in the middle on the input. However, this solution is nice and clean

Answer to this question is just call open function above your input parent like this

                <mat-form-field (click)="picker.open()">
                  <input matInput [matDatepicker]="picker">
                  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
                  <mat-datepicker #picker></mat-datepicker>
                </mat-form-field>

1 Comment

This one is pretty cool, and it works fine. However, I can notice the calendar component is not the same using this mat-datepicker. The one from <input matInput type date is the default one from the browser, but the one from mat-datepicker is a custom one from material. And this one is not translated with internationalisation (i18n)
7

This one worked for me

<mat-form-field (click)="picker.open()">
<input matInput [matDatepicker]="picker">
<mat-datepicker-toggle matSuffix [for]="picker"></matdatepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>

Comments

1

You can use CSS to make it work.

<mat-form-field>
  <input matInput [matDatepicker]="dp" placeholder="Moment.js datepicker" [formControl]="date">
  <mat-datepicker-toggle[for]="dp"></mat-datepicker-toggle>
  <mat-datepicker #dp></mat-datepicker>
</mat-form-field>

mat-datepicker-toggle.mat-datepicker-toggle {
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 1;
opacity: 0;

button {
  width: 100%;
  height: 100%;
}

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.