[Fixed] Why am I getting this error using ngModelChanges in my ngbtimepicker when all the data is returned correctly?

Issue

I have an ngbtimepicker. I am creating a time sheet in which users can only enter time in 0-15-30-45 increments. I am using a popup modal to enter time. If a user types for example 10:23pm, I want the timepicker to round to the nearest 15 min which would be 10:30 in this case. As I type in 10:23pm, and then click out of focus, the time does change to 10:30. I also have a save button, so when clicking on save it will save that data. I checked the chrome tools to see if it returns the correct data using my method to make that change using (ngModelChange) and it checks out.

However, the method is called again after I hit the save button and I get a typeError of "Can not read property ‘minute’ of null.

I put in a debugger, and after i hit the save button it goes through my method again of setStartMinutesOnChanges(startTime) and shows startTime = null. How do I fix this?

<input type="text" ngbDatepicker [(ngModel)]="start" [firstDayOfWeek]="7" #sd="ngbDatepicker" name="day_s" class="form-control form-control-sm dark-text" id="start">
              <div class="input-group-append">
                <button class="btn btn-outline-secondary btn-sm calendar" style="background-color:#1ab394;height:31px;" (click)="sd.toggle()" type="button">
                  <fa-icon [icon]="faCaretDown" style="color:white;"></fa-icon>
                </button>
              </div>
            </div>
            <div class="col-4 d-flex justify-content-center">
              <ngb-timepicker [(ngModel)]="startHM" name="startDate" (ngModelChange)="setStartMinutesOnChange($event)" [meridian]="meridian" [minuteStep]="15" size="small"></ngb-timepicker>
            </div>
          </div>
export class EditAppointmentComponent implements OnInit  {

  recId = 0; entry: IAppointment; resources: IResource[]; recurrances: IRecurranceType[]; saving = false;
  meridian = true; start: NgbDateStruct; startHM = {hour: 0, minute: 0}; end: NgbDateStruct; endHM = {hour: 0, minute: 0};
  faCaretDown=faCaretDown; ticketId: number = 0;


  @ViewChild('editAppointmentForm') formValues;

  static show(modalService: NgbModal, id: number, tid: number): Promise<number> {
    let mRef = modalService.open(EditAppointmentComponent, { ariaLabelledBy: 'edit-appointment', backdrop: 'static', keyboard: true, size: 'lg' });
    let c = <EditAppointmentComponent>mRef.componentInstance; c.recId = id; c.ticketId = tid;
    return mRef.result;
  }

  constructor(private globals: GlobalsService, private server: ServerService, private activeModal: NgbActiveModal, private modalService: NgbModal,
    ) {}


  get form(): import("@angular/forms").NgForm { return this.formValues; }

  ngOnInit() { this.load(); }

  setStartMinutesOnChange(startTime) {

    let m = ((Math.round(startTime.minute/15) * 15) % 60);

    if(startTime.minute != 0 || startTime.minute != 15 || startTime.minute != 30 || startTime.minute != 45) {
      this.startHM = {hour: startTime.hour, minute: m };
    }
    console.log(this.startHM);
  }

Solution

The functionality works just fine, so the second time it runs through the (ngModelChange) it declares startTime and endTime as null. A simple fix I did was just if both of those are null or not values, just return so that I can keep on going.

setStartMinutesOnChange(startTime) {
    if(!startTime) return;
    let m = ((Math.round(startTime.minute/15) * 15) % 60);

    if(startTime.minute >= 53) {
        this.startHM = {hour: startTime.hour + 1, minute: 0};
    } else if(startTime.minute != 0 || startTime.minute != 15 || startTime.minute != 30 || startTime.minute != 45) {
        this.startHM = {hour: startTime.hour, minute: m };
    }
  }

  setEndMinutesOnChange(endTime) {
    if(!endTime) return;
    let m = ((Math.round(endTime.minute/15) * 15) % 60);

    if(endTime.minute >= 53) {
      this.endHM = {hour: endTime.hour + 1, minute: 0};
    }
    if(endTime.minute != 0 || endTime.minute != 15 || endTime.minute != 30 || endTime.minute != 45) {
      this.endHM = {hour: endTime.hour, minute: m };
    }
  }

Leave a Reply

(*) Required, Your email will not be published