Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use moment.js dates for the directives? #3218

Open
meness opened this issue Jun 1, 2019 · 4 comments
Open

How to use moment.js dates for the directives? #3218

meness opened this issue Jun 1, 2019 · 4 comments

Comments

@meness
Copy link

meness commented Jun 1, 2019

Hi,

I expect to use different date object for the directives while defined a custom provider. Sometimes, when I select a date from future the input receives an empty string/null. Moreover, the dates defined for directives do not work and default (+10-10 years) displays. By the way, NgbDateStruct date objects work well for directives but I expect the custom date object to work properly.

<div class="input-group">
   <input ngbDatepicker #startAtDatePicker="ngbDatepicker" [maxDate]="maxDateForStartsAtDate"
   readonly [startDate]="minDateForStartsAtDate" [minDate]="minDateForStartsAtDate"
   class="form-control" placeholder="yyyy-mm-dd" formControlName="startsAtDate">
   <div class="input-group-append">
      <span class="input-group-text" (click)="startAtDatePicker.toggle()">
      <i class="la la-calendar"></i>
      </span>
   </div>
</div>
import { Injectable } from "@angular/core";
import { NgbDateAdapter, NgbDateStruct } from "@ng-bootstrap/ng-bootstrap";
import * as moment from "moment";

@Injectable()
export class MomentNgbDateAdapterService extends NgbDateAdapter<moment.Moment> {
  fromModel(value: moment.Moment): NgbDateStruct {
    return {
      day: value.get("day"),
      month: value.get("month"),
      year: value.get("year")
    };
  }

  toModel(date: NgbDateStruct): moment.Moment {
    if (date === null) {
      throw new Error("date cannot be null");
    }

    return moment({ year: date.year, month: date.month, day: date.day });
  }

  constructor() {
    super();
  }
}
// public properties
minDateForStartsAtDate = moment().utc();
maxDateForStartsAtDate = moment()
    .utc()
    .add(1, "month");

// inside formBuilder
startsAtDate: this.formBuilder.control(this.minDateForStartsAtDate, [])
@NgModule({
  imports: [
    NgbDatepickerModule
  ],
  exports: [
    NgbDatepickerModule
  ],
  providers: [
    { provide: NgbDateAdapter, useClass: MomentNgbDateAdapterService }
  ]
})
export class BootstrapModule {}
@meness
Copy link
Author

meness commented Jun 2, 2019

Bad formatting in the adapter causes the null exceptions but now fixed with the below implementation.

import { Injectable } from "@angular/core";
import { NgbDateAdapter, NgbDateStruct } from "@ng-bootstrap/ng-bootstrap";
import * as moment from "moment";
import * as _ from "lodash";

@Injectable()
export class MomentNgbDateAdapterService extends NgbDateAdapter<moment.Moment> {
  constructor() {
    super();
  }

  fromModel(value: moment.Moment): NgbDateStruct {
    return value && moment.isMoment(value)
      ? {
          day: value.date(),
          month: value.month() + 1,
          year: value.year()
        }
      : null;
  }

  toModel(date: NgbDateStruct): moment.Moment {
    return date &&
      _.isInteger(date.year) &&
      _.isInteger(date.month) &&
      _.isInteger(date.day)
      ? moment({
          year: date.year,
          month: date.month - 1,
          date: date.day,
          hour: 12
        })
      : null;
  }
}

But still, I cannot use MomentJS for directives.

@meness meness changed the title How to use custom date object for directives? I always get null exception in the custom provider How to use moment.js objects for the directives? Jun 2, 2019
@meness meness changed the title How to use moment.js objects for the directives? How to use moment.js dates for the directives? Jun 2, 2019
@danieldiazastudillo
Copy link

I wouldn't use this approach. First of all you are importing the entire Lodash library in order to use one method (isInteger), you can cherry-pick methods in Lodash or, even better, use native Number.isInteger() function as described in MDN.

Moment it's great but it's not tree-shakeable and besides that when bundling with Angular CLI it contains locales wich is very annoying. I suggest using Luxon or, as i do, use date-fns v2 wich is fully tree shakeable and covers almost the entirety Moment's API surface.

@fbasso
Copy link
Member

fbasso commented Jun 18, 2019

@meness What's going on with the directives ? You told that the DateAdpater is now working, fine, but in a directive, you can just use the moment objects, right ? An example of what you want to achieve would be welcome !

@benouat
Copy link
Member

benouat commented Jun 18, 2019

An example of what you want to achieve would be welcome !

Good point! We would really appreciate a reproducible scenario inside a Stackblitz to simply understand what you want to achieve.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants