I have my mat-datepicker in 2 places on the page. And when I'm clicking on the one place, it opens in an oposite place. How can I fix that? I have 2 different components with mat-datepicker, but it opens different.
Maybe the problem is that I imitate click in one component? But why it opens different one?
Here's the code
Opens here: (child.components.html)
<mat-form-field appearance="fill">
<input matInput [matDatepicker]="picker">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker ngDefaultControl></mat-datepicker>
</mat-form-field>
Clicks here: (parent.component.html)
<mat-form-field appearance="fill">
<mat-label>Choose a date</mat-label>
<input [min]="minDate" (dateInput)="onDate($event)" matInput [matDatepicker]="picker" (keydown)="false">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker ngDefaultControl></mat-datepicker>
</mat-form-field>
Onchange event opens Calendar like this:
public onTabChange(event: MatButtonToggleChange): void {
setTimeout(() => {
const element: HTMLElement = document.getElementsByClassName('mat-icon-button')[0] as HTMLElement;
element.click();
}, 200);
}
try give differents "template reference variable" (replace one #picker by, e.g. #picker2 and replace the picker by picker2.
About imitate click (it's not the problem) I suggest use a ViewChild and directly use open method
import {MatDatepicker} from '#angular/material/datepicker';
#ViewChild('picker2') datepicker:MatDatepicker<any>
public onTabChange(event: MatButtonToggleChange): void {
setTimeout(() => {
this.datepicker.open()
});
}
See that you needn't "wait" the 200 miliseconds. The setTimeout say to angular: "hey you!, repaint the app and after, remember execute the code under the setTimeout" -the same happens if you use change detector and use .markForCheck()-
Related
Is it possible to somehow catch click event on angular material datepicker toggle icon? I want trigger function foo().
My implementation looks like:
<mat-form-field class="example-full-width">
<input matInput [matDatepicker]="picker" placeholder="Date">
<mat-datepicker-toggle matSuffix [for]="picker" (click)="foo()"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
I have already tried put (click)="foo()" to mat-datepicker-toggle and mat-datepicker element but event not triggered.
Use opened and closed event emitter provided by angular date picker component to listen open and close of calander component.
<mat-form-field class="example-full-width">
<input matInput [matDatepicker]="picker" placeholder="Date">
<mat-datepicker-toggle
matSuffix [for]="picker" (click)="foo()"></mat-datepicker-toggle>
<mat-datepicker
#ref
(opened)="toggle(ref)"
(closed)="toggle(ref)"
#picker></mat-datepicker>
</mat-form-field>
Example
Try to (focus)="foo()" instead of (click)="foo()"
I have a form where every required field turns red if the user clicks and blur the field without writing anything on the field, the problem comes with this date picker
<mat-form-field class="contenedorFecha" appearance="outline" color="accent">
<mat-label>Fecha plantaciĆ³n</mat-label>
<input matInput [matDatepicker]="fechaPlantacion" formControlName="fechaPlantacion" readonly (click)="fechaPlantacion.open()">
<div matSuffix style="display:flex; align-items: center">
<mat-datepicker-toggle [for]="fechaPlantacion"></mat-datepicker-toggle>
<button mat-icon-button (click)="deleteDate('fechaPlantacion', $event)" [disableRipple]="true"
*ngIf="fincaForm.get('fechaPlantacion').value !== null">
<mat-icon class="nav-link-icon mat-icon notranslate material-icons mat-icon-no-color ng-star-inserted" role="img" aria-hidden="true">close</mat-icon>
</button>
</div>
<mat-datepicker #fechaPlantacion></mat-datepicker>
</mat-form-field>
When I click on the input it opens the matDatePicker, but as it opens the date picker the input blurs, so the input changes to red, any way to prevent this? I've tried with css but the problem is I want the input to be red but only when it should
Yes the problem is because the focus gets out of the input control and goes to the calendar. If you are only using the default button as the trigger to open the date picker, then you won't encounter this issue. But like what you did, sometimes it's better to add that (focus) or (click) trigger. I can only think of one work around.
Start by removing the initial validators from your field. Then put a handler whenever the material date picker was closed such as:
<mat-datepicker #fechaPlantacion (closed)="close()"></mat-datepicker>
and in the close method, you have to set the validators dynamically:
close() {
this.fechaPlantacion.setValidators(Validators.required);
this.fechaPlantacion.updateValueAndValidity(null);
}
This way, the validation will only be added after the selection (or not selecting anything) from the dates in the calendar. I also tried using readonly input and still working fine after testing in my local machine.
I am relatively new to Angular and I couldn't find any solution to the following problem.
I have the following code:
<mat-form-field>
<input matInput placeholder="ZIP" style="color:red;">
</mat-form-field>
I want it to write the word ZIP in red, but all it does is showing a red cursor, and the word zip is still grayed out.
This works perfectly when working with input, and not with matInput.
Does anybody know how can it be solved?
Thanks!
Try this way :
<mat-form-field class="example-full-width">
<mat-label style="color: red">Zip</mat-label>
<input matInput>
</mat-form-field>
Live example :
https://stackblitz.com/edit/angular-rkewwm?file=app/input-overview-example.html
(Don't forget to upgrade your package #angular/material, v5 min if I'm not mistaken)
In the datepicker documentation there is an example of the popup calendar being controlled programatically by using the open() and close() methods like so:
<mat-form-field class="example-full-width">
<input matInput [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
<button mat-raised-button (click)="picker.open()">Open</button>
One can also set the opened property to true/false like so:
<button mat-raised-button (click)="picker.opened = true">Open</button>
I wonder if there is anyway to use this to get the calendar popup to stay permanently opened for the purpose of letting the user click around on different dates, and having those selection reflected in the input?
I guess you can try this :
<mat-form-field class="example-full-width">
<input matInput (dateChange)="reOpenCalendar()" [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
<button mat-raised-button (click)="picker.open()">Open</button>
in your component ts/js file you need to declare a new method :
export class YourComponent{
#ViewChild('picker') picker;
//....
reOpenCalendar(){
let self = this;
setTimeout(
()=>{
self.picker.open();
},
50
);
}
}
This will introduce a flash effect as the date picker disappears and quickly reappears.
The other solution would be fork angular material datepicker component in your local project and introduce an Input property to disable the closing when a date is selected
The built-in datepicker control of Material library comes with an internal Calendar component. You can use the following to have a calendar that is always open (without the input box but still works with date/month/year selection)
Read more about the calendar here:
https://onthecode.co.uk/angular-material-calendar-component/
When I copy the DatePicker example from the Angular Material website it's adding an extra horizontal line to the bottom of it and I can't figure out why.
Here's the example:
<mat-form-field>
<input matInput [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
And here's a screenshot:
this problem is because you are using the angular material and also the cdn of materialize or materialize style.
you could delete this line:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
and the line of the datepicker will be ok, and then, you could use other grid system for de rows and cols.
for example: https://github.com/angular/flex-layout
I am just leaving this here in case someone else makes the same mistake I did. In my case I accidentally copy and pasted the date picker code inside an existing mat-form-field. I didn't notice it at first because of all the markup.
I had it like this and removing the outer mat-form-field fixed it for me:
<mat-form-field>
<mat-form-field>
<mat-label>End Date</mat-label>
<input matInput [(ngModel)]="endDate" #endDate="ngModel" [matDatepicker]="picker1">
<mat-datepicker-toggle matSuffix [for]="picker1"></mat-datepicker-toggle>
<mat-datepicker #picker1></mat-datepicker>
</mat-form-field>
</mat-form-field>