15

I'm using reactive forms in my Angular 2 webapp and I'm having troubles assigning the date to ngbDatepicker (ngbootstrap 1 alpha 6). My object has a date object such as:

var myObject = {date: new Date(1, 9, 2016)};

and in my reactive form, it is configured as follow:

input.form-control(name='date', ngbDatepicker, #date="ngbDatepicker", placeholder='jj.mm.aaaa', formControlName='date', type="text")

and I patch the form like this:

this.form.patchValue({myObject: myObject});

The problem is that ngbDatepicker take the date with the following structure:

{day: DD, month: MM, year: YYYY}

I have found a workaround that does:

this.form.controls.myObject.controls.date.valueChanges
        .map((value) => {
            if(value) {
                if (typeof value.getMonth === 'function') {
                    this.form.controls.myObject.patchValue({
                        date: {
                            day: value.getUTCDay(),
                            month: value.getUTCMonth(),
                            year: value.getUTCFullYear()
                        }
                    });
                }
            }
            return value;
        })
        .subscribe((value) => {

        });

And everything works as expected (the date gets updated whenever form gets patched) but it is way too verbose (18 lines of code) and my form has a dozen of dates!

So my question is can I achieve the same result with a much shorter solution?

Nate
  • 7,606
  • 23
  • 72
  • 124

3 Answers3

11

I don't know if it might help you

ng-bootstrap: 1
angular: 2
bootstrap: 4

ngOnInit() {
const now = new Date();
const since = moment().subtract(14,'d').toDate();

this.model.fechaHasta = {year: now.getFullYear(), month: now.getMonth() + 1, day: now.getDate()};
this.model.fechaDesde = {year: since.getFullYear(), month: since.getMonth() + 1, day: since.getDate()};
}

HTML

<div class="input-group">
    <input class="form-control" placeholder="yyyy-mm-dd"
                name="fechaHasta" [(ngModel)]="model.fechaHasta" ngbDatepicker #d10="ngbDatepicker">

    <div class="input-group-addon" (click)="d10.toggle()">
       <img src="../../shared/img/calendar-icon.png" style="width: 1.2rem; height: 1rem; cursor: pointer;"/>
    </div>
</div>
3

I've just found your question while looking for a solution to the same problem. What I've done is leveraged momentjs, which is a date/time manipulation library (http://momentjs.com), and I'm manipulating dates coming from the database via momentjs before patching them into the form and initializing the ngbDatepicker.

this.START_DATE is the value from the database, and it comes as a string START_DATE : "2017-08-27"

var _savedStartDate = moment(this.START_DATE).toObject();

var _savedStartDateObject = {day:0,month:0,year:0};

    _savedStartDateObject.day = _savedStartDate.date;
    _savedStartDateObject.month = _savedStartDate.months;
    _savedStartDateObject.year = _savedStartDate.years;

this.form.patchValue({
  START_DATE: _savedStartDateObject
})

This is more verbose than it needs to be, you could create the object and assign the attributes in one line, but this is much more readable.

Basically create a moment date object by passing the date as a string into the moment() function, and then call the toObject function on the result, which gives you an object like this: {years: 2017, months: 7, date: 27, hours: 0, minutes: 0, seconds: 0, milliseconds: 0}

Then create an empty object in the format ngbDatepicker wants to see it {day:0,month:0,year:0}, and map the appropriate attributes from the moment object into the ngbDatepicker object, then call this.formpatchValue and pass in the newly created object with the appropriate format.

The relevant momentjs docs are here http://momentjs.com/docs/#/displaying/as-object/

Stephen R. Smith
  • 3,310
  • 1
  • 25
  • 41
2

@ncohen we fill the pain too, see: https://github.com/ng-bootstrap/ng-bootstrap/issues/754. There is no perfect solution at the moment and the ultimately one needs to come from Angular itself in a form of parsers / formatters known from AngularJS. There are already 2 issues in the Angular repo that track your use-case as a feature request:

I believe that for now your best option is to extract verbose code to an utility function and call it when conversion is needed (as suggested in one of the comments).

pkozlowski.opensource
  • 117,202
  • 60
  • 326
  • 286
  • You can now get/assign JS native Date object using Custom date adapter. Check this link: https://ng-bootstrap.github.io/#/components/datepicker/examples#adapter – Sanjeev Hegde Sep 24 '19 at 13:05