InfomediaLtd / angular2-materialize

Angular 2 support for Materialize CSS framework.
https://infomedialtd.github.io/angular2-materialize/
MIT License
407 stars 140 forks source link

DatePicker issue: Format is ignored when bound to property of Date Type #262

Closed pain0486 closed 7 years ago

pain0486 commented 7 years ago

The inital binding of a datepicker does not work when the property is a full date. So if the property is this.datePicker = new Date('3/30/1989'); The date picker shows Thu Mar 30 1989 00:00:00 GMT-0500(Central Daylight Time) and even if you change it to just '3/30/1989' the DatePicker still opens up directly to today instead of the starting date.

Its important that this works. I'm using typescript and the Items on my models are dates and not strings. My only option so far is to change the dates to strings and inject the date-pipe into the component to set the initial date.

plunker

rubyboy commented 7 years ago

Thanks for the plunker. It helped understanding the issue and reproducing it!

Try this.datePicker = '03/30/1989'; or this.datePicker = '30/03/1989'; (depends on your timezone.

image

pain0486 commented 7 years ago

I get a full date object back from the server in ISO format ex: (2017-03-30T06:00:00.000Z) So to use this.datePicker = '03/30/1989'; or this.datePicker = '30/03/1989' isn't really an option because typescript flags the this.datePicker as a type error.

I am currently getting around the issue by binding to (input) and [value]. <input type="text" class="datepicker" name="datePicker " materialize="pickadate" [materializeParams]="[{ format: 'mm-dd-yyyy', closeOnSelect: true }]" (input)="datePicker = $event.target.valueAsDate" [value]="datePicker | date: 'MM-dd-yyyy'"/>

Thanks to hakany and Yuriy Rozhovetskiy's solution at stackoverflow

rubyboy commented 7 years ago

@pain0486 is that a limitation of the Angular binding or MaterializeCSS library itself? Trying to figure out if we need to do something, or leave as is. Thanks.

pain0486 commented 7 years ago

Not sure, I dont think materialize formats the date till after you choose a date, taking in whatever you have as a value and displaying it. I know in Angular(JS and current) when its a 2 way binding you cant alter the appearance of the item being bound. IE you cant use a pipe to format a date the way you like it AND have DOM to component binding (output binding). So ngModel can't be set to a Date value and be formatted to appear a certain way without the directive handling this for us. In AngularJS we would have a directive that would take in a date but would convert the date to string before handing it off the the datepicker lib. In this case that would be the pickadate lib. Then we would need to hook into the change events updating the handed in date and the DOM.

Example directive in angularJS around the bootstrap-datetimejs. plunker

What I would expect is to take the input binding as string or date and format it to be the requested format or default. Then keep the datepicker displaying the formatted string while keeping the date/string object in the ngModel updated which each calendar change.

Seems right now the format does not take effect till after a date is picked.

rubyboy commented 7 years ago

If you have time at some point to try vanilla MaterializeCSS and check if we can close the issue here and open one there it would be awesome. Adding @criticalbh who originally created the support for the date picker here. He may have more info/ideas about this topic.

pain0486 commented 7 years ago

@rubyboy @criticalbh I have been messing with a plunkers and so far the only thing that the datepicker in materialize binds to when setting the value is the date part of an ISO String (date.toISOString()) plunker

So it seems to make this work, it needs to detect if the bound object is a date, If its a type of date set the bound value to date..toISOString().substring(0,10) then hook into the materialize change event and update the passed in date to value from the dom. Most likely the doing something like date = new Date(passedInValue);

rubyboy commented 7 years ago

@pain0486 do you think it should be done in this library or in MaterializeCSS or pickadate itself?

RomainMarecat commented 7 years ago

For me all done with ngModel @angular/cli: 1.0.1 node: 7.9.0 os: linux x64 @angular 2.4.10 @angular/cli: 1.0.1 materialize-angular2 15.0.1

<input formControlName="birthday" materialize="pickadate" [(ngModel)]="user.user_metadata.birthday" [materializeParams]="[birthdateOption]" type="text" />

this.birthdateOption = {
      format: 'dd/mm/yyyy',
      selectMonths: true,
      today: false,
      selectYears: 100,
      closeOnSelect: true,
      max: new Date(),
      clear: 'clear'
      close: 'save',
      formatSubmit: "yyyy-mm-dd"
    };

my issue is closeOnSelect doesn't work...

rubyboy commented 7 years ago

@RomainMarecat is that related to the date format problem? Otherwise, I think you should create a different issue, and not add on to the date format discussion. Thanks.

rubyboy commented 7 years ago

@RomainMarecat https://github.com/InfomediaLtd/angular2-materialize/issues/135

RomainMarecat commented 7 years ago

@RomainMarecat is that related to the date format problem ?

pain0486 commented 7 years ago

That is a tough question. I am not very familiar with other front-end libs outside Jquery and binding frameworks.(Knock-out, Backbone, AngularJS, Anagular). But I would say this lib would be the place that I would put it and that is mainly because its build on a binding library. The bridge between angular and materialize. Especially since they promote typescript so much. Your more likely to try and bind a date in a binding lib that uses typescript. Perhaps its my .NET background that is saying a date should be of type date and not string.

I wouldn't think it would be materialize css as I think the straight HTML would be a string and the form would post back to the server and be converted to a date there. The pickadate probably takes and returns a string so it could keep the HTML element insync. Although I would be surprised if it didn' deal with it as a date inside its own lib.

pain0486 commented 7 years ago

@RomainMarecat what was the value of user.user_metadata.birthday in that example you posted?

RomainMarecat commented 7 years ago
{
  birthday: "15/03/2017"
}
pain0486 commented 7 years ago

@RomainMarecat . Notice how the date isnt right if user.user_metadata.birthday is a date object { birthday: new Date("15/03/2017") } Or if you put the date in a different format than specified 15-03-2017 or 2017/03/15

criticalbh commented 7 years ago

Sorry everyone, I hope I am not too late. There is PR, it should be ok now.

pain0486 commented 7 years ago

works great! Thanks @criticalbh!