surveyjs / survey-library

Free JavaScript form builder library with integration for React, Angular, Vue, jQuery, and Knockout.
https://surveyjs.io/form-library
MIT License
4.18k stars 808 forks source link

object values for dropdowns are broken in react #1525

Closed awlayton closed 5 years ago

awlayton commented 5 years ago

Are you requesting a feature, reporting a bug or asking a question?

reporting a bug

What is the current behavior?

When the value for the element of a dropdown is not an object, the results for it end up being "[object Object]" instead of the actual specified value.

What is the expected behavior?

I expect the object to be in the results as they are for the Survey Builder, that is an object with the same keys and values as the one specified under value.

How would you reproduce the current behavior (if this is a bug)?

Choose one of the choices for the dropdown in the sample below, then check the console for the survey results.

Provide the test code and the tested page URL (if applicable)

Use surveyjs_react_quickstart and replace App.js with the following:

import React, {Component} from 'react'

import * as Survey from "survey-react";
import "survey-react/survey.css";

class App extends Component {
 json = {
    pages: [
        {
          name: 'uav-sensors',
          title: 'Sensors',
          elements: [
            {
              name: 'sensors',
              title: 'Sensors',
              type: 'panel',
              elements: [
                    {
                        name: 'uav-sensor',
                        title: 'Sensor',
                        type: 'dropdown',
                        hideIfChoicesEmpty: true,
                        choices: [
                            {
                                text: 'Sony A6000',
                                value: {
                                    make: 'Sony',
                                    model: 'A6000',
                                    type: 'RGB',
                                },
                            },
                            {
                                text: 'Parrot Sequoia',
                                value: {
                                    make: 'Parrot',
                                    model: 'Sequoia',
                                    type: 'Multispectral',
                                },
                            },
                        ],
                    },
              ],
            },
          ],
        },
    ]
 };
 render() {
  var model = new Survey.Model(this.json);
  return (<Survey.Survey model={model} onComplete={this.onComplete}/>);
 }

    onComplete({data}){
        console.dir(data);
    }  
}

export default App;

Specify your

tsv2013 commented 5 years ago

Hello @awlayton , the choice item value is assigned to the value attribute of the option HTML tag and is treaten as a string according to the HTML option tag specification (https://www.w3schools.com/tags/tag_option.asp)

The value property of a choice item wasn't designed to be assigned an object to it.

awlayton commented 5 years ago

So it's a bug that it works with objects in the Survey Builder?

I wanted to do this because I have a dropdown where some of the choices should fill out a couple text questions automatically.

tsv2013 commented 5 years ago

As far as I know survey builder can't work with the value as object. Instead of the

{
                                text: 'Parrot Sequoia',
                                value: {
                                    make: 'Parrot',
                                    model: 'Sequoia',
                                    type: 'Multispectral',
                                },
                            }

it can work with the

{
                                text: 'Parrot Sequoia',
                                value: "valueOfValue",
                                make: 'Parrot',
                                model: 'Sequoia',
                                type: 'Multispectral',
                            }

objects

awlayton commented 5 years ago

If I give Survey Builder this JSON:

{
 title: "Software developer survey.",
 pages: [
  {
   name: "page1",
   elements: [
    {
     type: "dropdown",
     name: "question1",
     hasOther: true,
     choices: [
      {
       value: {
        a: "b"
       },
       text: "item1"
      },
      "item2",
      "item3"
     ],
     hideIfChoicesEmpty: true
    }
   ],
   title: "Please enter your name and e-mail"
  }
 ]
}

then choosing item1 in the dropdown when I test it gives these results:

{
    "question1": {
        "a": "b"
    }
}

If I use the way you suggest, how do I access the fields of the item besides its value in expressions?

tsv2013 commented 5 years ago

@awlayton IMO this doesn't supposed to work :-) The scenario with objects as values is not supported in the SurevyJS Library. And yes, you are right - you can access values only in expressions. So I can treat this as a new feature, but not as a bug. @andrewtelnov please take a look

awlayton commented 5 years ago

Sorry if I wasn't clear. I wasn't stating a fact I was asking a question. How am I supposed to access those values in expressions? I do not see it documented, but maybe I am just missing it.

andrewtelnov commented 5 years ago

@awlayton Could you please describe us a complete scenario? I believe we will be able to provide a better solution. You may use a custom function in your expression. Here is an example. You may have a separate list of your objects {make, model, type} or you may add a custom property into ItemValue { text: 'Parrot Sequoia', value: "Parrot", model: 'Sequoia', type: 'Multispectral' } In your custom function, you may access your list or find the itemvalue by its value and return the needed property/attribute value.

Thank you, Andrew

awlayton commented 5 years ago

I have a dropdown that is optional, but when something from that dropdown is chosen it should fill out two other text questions. Below is what I was currently trying to achieve this.

{
    name: 'uav-sensor',
    valueName: 'sensor',
    title: 'Sensor',
    type: 'dropdown',
    hideIfChoicesEmpty: true,
    choicesVisibleIf: '{panel.type} == {item.type}',
    choices: [
        {
            text: 'Sony A6000',
            value: {
                make: 'Sony',
                model: 'A6000',
                type: 'RGB',
            },
        },
        {
            text: 'Parrot Sequoia',
            value: {
                make: 'Parrot',
                model: 'Sequoia',
                type: 'Multispectral',
            },
        },
    ],
},
{
    name: 'uav-sensor-make',
    valueName: 'sensor.make',
    title: 'Make',
    type: 'text',
},
{
    name: 'uav-sensor-model',
    valueName: 'model',
    title: 'Model',
    type: 'text',
},
andrewtelnov commented 5 years ago

@awlayton Do you want a generic solution that will work with our SurveyJS Builder or do you need a quick solution in run-time only? If you need a question solution, then you may use onValueChanged or onDynamicPanelItemValueChanged (in case you are using the dynamic panel) and set values manually.

Thank you, Andrew

awlayton commented 5 years ago

That will work for now, though a generic solution would be preferable. I will likely have other questions needing this sort of relation and it would be nice to have the logic in the specification of the questions.

However, I realize this is FOSS and I appreciate you taking your time to help me find any solution.