Blockly:根据 inputDummy 下拉字段的选择更新其他 inputDummy 下拉字段

问题描述

我一直在尝试在 Blockly 工作区中创建一个自定义块,该块根据同一块中上一个下拉字段的选择来更改下拉字段中的选项。 关于区块:-

  1. 共有三个下拉字段
  2. 全部使用 Blockly.Extensions 动态填充
  3. 所有代码都在下面

我已经为块初始化实现了一个 'onchange' 函数,它通过 'event' 变量获取更改数据并做出相应的响应。我在尝试更新不断变化的下拉字段时遇到问题。请协助。

代码

// the block JSON declaration variable
var updateTableData = {
    "type": "al_update_table_data","message0": "Update in table %1 where column %2 is %3 set value for column %4 to %5","args0": [
        {
            "type": "input_dummy","name": "table_input",},{
            "type": "input_dummy","name": "column_input",{
            "type": "input_value","name": "get_value"
        },"name": "column_input1","name": "set_value"
        }
    ],"inputsInline": false,"prevIoUsstatement": null,"nextStatement": null,"fieldRow": false,"colour": 90,"tooltip": "Update value in a table","helpUrl": "","extensions": ["get_tables","get_column","get_column1"],}
// the blockly extensions
// get list of tables and populate the 'table_input' drop-down field
Blockly.Extensions.register('get_tables',function () {
    this.getInput("table_input")
        .appendField(new Blockly.FieldDropdown(
            function () {
                let options = []
                let tables = JSON.parse(localStorage.getItem('applab_myTables'))
                tables.map(t => options.push([t.name,t.id]))
                return options
            }
        ),"table_input")
})

// get list of columns from the first table and populate the 'column_input' drop-down field
Blockly.Extensions.register('get_column',function () {
    this.getInput('column_input')
        .appendField(new Blockly.FieldDropdown(
            function () {
                let options = []
                let table = JSON.parse(localStorage.getItem('applab_myTables'))[0]
                Object.keys(table['columnData']).filter(cId => table['columnorder'].includes(cId)).map(cId => options.push([table['columnData'][cId]['name'],cId]))
                return options
            }
        ),'column_input')
})

// get list of columns from the first table,remove the column value already selected in 'column_input' and populate the 'column_input1' drop-down field
Blockly.Extensions.register('get_column1',function () {
    var selectedColumn = this.getFieldValue('column_input')
    this.getInput('column_input1')
        .appendField(new Blockly.FieldDropdown(
            function () {
                let options = []
                let table = JSON.parse(localStorage.getItem('applab_myTables'))[0]
                Object.keys(table['columnData']).filter(cId => table['columnorder'].includes(cId)).filter(cId => cId !== selectedColumn).map(cId => options.push([table['columnData'][cId]['name'],'column_input1')
})
// Comments with 7 slashes (///////) are my commentary on the issues,errors and outputs that I get
// blockly block initialization
Blockly.Blocks['al_update_table_data'] = {
    init: function () {
        this.jsonInit(updateTableData)
    },onchange: function (event) {
        // console.log(event.type)
        var table_id = this.getFieldValue('table_input')
        var selectedcolumn = this.getFieldValue('column_input')
        var otherColumn = this.getFieldValue('column_input1')
        if (event.blockId === this.id) {
            if (event.type === Blockly.Events.BLOCK_CHANGE) {
                // console.log('name of changed field',event.name)
                // console.log('old value',event.oldValue)
                // console.log('new value',event.newValue)
                if (event.name === 'table_input') { 
                    // change in selected table,update column_input and column_input1
                } else if (event.name === 'column_input') {
                    // change in selected column,update column_input1
                    /////// I tried to removeField which did remove the field,but also the label on the same field row. But when I tried to getInput,I get the error: 'column_input1' input doesn't exist
                    // this.removeField('column_input1',true)
                    /////// I tried to removeInput as well,which too removed the field,but also the label on the same field row. And when I tried to getInput,I again get the error: 'column_input1' input doesn't exist
                    // this.removeInput('column_input1')
                    /////// This functions runs fine when I don't remove any input or field. But it keeps adding new drop-downs next to existing ones with new options
                    this.getInput('column_input1')
                        /////// I tried this to use removeField after getInput as well. But it shows the error: this.getinput().removeField() is not a function
                        // .removeField('column_input1')
                        .appendField(new Blockly.FieldDropdown(
                            function () {
                                let options = []
                                let table = JSON.parse(localStorage.getItem('applab_myTables')).find(table => table.id === table_id)
                                Object.keys(table['columnData']).filter(cId => table['columnorder'].includes(cId)).filter(cId => cId !== event.newValue).map(cId => options.push([table['columnData'][cId]['name'],cId]))
                                return options
                            }
                        ),'column_input1')
                }
            }
        }
        if (event.type === Blockly.Events.FINISHED_LOADING) {
            // workspace finished loading,update column_input and column_input1 based on selected table
        }
    }
}

这是生成的块的快照:

enter image description here

tldr; 当另一个下拉列表的选定选项发生更改时,更新块中下拉字段的选项。

谢谢, 乌特卡什

解决方法

感谢来自 https://groups.google.com/g/blockly 的 Google Blockly 群组的 @beka。

这里的主要问题是概念上的。一个区块有

  1. 输入:字段行,可以有任何值块(拼图输入)或语句块(乐高输入)
  2. 字段:就像来自 HTML。这些可以是文本框、下拉菜单、图片等。

输入和字段都可以有名称。最好以不同的方式命名它们。

正如在我的扩展中看到的那样,我接受了我的输入 1 并附加了一个具有相同名称的字段 this.getInput('columnInput')。因此,输入有一个同名的字段。

以下是更正:

  1. 扩展名:

    Blockly.Extensions.register('get_column',function () {
    this.getInput('column_input')
        .appendField(new Blockly.FieldDropdown(
            function () {
                let options = []
                let table = JSON.parse(localStorage.getItem('applab_myTables'))[0]
                Object.keys(table['columnData']).filter(cId => table['columnOrder'].includes(cId)).map(cId => options.push([table['columnData'][cId]['name'],cId]))
                return options
            }
        ),'column_input_field') // updated the field name different from input name
    })

  1. 更新块初始化中的所有下拉列表的函数

    this.getInput('column_input').removeField('column_input_field') // first removed the field
    // and then,append a new field with the new options
    this.getInput('column_input')
        .appendField(new Blockly.FieldDropdown(
            function () {
                let options = []
                let table = JSON.parse(localStorage.getItem('applab_myTables')).find(table => table.id === event.newValue)
                Object.keys(table['columnData']).filter(cId => table['columnOrder'].includes(cId)).map(cId => options.push([table['columnData'][cId]['name'],'column_input_field') // updated the field name different from input name

当然,如果您个人在 .appendField 期间遇到任何问题,请记录输入对象 this.getInput('').removeField('') 并进行评估。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...