8000 Dynamic dropdowns are not responding to programmatic setValue calls correctly · Issue #3099 · google/blockly · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
Dynamic dropdowns are not responding to programmatic setValue calls correctly #3099
Open
@BeksOmega

Description

@BeksOmega

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:

  1. 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']
        ];
    }
  }
};
  1. Load the following xml:
<xml xmlns="https://developers.google.com/blockly/xml">
  <block type="test_block"/>
</xml>
  1. Change the first dropdown's value.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0