ReactiveForms in Angular 2 generate JSON with empty value or empty object for my optional field

2.3k Views Asked by At

I have an issue with reactive forms in angular 2. I want to create my object to send it to my API but my ReactiveForms generate also no required field and formgroup.

If I send directly my object thanks to http post request I have this JSON :

MyObject{
Name:"toto"
Surname:""
   Address:{
    City:"",
    StreetName:""
   }
}

But I want this JSON to agree with the API. (If there is empty or null property/object I obtain an error because the fields are present but not valid:

MyObject{
Name:"toto"
}

Because Surname and Address is optionnal.

I use ReactiveForm with formBuilder and I do not know how I can obtain only fill fields.

This how I create my form :

myForm: FormGroup;
myUserModel : UserModel; // (Interface UserModel such as my form fields)

constructor(private fb : FormBuilder){}

createForm(){
   this.myFrom = this.fb.FormGroup({
      Name:['';Validators.requires],
      Surname:'',
      Address:this.fb.FormFroup({
          City: '',
          StreetName:''
      })
   })
}

onSubmit(){
    this.myUserModel = this.myForm.value;
    this.registerUserToAPI(this.myUserModel);
}

To cheat I use this but it's so dirty... :

cleanObjectToSend(obj){
    return this.removeEmptyObj(this.removeEmptyAttribute(obj));
  }

  removeEmptyAttribute = (obj) => {
    Object.keys(obj).forEach(key => {
      if (obj[key] && typeof obj[key] === 'object') this.removeEmptyAttribute(obj[key]);
      else if (obj[key] == null || obj[key] == '') delete obj[key];
    });
    return obj;
  };

  removeEmptyObj(obj){
    Object.keys(obj).forEach(key => {
      if (obj[key] && typeof obj[key] === 'object') {
        if(Object.keys(obj[key]).length===0 && obj[key].constructor == Object){
          delete obj[key];
          return;
        }
        else this.removeEmptyObj(obj[key]);
      }
      else if (obj[key] == null || obj[key] == '') delete obj[key];
    });
    return obj;

  }

It allow me to obtain only not null and not empty field to generate my JSON then.

How can I have a JSON clean JSON directly without null or empty value ?

2

There are 2 best solutions below

1
On BEST ANSWER

Ok with your answer Lazar Ljubenović but there is no other way to make this in angular? Use an other form type such as Template Driven Form and ngModel for example ?

Update :

I think this is the better way to clean your JSON Object without delete. It works with nested object !

JSON.stringify(myModel,this.replacer);

replacer(key,value){
if(value == null || value == '' || (Object.keys(value).length === 0 && value.constructor == Object) || value == {})
  return undefined;
else if(value && typeof value === 'object'){
  let isEmptyObject = true;
  Object.keys(value).forEach(key => {
    if(value[key] != null && value[key] != ''){
      isEmptyObject = isEmptyObject && false;
    }
  });
  if(isEmptyObject) return undefined;
  else return value;
}
else return value;
}
0
On

They're present because you've entered them. (I've edited your code because it has weird syntax errors and typos.)

this.myFrom = this.fb.group({
   Name: ['', Validators.required],
   Surname: '',
   Address:this.fb.group({
       City: '',
       StreetName: '',
   })
})

If the user does not touch the form, those values will stay as you've written them. Empty strings are also values.

What you can try is using undefined as default value.

this.myFrom = this.fb.group({
   Name: [undefined, Validators.required],
   Surname: undefined,
   Address:this.fb.group({
       City: undefined,
       StreetName: undefined,
   })
})

However, if a user comes to the field, types a letter, and then leaves, this would be an empty string again. So there is no real way to do what you want automatically, as it's your own custom logic based on your API.

I suggest that you fix the server. An empty string is usually "not entered", and not "wrong format" or something else. Sending an empty string should not count as any value has been entered, unless an empty string could be a valid value for some fields; but this is hardly ever the case.