brutusin / json-forms

JSON Schema to HTML form generator, supporting dynamic subschemas (on the fly resolution). Extensible and customizable library with zero dependencies. Bootstrap add-ons provided
http://brutusin.org/json-forms
Apache License 2.0
607 stars 168 forks source link

Select option with value/title #85

Closed minhdqtt closed 7 years ago

minhdqtt commented 7 years ago

First of all, thanks for your awesome library, it helps me a lot...

I wonder if the library can render the select tag like:

<select>
  <option value="id1">Title 1</option>
  <option value="id2">Title 2</option>
</select>

for the enum, and I read the post https://github.com/brutusin/json-forms/issues/42, I found that we can use the script to decorate the returned object. But my situation is I load the scheme on the fly, and have no way to put the right decoration script.

I look into your source code: line 193-195:

var option = document.createElement("option");
var textNode = document.createTextNode(s.enum[i]);
option.value = s.enum[i];

then the value and the title are the same. Is there any support for value/title select in near future?

idelvall commented 7 years ago

Thanks for your kind words @minhdqtt!

Can you give me an example of your schema? Where do you get the title (option visible name) from?

minhdqtt commented 7 years ago

Thanks for your reply.

Imaging we have system that allow customer can select a web template, and each web template can modify some parameters. So, we have select tag:

<select id="tempSel">
  <option value="1">Template 1</option>
  <option value="2">Template 2</option>
</select>

When customer click on select (that change the template), we load the json schema from server. Because each template has difference option, for example, template 1 allow user change title, and type of menu (vertical or horizontal) and template 2 allow user to change title, and skin (light or dark), we use the code:

$("#tempSel").change(function() {
  $.ajax({
        type: "POST",
        url: url,
        data: JSON.stringify({ templateId: $("#tempSel").val() }),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (ret, textStatus) {
            var schema = JSON.parse(ret.d);
            var BrutusinForms = brutusin["json-forms"];
            bf = BrutusinForms.create(schema);
            bf.render($('#option-form')[0]);
        }
    });
});

The return schema form server has something like:

{
  "$schema": "http://json-schema.org/draft-03/schema#",
  "type": "object",
  "properties": {
    "Title": {
      "type": "string",
      "title": "Tiêu đề trang",
      "required": true
    },
    "MenuType": {
      "type": "string",
      "title": "Kiểu menu",
      "required": true,
      "enum": [
        "vertical",
        "horizontal"
      ],
      "display": [
        "Menu kiểu dọc",
        "Menu kiểu ngang"
      ]
    }
  }
}

so, the form can render the like:

<select>
  <option value="vertical">Menu kiểu dọc</option>
  <option value="horizontal">Menu kiểu ngang</option>
</select>

Of cause, if user select template 2, the form like:

<select>
  <option value="light">Giao diện sáng màu</option>
  <option value="normal">Giao diện trung tính</option>
  <option value="dark">Giao diện tối màu</option>
</select>

How can I archive this? Thank you

idelvall commented 7 years ago

Hi, this is easy with a decorator that in case of rendering a select (checking tagName), checks if the schema contains a "display" property, and in that case overrides the options inner text Cheers

minhdqtt commented 7 years ago

Thanks for your support. I put my code here to hope that it's helpful for someone:

brutusin["json-forms"].addDecorator(function (element, schema) {
    if (element.tagName) {
        var tagName = element.tagName.toLowerCase();
        if (tagName === "select" && schema.display) {
            var opts = $(element)[0].options;
            $.each(opts, function (index, option) {
                if (index > 0) $(option).text(schema.display[index - 1]);
            });
        }
    }
});
rlamorea commented 6 years ago

It seems that the method to add descriptors to enumerated values in json-schema is via "oneOf" - as described in this issue: json-schema-org/json-schema-spec#520

sunilb0575 commented 5 years ago

For a drop down

'program': {
                'type': 'string',
                 'enum': programs.map((program) => program.name)
              },

where Programs is an array

programs: [ 
{id: 1, name: "Therapeutic Behavioral Services", identifier: "TBS", start_date: null, end_date: null}
{id: 2, name: "School-Based Therapy", identifier: "", start_date: null, end_date: null}
{id: 3, name: "Intensive Home Based Services", identifier: "IHBS", start_date: null, end_date: null}
{id: 4, name: "Therapeutic Foster Care", identifier: "TFC", start_date: null, end_date: null}
]

So the list of items in the drop down are names of the programs.

Is there a way I can store ID instead of name, when the user selects the name from the dropdown? @idelvall