dschnelldavis / angular2-json-schema-form

Angular 2 JSON Schema Form builder
MIT License
285 stars 177 forks source link

Adding/removing additional properties on object #104

Open aconanlai opened 7 years ago

aconanlai commented 7 years ago

I am thinking of implementing this myself, but wanted to check if anyone had any experience with this, or if a current maintainer has any ideas about the feasibility:

I'd like to make object properties addable/removable. For example, if a data structure looks like:

{
  "countries": {
    "Finland": {
      "population": 100
    },
    "Chile": {
      "population": 200
    }
  }
}

I'd like for users to be able to remove and add properties from 'countries', much like the feature currently available on arrays (I am using an existing API and cannot change the shape of this data structure). I can enforce the structure in the JSON Schema in the following way:

"additionalProperties": {
  "$ref": "#/definitions/country"
}

Has anyone tried this or have any insight into how to tackle it? If it's do-able, I will be happy to make a PR when I'm done.

dschnelldavis commented 7 years ago

You're right, additionalProperties are not currently supported.

I believe the add-reference widget (and the Material Design version) could be modified to support this.

The current add-reference widget displays as a button, and is used both to add additional items to arrays and also to add sections to recursive reference points (where a schema uses a $ref to refer to one of its own ancestors). When a user presses the button, it calls the addItem() function, which detects which action it needs to take (add array item or add object property) by checking the layoutNode's boolean 'arrayItem' property (true = add array item, false = add object property).

To support additionalProperties, the control would need to be modified to show both an input control (or a select control, if propertyNames is an enum) and a button. The button would initially be disabled, but when the user enters (or selects) a valid property name, the button would become enabled and the user could press it to add the new property.

My suggestion would be to have it check the layoutNode's 'name' property, which the widget already uses for recursive references to set the name of the object property it's adding, and display the input or select control if 'name' is null.

The most complicated bit will be supporting all the schema rules about when and what names are allowed, including maxProperties, minProperties, patternProperties, and propertyNames. Max and min should be relatively easy—just hide the widget when max is reached (it already does this for arrays). PatternProperties and propertyNames will be more complicated, and will probably require some hints or error messages to help the user enter a valid property name.

If you want to take this on, that would be awesome. I think it's definitely doable, I just don't have time to do it myself at the moment. But if you'd like to take a shot at it, I'll be glad to give you a hand if you get stuck.

Thanks!