MrWolfZ/ngrx-forms

A form control value must be serializable

Closed this issue · 10 comments

Error: A form control value must be serializable (i.e. value === JSON.parse(JSON.stringify(value))), got: {"__boxed":"","value":{"isRange":false,"singleDate":{"date":{"year":2020,"month":9,"day":30},"jsDate":"2020-09-29T18:30:00.000Z","formatted":"2020-09-30","epoc":1601404200},"dateRange":null}}

I am using two dataTypes for form inputs. Both are not primitive. One of the input is boxed and unboxed without any issue.The other one gives the above error.

  1. type: MetaData {
    id?: string;
    parentContentAttributeId?: string;
    title?: string;
    description?: string;
    dataType?: string;
    sequenceNo?: number;
    createdDate?: string;
    createdBy?: null;
    dateModified?: string
    }
    2.type: export interface IMyDateModel {
    isRange: boolean;
    singleDate?: IMySingleDateModel;
    dateRange?: IMyDateRangeModel;
    }

export interface IMySingleDateModel {
date?: IMyDate;
jsDate?: Date;
formatted?: string;
epoc?: number;
}
export interface IMyDateRangeModel {
beginDate?: IMyDate;
beginJsDate?: Date;
beginEpoc?: number;
endDate?: IMyDate;
endJsDate?: Date;
endEpoc?: number;
formatted?: string;
}

The second one is causing the issue. Is it beause of nested object structure. Kindly help

Which version of the library are you using? I have unfortunately no explanation on why this is happening. I wrote a quick test to check this, but it works just fine:

const testValue = box({
  isRange: false,
  singleDate:
  {
    date: { year: 2020, month: 9, day: 30 },
    jsDate: '2020-09-29T18:30:00.000Z',
    formatted: '2020-09-30',
    epoc: 1601404200,
  },
  dateRange: null,
});

expect(verifyFormControlValueIsValid(testValue)).toBe(testValue);

Can you post the actual boxed value? What is displayed above is the output of JSON.stringify(), which for example drops undefined values, symbols etc.

Also, I recommend you set a breakpoint on exceptions to get into the verifyFormControlValueIsValid function. That will allow you to inspect the object and see why the equality check fails.

For this it is not even updating the state. While updating I am getting this error. FYI I am not using box and unbox method. Since by default it is boxing non primitive types. I hope it is a inbuild feature. Correct me If I am wrong

I debugged the code and found deepequals is the method which is causing the issue. I checked value and deserialized value , look sboth are same.

Boxing is unfortunately not performed automatically, so if you use e.g. setValue, you will have to use setValue(box(value)). However, in your example above the value seems boxed correctly.

Could you please investigate some more why deepEquals fails? Maybe there's a bug in there.

As I said earlier the other non primite type is boxing and unboxing without any code. How can that happen? This is the data in state.
{ controlId: 'TDF.channel', value: { __boxed: '', value: { id: 'D29A8502-F530-4E14-928E-E8515A6D4E92', sequenceNo: 2, createdDate: '2009-09-07T07:40:54.337+00:00', children: [], active: true, system: true, contentAttributeId: 'C75644A9-F875-4920-BB51-2E92E568B276', parentContentAttributeValueId: '00000000-0000-0000-0000-000000000000', enable: true, defaultLength: 0, code: 'MTS', name: 'Video', entityIdentifier: '' } }, type: 'ngrx/forms/SET_VALUE' }

Version I am using - 6.3.3

Ah, you are right, hahaha. I misremembered what I implemented. There is indeed automatic boxing happening for object values being set in form controls. Just not when manually setting the value via setValue etc.

In any case, since boxing happens correctly here, that is not the issue. We need to find out why the deepEquals returns false for the comparison of the original value and the serialized-then-deserialized-value. I cannot do this remotely. Unfortunately you will have to debug this and find out where the comparison fails. I recommend you set a breakpoint at every line that return false in the deepEquals function. That way you will know which comparison causes the issue.

Sure. I will debug that method and let you know.

Found the issue. But not sure how to fix.
I have jsdate in the value which is getting changed while serialization.
Actual Value: Fri Oct 23 2020 00:00:00 GMT+0530 (India Standard Time)
After Serialization : "2020-10-22T18:30:00.000Z"
Any thoughts would be helpful.

You mean you have an actual Date object in the value? Then the error is perfectly correct in saying that the value must be serializable (which a Date is not). The standard workaround is to use an ISO string in the form value instead of the Date object.

Thanks a lot @MrWolfZ . I fixed my issue.