Open
Description
Describe the bug
If you try to set a dynamic dropdown's value programmatically it won't regenerate its options, causing it to sometimes throw the 'Cannot set the dropdown's value to an unavailable option.' warning when it should not.
To Reproduce
Steps to reproduce the behavior:
- Add the following block to the playground:
Blockly.Blocks['test_block'] = {
init: function() {
this.appendDummyInput()
.appendField(new Blockly.FieldDropdown([
['a', 'A'],
['b', 'B'],
['c', 'C'],
// This is your validator.
], this.firstDropdownListener), 'FIRST')
// This is your dynamic option generator.
.appendField(new Blockly.FieldDropdown(this.generateOptions), 'SECOND');
},
firstValue: 'A',
firstDropdownListener: function(newValue) {
var sourceBlock = this.getSourceBlock();
// We have to cache the value to the block because setFieldValue() calls
// generateOptions(), and generateOptions() wouldn't be able to retrieve
// the newValue using getFieldValue() at this point (because the new
// value hasn't been applied yet).
sourceBlock.firstValue = newValue;
sourceBlock.setFieldValue(sourceBlock.getOptions(newValue)[0][1], 'SECOND');
},
generateOptions: function() {
var sourceBlock = this.getSourceBlock();
// The menu generation function is called in the constructor, at which
// point the source block has not yet been applied, so we have to handle
// that case.
if (sourceBlock) {
return sourceBlock.getOptions(sourceBlock.firstValue);
} else {
return [
['alligator', 'ALLIGATOR'],
['apple', 'APPLE'],
['airplane', 'AIRPLANE']
];
}
},
getOptions: function(firstValue) {
switch (firstValue) {
case 'A':
return [
['alligator', 'ALLIGATOR'],
['apple', 'APPLE'],
['airplane', 'AIRPLANE']
];
case 'B':
return [
['ball', 'BALL'],
['basket', 'BASKET'],
['bottle', 'BOTTLE']
];
case 'C':
return [
['coffee', 'COFFEE'],
['captain', 'CAPTAIN'],
['carrot', 'CARROT']
];
}
}
};
- Load the following xml:
<xml xmlns="https://developers.google.com/blockly/xml">
<block type="test_block"/>
</xml>
- Change the first dropdown's value.
- Observe the warning in console.
Expected behavior
The second dropdown should update in response to the first dropdown.
Menu options should be regenerated when calling setValue programmatically.
Stack Traces
field_dropdown.js:474 Cannot set the dropdown's value to an unavailable option. Block type: test_block, Field name: SECOND, Value: BALL
Additional context
This is a regression caused by #3036
The above example block should probably be added as a test block.