Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine datepicker and timepicker values with ngx-bootstrap

I am using ngx-bootstrap in an Angular 5 project. Does anyone know how to combine the Datepicker with Timepicker? When I select a time it always includes today´s date. I want to use the date selected in the Datepicker.

Even better would be to have it on the same model if possible. The idea is to pass this into a webapi which accepts a datetime property(c#).

Thanks in advance!

like image 926
Jocke Avatar asked Jan 10 '18 09:01

Jocke


2 Answers

Both the values of Datepicker and Timepicker will be of type Date.

So you can simply combine their values before sending the result to the server.

For example, assuming that you stored the value of Datepicker inside a date variable and the Timepicker inside the time variable, you can do the following:

date.setHours(time.getHours(), time.getMinutes(), time.getSeconds());

now date contains both the date from the Datepicker and the time frome the Timepicker, so you can now send date to the server (in whatever format you need).

like image 133
Francesco Borzi Avatar answered Sep 22 '22 01:09

Francesco Borzi


Alternatively, you can combine the Date and Time Pickers into a custom ControlValueAccessor and abstract away the need to combine separate date & time values on a per item basis.

The code below is opinionated in the sense that:

  • It makes both date and time required.
  • It eliminates the spinner arrows to create a more "even aesthetic".
  • Assumes you want the date field to grow as the view-port grows.

But it can easily be modified and should form a good basis for accomplishing this task.

Component

// datetime-picker.component.ts
import { Component, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor, FormGroup, FormControl, Validators } from '@angular/forms';

interface DateAndTime {
  date: Date;
  time: Date;
}

@Component({
  selector: 'datetime-picker',
  templateUrl: './datetime-picker.component.html',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => DatetimePickerComponent),
    multi: true
  }]
})
export class DatetimePickerComponent implements ControlValueAccessor {
  private onChange: (value: Date) => void;

  public datetime: Date = new Date();
  public form: FormGroup;

  constructor() {
    this.form = new FormGroup({});
    this.form.addControl('date', new FormControl(this.datetime, Validators.required));
    this.form.addControl('time', new FormControl(this.datetime, Validators.required));
    this.onChanges();
  }

  private onChanges(): void {
    // listen for changes, and recombinate internal datetime when they occur
    this.form.valueChanges.subscribe((f: DateAndTime) => this.setDatetime(f));
  }

  private setDatetime(d: DateAndTime) {
    this.datetime.setFullYear(d.date.getFullYear(), d.date.getMonth(), d.date.getDate());
    this.datetime.setHours(d.time.getHours(), d.time.getMinutes(), 0, 0);

    this.onChange(this.datetime);
  }

  /*
   * Control Value Accessor
   */
  writeValue(value: Date): void {
    // This method is called with the `null` value when the form resets.
    // A component's responsibility is to restore to the initial state.
    if (value === null) {
      value = new Date();
    }

    this.datetime = value;
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void { }

  setDisabledState?(isDisabled: boolean): void { }
}

View

// datetime-picker.component.html
<div class="d-flex" [formGroup]="form">
  <div class="flex-grow-1 pr-3">
    <input type="text" class="form-control" formControlName="date" bsDatepicker />
  </div>
  <div>
    <timepicker formControlName="time" [showSpinners]="false"></timepicker>
  </div>
</div>
like image 24
pim Avatar answered Sep 22 '22 01:09

pim