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.21k stars 815 forks source link

Unexpected results when using runexpression trigger values in another trigger #2427

Closed kc-nxtbig closed 1 year ago

kc-nxtbig commented 4 years ago

Hi,

I was looking to use the result of two runExpression triggers to in another runExpression trigger. The result of the first two is not setToName of another question in the survey but to be retained (as it is not to be shown to the user) and to be used for computing in other expression type questions. One can imagine it to be breaking down bigger computations to small manageable ones and showing only the final result to the user.

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

Question

What is the current behavior?

The result of triggers set to temporary names using setToName when used by other triggers gives unexpected results.

What is the expected behaviour?

The result of runExpression or other triggers to be available for use by other triggers by referring to the setToName of the previously used triggers.

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

Sample code attached

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

Tested page URL:

Test code

your_code_here

`{
 "pages": [
  {
   "name": "page1",
   "elements": [
    {
     "type": "text",
     "name": "ip1"
    },
    {
     "type": "text",
     "name": "ip2"
    },
    {
     "type": "text",
     "name": "ip3"
    },
    {
     "type": "text",
     "name": "ip4"
    },
    {
     "type": "expression",
     "name": "expr1",
     "expression": "{trigger3}"
    }
   ]
  }
 ],
 "triggers": [
  {
   "type": "runexpression",
   "expression": "{ip1} notempty or {ip1} empty or {ip2} notempty or {ip2} empty ",
   "setToName": "trigger1",
   "runExpression": "{ip1} + {ip2}"
  },
  {
   "type": "runexpression",
   "expression": "{ip3} notempty or {ip3} empty or {ip4} notempty or {ip4} empty",
   "setToName": "trigger2",
   "runExpression": "{ip3} + {ip4}"
  },
  {
   "type": "runexpression",
   "expression": "{ip1} notempty or {ip2} notempty or {ip3} notempty or {ip4} notempty or {ip1} empty or {ip2} empty or {ip3} empty or {ip4} empty",
   "setToName": "trigger3",
   "runExpression": "{trigger1} + {trigger2}"
  }
 ]
}`

Specify your

andrewtelnov commented 4 years ago

@kc-nxtbig You need to use calcualtedValues, here is your example.

    calculatedValues: [
        {
            name: 'trigger1',
            expression: '{ip1} + {ip2}',
        },
        {
            name: 'trigger2',
            expression: '{ip3} + {ip4}',
        },
        {
            name: 'trigger3',
            expression: '{trigger1} + {trigger2}',
        },
    ]

Thank you, Andrew

kc-nxtbig commented 4 years ago

Thank you, Andrew.

I did read about calcualtedValues in your docs and wasn't too sure if they work like runExpression triigers triggering a computation on any changes to input visibility/ values. Apparently, they do. Please correct me if I am wrong in my assumption.

On the other hand, there is a related issue - triggers or calculatedValues being used along with visbileIf and defaultValues.

Take the following example:

  1. ip1, ip2,ip3,ip4 have defaultValues 1,2,3,4. Their visibleIf is decided by the user using qVisibilityToggle question.
  2. One would expect those values to be available for computation only once the questions become visible (based on user choice).
  3. The calculatedValues - on the otherhand gives a result 10 - intially even when none of the questions have been selected by the user. This is unexpected.
  4. If the user selects and then unselects a question - the question value is now taken out from computation. This is expected.
  5. If the user again selects (select, followed by deselecting, followed by select again) => the defaultValue is no longer available. This is unexpected. One would expect the defaultValue to be available anytime the question is visible.

I am sure the surveyJS team would have taken a considered call on this behaviour. Is this intended? If yes, any workarounds ?? Thanks

A sample JSON highlighting the behaviour I described above:

{ "pages": [ { "name": "page1", "elements": [ { "type": "checkbox", "name": "qVisibilityToggle", "choices": [ "ip1", "ip2", "ip3", "ip4" ] }, { "type": "text", "name": "ip1", "visible": false, "visibleIf": "{qVisibilityToggle} contains 'ip1'", "defaultValue": "1" }, { "type": "text", "name": "ip2", "visible": false, "visibleIf": "{qVisibilityToggle} contains 'ip2'", "defaultValue": "2" }, { "type": "text", "name": "ip3", "visible": false, "visibleIf": "{qVisibilityToggle} contains 'ip3'", "defaultValue": "3" }, { "type": "text", "name": "ip4", "visible": false, "visibleIf": "{qVisibilityToggle} contains 'ip4'", "defaultValue": "4" }, { "type": "expression", "name": "calcValues result", "visible": false, "visibleIf": "{qVisibilityToggle} anyof ['ip1', 'ip2', 'ip3', 'ip4']", "expression": "{calVal3}" } ] } ], "calculatedValues": [ { "name": "calVal1", "expression": "{ip1} + {ip2}" }, { "name": "calVal2", "expression": "{ip3} + {ip4}" }, { "name": "calVal3", "expression": "{calVal1} + {calVal2}" } ], "sendResultOnPageNext": true, "clearInvisibleValues": "onHidden" }

andrewtelnov commented 4 years ago

@kc-nxtbig I have fixed the issue here. You can look at commit and unit tests.

Thank you, Andrew

kc-nxtbig commented 4 years ago

Thank you, Andrew. That helps.

So, I have a question.

Both triggers and calculatedValues appear to be doing similar jobs apart from the ability to use a trigger output to a question using setToName. On the other hand, I noted that you can use the result of a calculatedValues as input to another calculatedValues - which possibly is not the case with triggers.

What is the recommended use for each?

Thank you, kc

andrewtelnov commented 4 years ago

@kc-nxtbig I would go with calculatedValues. They are similar to expression question, but they do not have UI elements.

Thank you, Andrew

kc-nxtbig commented 4 years ago

Thank you very much, Andrew.

Much appreciated.