Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change model structure of angular powered bootstrap ngbDatepicker

I am using angular powered bootstrap ngbDatepicker. I have created my own custom control which will be used in different pages for date capturing as follows.

<form-date 
  [label]="'Date of birth'" 
  [name]="'inputCPDDOB'"
  [(ngModel)]="birthDate"
  placeholder="mm/dd/yyyy"
  required
  >
</form-date>

Here I have passed birthDate as my model object.

I want

  1. User should be able to choose the date by clicking the CAL button (beside the text box),
  2. User should be able to type a date in format 'MM/DD/YYYY' in the textbox.
  3. After selecting or typing the date, the model should be updated as string with format 'YYYY-MM-DD' by two way data binding.

I have successfully did point#1 and point#2 the date format of text box as MM/DD/YYYY by inheriting NgbDateParserFormatter

But I am not able to change the model structure. While I need to communicate with my web service as 'YYYY-MM-DD' format.

Please help me to achieve the same. Here is the plunker attached.

like image 931
Partha Sarathi Ghosh Avatar asked Dec 21 '17 06:12

Partha Sarathi Ghosh


Video Answer


1 Answers

So I think the easiest way to solve your problem is to provide your own implementation of NgbDateAdapter and inject that into you component. You will need to add

{provide: NgbDateAdapter, useClass: NgbUTCStringAdapter}

to you components providers array and define the NgbUTCStringAdapter somewhere:

@Injectable()
export class NgbUTCStringAdapter extends NgbDateAdapter<string> {

  fromModel(date: string): NgbDateStruct {
    return (date && Number(date.substring(0, 4)) && Number(date.substring(5, 7) + 1) && Number(date.substring(8, 10))) ?
                {year: Number(date.substring(0, 4)),
                    month: Number(date.substring(5, 7)),
                    day: Number(date.substring(8, 10))} : null;
  }

  toModel(date: NgbDateStruct): string {
    return date ? date.year.toString() + '-' + String('00' + date.month).slice(-2)
                            + '-' + String('00' + date.day).slice(-2) : null;
  }
}

The other way to do it would be to put this code into your custom form control something like this:

@Component({
selector: 'app-date',
templateUrl: './date.component.html',
providers: [
    {
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => DateComponent),
        multi: true
    },
    {provide: NgbDateParserFormatter, useClass: NgbDateOmniParserFormatter}]
})

export class DateComponent implements ControlValueAccessor {

  model;

  writeValue(value: any) {
    this.model =  (value && Number(value.substring(0, 4)) && 
                        Number(value.substring(5, 7) + 1) &&
                        Number(value.substring(8, 10))) ?
                            {year: Number(value.substring(0, 4)),
                             month: Number(value.substring(5, 7)),
                             day: Number(value.substring(8, 10))} : null;
  }

  propagateChange = (_: any) => {};

  registerOnChange(fn) {
    this.propagateChange = fn;
  }

  registerOnTouched() {}

  change() {
    const date = this.model ? this.model.year.toString() + '-' + 
                   String('00' + this.model.month).slice(-2) + '-' +
                   String('00' + this.model.day).slice(-2) : null;

    this.propagateChange(date);
  }
}
like image 83
Iain Avatar answered Oct 21 '22 21:10

Iain