ngx-schema-form icon indicating copy to clipboard operation
ngx-schema-form copied to clipboard

Model of Array does not get updated

Open marc101101 opened this issue 7 years ago • 14 comments

Hey guys,

sorry for again opening a issue. I love your library. Great job! My Problem: I have this snippet as part of my schema file:

region: { title: "Deployment Region(s)", type: "array", items: { type: "string", title: "items", description: "items", oneOf: [{ description: "EU", enum: [ "EU" ] }, { description: "US", enum: [ "US" ] }, { description: "RUS", enum: [ "RUS" ] }, { description: "CANADA", enum: [ "CANADA" ] }, { description: "SOUTH-AMERICA", enum: [ "SOUTH-AMERICA" ] }, { description: "ASIA-PACIFIC", enum: [ "ASIA-PACIFIC" ] }, { description: "OTHER", enum: [ "OTHER" ] } ], widget: "select" }, minItems: 1, uniqueItems: true, description: "Deployment Region(s)" }

It is an array to which the user can add selects and the rendering works perfectly. tst My problem now: I want to generate a json by using the model. But the values do not update the values of the array elements. The model contains the added items but the values are still empty. All other values on a higher level are all set correctly. "region": [ "", "" ]

Hope you can help :)

marc101101 avatar Jun 09 '17 08:06 marc101101

I have added your Region field in the test app here: https://github.com/makinacorpus/angular2-schema-form/blob/master/tests/src/app/sampleschema.json

and it seems to work properly, I get this kind of output: "region":["US","SOUTH-AMERICA"],

So I guess your problem comes from something else in your app. I suggest you make a new empty app, use your schema and then progressively move over your original app elements to see when it fails.

ebrehault avatar Jun 09 '17 08:06 ebrehault

Thanks for your fast reply. I use this statement in my app.component.html <sf-form [schema]="element.data" [model]="element.model" (onChange)="onChange(element, $event, element.uid)"></sf-form> And I use $event.value to update my model value in the app.component.ts In the onChange() method I receive the value missing model json. Okay I will try your suggestion

marc101101 avatar Jun 09 '17 08:06 marc101101

okay I sloved the problem by simply removing [model]="element.model" this was causing the problems.

marc101101 avatar Jun 09 '17 08:06 marc101101

@ebrehault I think that there is still a bug somehow? If I change the value of the select input, the (onChange) method does not get triggerd. I am right?

marc101101 avatar Jul 19 '17 14:07 marc101101

nope in your sample application it works

marc101101 avatar Jul 19 '17 18:07 marc101101

Hi Marc, I also ran into this problem today! I used (onChange) to update my model with this function:

onFormChange(e) {
    this.result = e.value;
  }

This method won't update the array properties of the model, but I changed to this one, and now works as I expected:

onFormChange(e) {
   if (this.isDirty()) { // only update your model when it's dirty!
     Object.assign(this.result.document, e.value);
   }
 }

pankyka avatar Jul 25 '17 08:07 pankyka

@pankyka where in my html template can I reference to this method? In the ?

marc101101 avatar Jul 28 '17 11:07 marc101101

Hi Marc, this is a custom method on my component. You should check your object when it's dirty. For example, I save my original model (deep clone) and I edit in a new object. My isDirty method looks like this:

isDirty() {
  return _.isEqual(this.original, this.result);
}

I use lodash for equality check.

pankyka avatar Jul 28 '17 12:07 pankyka

yeah - I got this. Do you not reference from the html template to onFormChange(e). Because actually if something is changing in the the (onChange)="METHOD()" should get triggerd. I dont get why this is not triggerd if I change the selected option.

@ebrehault in your sample/test application everything works.

marc101101 avatar Jul 28 '17 12:07 marc101101

Yes, two-way binding [(model]] would be much better.

pankyka avatar Jul 28 '17 13:07 pankyka

some information for you. I am using materialize.css and I am writing custom widgets. If I switch back to the default widget registry everything works. Maybe my select widget is corrupted.

export class MySelectWidget extends ControlWidget implements AfterViewInit {
  ngAfterViewInit(): void {
    $('select').material_select();
  }
<div class="col l9">
    <div class="input-field col s12">
      <select [attr.class]="'select ' + schema.title">
          <option *ngFor="let option of schema.oneOf" [ngValue]="option.enum[0]">{{option.enum[0]}}</option>
        </select>
      <label>{{ schema.title }} Select</label>
    </div>
    <input class="selectValue" *ngIf="schema.readOnly" [attr.name]="name" type="hidden" [formControl]="control">
  </div>

marc101101 avatar Jul 28 '17 13:07 marc101101

Yes, it's due to the ngAfterViewInit hook. I don't know why but all widget is dead when it implements the AfterViewInit interface. I use angular material and covalent ui controls.

pankyka avatar Jul 28 '17 13:07 pankyka

WidgetControl class implements the ngAfterViewInit hook. Does calling super.ngAfterViewInit in your hook solves the problem?

fbessou avatar Jul 31 '17 08:07 fbessou

yeah thanks. That was the problem :)

marc101101 avatar Aug 01 '17 09:08 marc101101