Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PrimeNG Calendar control Reactive Forms update value when calendar control is in invalid state does not see to update Calendar UI

I am using PrimeNG Calendar control in an Angular Reactive Forms application. In my application I have a form with a calendar control inside a Primefaces dialog.

When an invalid date value is typed into the calendar control I programmatically update the value of the control to a predefined rollback date value when the dialog is closed so that when it is shown again the form is in a valid state.

However, I have found that updating the value of the calendar control programmatically does not consistently update the UI with the new value.

I am using a FormGroup and have tried both setValue and patchValue. I have also tried using setValue and patchValue on the calendar control explicitly and also the reset method of formGroup. The problem still occurs.

Just wondering if anybody can advise on where I am going wrong in the code?

I have created a plunker at http://plnkr.co/edit/xc4ygZ?p=info , to illustrate an example. The code for the angular component and template is included below....

import {
  Component
} from '@angular/core';
import {
  FormBuilder
} from '@angular/forms';
import {
  FormGroup
} from '@angular/forms';
import {
  OnInit
} from '@angular/core';
import {
  Validators
} from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: 'app/app.template.html'
})


export class AppComponent {

  birthDate: Date;
  form: FormGroup;

  formErrors = {
    'setdate': '',
  };


  validationMessages = {
    'setdate': {
      'required': 'Set date is required.',
      'invalidDate': 'Invalid Date.'
    },
  };


  constructor(private fb: FormBuilder) {

    this.birthDate = new Date();
  }


  ngOnInit(): void {
    this.buildForm();
  }


  onSubmit(): void {

  }


  setSetDate(): void {
    let today = new Date();

    this.form.patchValue({
      setdate: today
    });

  }


  private buildForm(): void {
    this.form = this.fb.group({
      setdate: [this.birthDate, [Validators.required]]
    });

    this.form.valueChanges
      .subscribe(data => this.onValueChanged(data));
    //this.onValueChanged(); 
  }





  private onValueChanged(data ? : any): void {

    let _self = this;

    if (!this.form) {
      return;
    }
    const form = this.form;

    console.log("onValueChanged()");
    for (const field in this.formErrors) {
      // clear previous error message (if any)
      this.formErrors[field] = '';
      const control = form.get(field);
      if (control && control.dirty && !control.valid) {
        const messages = this.validationMessages[field];
        for (const key in control.errors) {
          this.formErrors[field] += messages[key] + '\n';
        }
      }
    }
  }

}
<p> Enter a date that is invalid, e.g. edf. Then try clicking the button to programmatically reset the date</p>
<p> The UI for the calendar control does not consistently update with the new date. </p>
<form autocomplete="off" [formGroup]="form" novalidate (ngSubmit)="onSubmit()">

  <div class="form-group">
    <label for="setdate" class="control-label col-xs-4">Set Date</label>
    <div>
      <p-calendar #theDate id="setdate" formControlName="setdate" showTime="true" hourFormat="24" dateFormat="dd-mm-yy" [showIcon]="true" placeholder="Set Date" required>

      </p-calendar>
      <p>SetDate Value :: {{ theDate.value }}</p>
      <p>SetDate Valid :: {{ this.form.controls['setdate'].valid }}</p>
      <p>SetDate Errors :: {{ this.form.controls['setdate'].errors | json }}</p>
    </div>

    <div *ngIf="formErrors.setdate" class="alert alert-danger">
      {{ formErrors.setdate }}
    </div>

  </div>
  <button type="button" class="btn" (click)="setSetDate()">Test SetDate</button>
</form>
like image 569
dcs3spp Avatar asked Nov 07 '22 19:11

dcs3spp


1 Answers

I had two things that were causing Reactive Forms and PrimeNG to not behave together.

  1. I was using this.myForm.reset() which was wiping out necessary data on PrimeNG components.

    Solution

    I reset the values using this.myForm.patchValue({myFormControlName: 'my reset value'}).

    Of course you could use this.myForm.setValue() if you prefer.

  2. On my calendar I had done what Yaroslav Admin describes here. Essentially I wasn't passing a date object. I was passing a unix time stamp as number type.

    Solution

    Instead of:

    const time = 1562162176;
    this.form.controls.calendarField.setValue(time)
    

    do this:

    const time = new Date(1562162176);
    this.form.controls.calendarField.setValue(time)
    
like image 180
Tom Benyon Avatar answered Nov 14 '22 21:11

Tom Benyon