Changing Value Setters on runtime

Changing value setters during runtime is nothing new, we have already covered it in the dynamically changing value setters on result and made a calculator to illustrate the principle: [docs] Value Setter (Dynamic).

Note

We will present examples with each method. These examples are not the only possible use-cases. Feel free to modify and play with them to get the behaviour you want.

What we have here are a three different ways use this principle to achieve more useful behaviours. We will start with the more niche use case and then move on those that improve the user experience of things we already know how to do.

Clear field for custom option

This section is an improvement over the option to have a value setter as well as a custom option to get the most flexibility without loosing ease of use. In the previous version you simply show/hide the variable field depending on whether the user had selected the “Custom” option on the value select or not.

But that also displayed the previously set value of the variable, which can be confusing in some situations. Instead you could simply clear the value of the variable before showing it to the user, so that you can present an empty variable field that the user immediately knows to fill.

To achieve this, you just need to do a small switcheroo thingy, the customJS equivalent of a sleigh of hand.

Here is the how to do it:

 1omni.onResult([], function (ctx) {
 2  ctx.hideVariables('sides');
 3
 4  if (ctx.getNumberValue('polygon') == 3) { //Triangle
 5    omni.createValueSetter('polygon', undefValue);
 6  } else {
 7    ctx.showVariables('sides');
 8    omni.createValueSetter ('polygon', emptyValue);
 9  }
10  ctx.addHtml('Number of Sides: ' + ctx.getNumberValue('sides'));
11});
12
13var undefValue = [{name:"Triangle", uid:"3", values:{"sides":3}},
14                  {name:"N sides", uid:"0", values:{"sides": undefined}},
15                 ];
16var emptyValue = [{name:"Triangle", uid:"3", values:{"sides":3}},
17                  {name:"N sides", uid:"0", values:{}},
18                 ];
19
20omni.createValueSetter('polygon', undefValue);

By having two different value setters we can make the user selection clear the variable field upon selection. To avoid having Custom displayed when the user fills in the data, we can use a value setter without any value assigned to that variable. Switching between them an be done easily inside of onResult. If needed, the value setter could even be dynamically created inside of onResult as well; handy for situations with plenty of options or value setters.

See also

We have created a calculator where you can see and interact with the whole code. Check it out at Value Setter (Empty Custom) on BB.

Nesting with default values

Now we are going to see how we can extend this trick to nested value setters. When nesting value setters we have one of them controlling which of the second options will be shown. This first value setter (we will call it Level 0) triggers which options will be shown to the user. The available options will be called Level 1 value setters.

Note

Big thanks to Wojtek, Jasmine, and Steve for requesting and using this feature.

Unfortunately, changing which value setter you show the user (using createValueSetter) does not change the value of any variable, just the text shown. To work around this we will have to specify in Level 0 which values should be set by default on the variables affected by the Level 1 value setter.

This option is not limited to two total levels, you can keep nesting forever. Just keep in mind that the more levels and options available, the more complex it will be to create all the code.

 1omni.onResult([], function (ctx) {
 2  var category = ctx.getNumberValue('category') || 0;
 3  omni.createValueSetter('category', categoryEmptyArrayVS[category]);
 4  omni.createValueSetter('option', categoryArrayVS[category]);
 5});
 6
 7//Level 0 VS
 8//Set all default values here, even if it's normally controlled by the nested VS
 9var Type_Color_empty_VS = [{name:'Color', uid:'0', values: {}},
10                          {name:'Shape', uid:'1', values: {'option':0,'value':3}},
11                          {name:'Size', uid:'2', values: {'option':0,'value':0}}
12                          ];
13
14var Type_Shape_empty_VS = [{name:'Color', uid:'0', values: {'option':0,'value':650}},
15                          {name:'Shape', uid:'1', values: {}},
16                          {name:'Size', uid:'2', values: {'option':0,'value':0}}
17                          ];
18
19var Type_Size_empty_VS = [{name:'Color', uid:'0', values: {'option':0,'value':650}},
20                          {name:'Shape', uid:'1', values: {'option':0,'value':3}},
21                          {name:'Size', uid:'2', values: {}}
22                        ];
23
24categoryEmptyArrayVS = [Type_Color_empty_VS, Type_Shape_empty_VS, Type_Size_empty_VS];
25
26//Level 1 VS
27var Color_VS = [{name:'Red', uid:'0', values: {'value':650}},
28                {name:'Orange', uid:'1', values: {'value':600}},
29                {name:'Yellow', uid:'2', values: {'value':570}}
30              ];
31
32var Shape_VS = [{name:'Triangle', uid:'0', values: {'value':3}},
33                {name:'Square', uid:'1', values: {'value':4}}
34              ];
35
36var Size_VS = [{name:'X small', uid:'0', values: {'value':0}},
37              {name:'Small', uid:'1', values: {'value':1}},
38              {name:'Medium', uid:'2', values: {'value':2}},
39              {name:'Large', uid: '3', values: {'value':3}},
40              {name: 'XLarge', uid: '4', values: {'value':4}}
41              ];
42
43categoryArrayVS = [Color_VS, Shape_VS, Size_VS];

As you can see, we need one value setter variable for each option in the Level 0 value setter. This can get pretty big pretty fast 1. If you are planning to use this trick using value setters with a big number of options, it would be useful to create the value setter variables automatically every time onResult is triggered.

See also

Thanks to Jasmine, you can see the code in action and play with it. Check it out at Value Setter (Nested with Default Values) on BB.

Footnotes

1

Guess who said what ;)