In Angular 2 projects (version 4.x), I make heavy use of Reactive Forms, both to create data and edit it.
When fetching an object from the database, I get all of its keys (via UnderscoreJS), then iterate over the object for each key and use patchValue to load the data into the form.
I'm using both Underscore.js and Moment.js, so they're imported into the component:
import * as _ from 'underscore';
import * as moment from 'moment';
The iterator and patch functions are as follows:
In the iterator, I'm using a regular expression to find values that match the date format coming from the database - these come as strings, not dates, and always in the format 'yyyy-mm-dd'. In the component, I'm using ng-bootstrap calendar pickers, so I need to catch the dates, convert them into an NgbDateStruct object format before patching them into the form.
updatedFormWithJSONData(inputObject: any) {
var _keys = _.keys(inputObject);
var _re = /\d{4}[-]\d{1,2}[-]\d{1,2}/g; //RexEx to match 2017-09-05 (or 2017-9-5) - yyyy-mm-dd format
for (let key of _keys) {
console.log("item.key", key);
console.log("item.value", inputObject[key]);
if (_re.test(inputObject[key])) {
console.log("Is Date", inputObject[key]);
var dateValue = moment(inputObject[key]);
var NgbDateStruct = { day: dateValue.date(), month: dateValue.month() + 1, year: dateValue.year()};
console.log("Date Value", NgbDateStruct);
this.updateSelected(key, NgbDateStruct);
} else {
this.updateSelected(key, inputObject[key]);
}
}
}
The update function tests to make sure the key and value both have values, and that the form contains the key, then patches the form.
updateSelected(key, value) {
if (key && value && this.form.contains(key)) {
this.form.controls[key].patchValue(value)
}
}
This all works, so I can test this by assigning a JSON block to a variable, and then calling the function, passing in the variable and the form loads.
var fetchedData = [{
"purchased_date": "2017-09-16",
"purchase_description": "Some description",
"purchase_reason": "Some Reason",
"pickup_date": "2017-09-14"
}]
And I can call it like this:
this.updatedFormWithJSONData(fetchedData[0]);
Note: The objects from the database always come in an array, which is why I'm plucking the first object off the array.
Now - the problem is, as long as there is a non-date key/value pair in the data between two date key/value pairs, everything works fine, but if there are two date key/value pairs beside each other, the second one doesn't match the regex, and doesn't get patched into the form.
So the above works fine, but the following skips the pickup_date:
var fetchedData = [{
"purchased_date": "2017-09-16",
"pickup_date": "2017-09-14"
"purchase_description": "Some description",
"purchase_reason": "Some Reason",
}]
I have no idea why the second date when adjacent in the data fails, but I would like to be sure that regardless of the ordering of the fetched data, all the dates will be handled properly.
Update: Here are some snippet from the console.log:
The first, working example logs out like this:
item.key purchased_date
item.value 2017-09-16
Is Date 2017-09-16
Date Value {day: 16, month: 9, year: 2017}
item.key purchase_description
item.value Some description
item.key purchase_reason
item.value Some Reason
item.key pickup_date
item.value 2017-09-14
Is Date 2017-09-14
Date Value {day: 14, month: 9, year: 2017}
The second, non-working example logs out like this:
item.key purchased_date
item.value 2017-09-16
Is Date 2017-09-16
Date Value {day: 16, month: 9, year: 2017}
item.key pickup_date
item.value 2017-09-14
item.key purchase_description
item.value Some description
item.key purchase_reason
item.value Some Reason
Followup: while ultimately the problem was in the parameters of the regex expression, the problem the question aimed to solve was with iterating over a JSON data file in order to load the values into a reactive form in an Angular 2 application, and the code provided was producing incorrect output in a very specific case. It wasn't clear that the regex was the problem, so the solutions similar to the actual regex solution weren't even on my radar.