12

I have a component that uses two date fields, a start date & and end date.

By default, I have my end date field disabled and I toggle it when they select a start date.

this.transitionForm = this.fb.group({
 effectiveEndDate: [{ value: '', disabled: true }]
 ..... 
});

I am trying to set the value of this end date field within my code.

this.transitionForm.controls['effectiveEndDate'].setValue(this.utils.currentDate());

Utility Function:

/**
 * Returns the current date
 */
currentDate() {
    const currentDate = new Date();
    const day = currentDate.getDate();
    const month = currentDate.getMonth() + 1;
    const year = currentDate.getFullYear();
    return month + "/" + day + "/" + year;
}

HTML:

<input type="date" class="form-control input-sm" id="effectiveEndDate" name="effectiveEndDate" placeholder="Required" formControlName="effectiveEndDate">

For some reason, the field is not getting updated though.

I have also tried to use PatchValue and that wasn't setting it either.

What am I missing?

SBB
  • 8,560
  • 30
  • 108
  • 223

4 Answers4

21

When you run this code in Chrome (other browsers not tested) it logs an error to console:

The specified value "7/26/2017" does not conform to the required format, "yyyy-MM-dd".

Which I think describes the problem pretty well

You can fix it by changing your currentDate() method to something like:

currentDate() {
  const currentDate = new Date();
  return currentDate.toISOString().substring(0,10);
}

Live plunker example

While this does fix the problem the answer from @JGFMK shows a better way of converting the date using a DatePipe

0mpurdy
  • 3,198
  • 1
  • 19
  • 28
17

FormBuilder.group returns FormGroup:
https://angular.io/api/forms/FormBuilder#group
https://angular.io/api/forms/FormGroup#setValue

Updates:


import {DatePipe} from '@angular/common'
...
let dp = new DatePipe(navigator.language);
let p = 'y-MM-dd'; // YYYY-MM-DD
let dtr = dp.transform(new Date(), p);
this.transitionForm.setValue({effectiveEndDate: dtr}); 

Plunker example (just hit reset)

JGFMK
  • 8,425
  • 4
  • 58
  • 92
  • 1
    Thanks for the reply, it did not work however. The date field remains at its default stare, prompting for the date selection. – SBB Jul 26 '17 at 15:02
  • @0mpurdy ??? I see the code I discussed in my post.. It's in the src/app.ts???? I did re-use the UI you'd created... Just to demo it works... It's not plagiarised in as much as the solution to the core problem is different. – JGFMK Aug 03 '17 at 15:36
  • @JGFMK no problem! it was just that the plunker was still showing my version - I thought you may have forgotten to unfreeze after making the changes :) (It could however have possibly been a caching issue on my part - the terminology I used was a bit strong too I didn't mean it like that) I'll delete my comment (and this one) shortly as they're no longer relevant - have a good day! – 0mpurdy Aug 03 '17 at 15:40
8

Angular has several ways to work with and manage forms. Not all the methods or even all configurations will show a value in the view. I have tried several options and my favorite by far is a reactive form configured like this, as it is simple, clean, flexible, supports validation and will show values in the view.

In your component you need to import FormBuilder and FormGroup from @angular/forms. Optionally you can import Validators as a way to validate each form field.

import { FormBuilder, FormGroup, Validators } from '@angular/forms';

In the rest of the component we need to define a new variable of type FormGroup: transitionForm: FormGroup.

Then we need to use constructor injection to make fb available as FormBuilder: constructor(public fb: FormBuilder), and add field names to our FormBuilder variable: this.transitionForm = fb.group({ ... });

export class EgComponent implements OnInit {
  transitionForm: FormGroup;

  constructor(public fb: FormBuilder) {
    this.transitionForm = fb.group({
      'effectiveEndDate': [''],
      ...
    });
  }
  ...
}

You can set the date in many ways. Here we'll just set it using ngInit

ngOnInit() {
  const currentDate = new Date().toISOString().substring(0, 10);
  this.transitionForm.controls['transitionForm'].setValue(currentDate);
}

For your form you just need is:

<form (ngSubmit)="onSubmit(transitionForm)" [formGroup]="transitionForm" novalidate>
  <input type="date" formControlName="effectiveEndDate">
  ...
  <button type="submit" [disabled]="transitionForm.invalid">Submit</button>
</form>

Because this method uses ReactiveForms you need to make sure to add it to @NgModule

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...,
    FormsModule,
    ReactiveFormsModule
  ],
...

Besides making data visible in the view, doing it this way also allows for cleaner html form layout and simple validation. You completely eliminate the need for ngModel and form name tags.

You can pass data to your method directly (ngSubmit)="onSubmit(transitionForm)" and since it's a FormGroup your forms data is also available as this.transitionForm.value

Jared Whipple
  • 1,111
  • 3
  • 17
  • 38
0
<input formControlName="loadActivationTime" [value]="transitionForm .get('effectiveEndDate').value | date: 'dd/MM/yyyy hh:mm'"   readonly="readonly" matInput placeholder="effectiveEndDate">
David Buck
  • 3,752
  • 35
  • 31
  • 35
  • 4
    While this code may solve the question, [including an explanation](https://meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – David Buck Jun 23 '20 at 19:16