Blockly:根据对 inputDummy 下拉字段的选择更新其他 inputDummy 下拉字段
Blockly: Update other inputDummy dropdown fields based on selection of a inputDummy dropdown field
我一直在尝试在 Blockly 工作区中创建一个自定义块,该块会根据同一块中先前下拉字段的选择来更改下拉字段中的选项。
关于区块:-
- 有三个下拉字段
- 全部使用 Blockly.Extensions
动态填充
- 所有代码都在下面
我已经为块初始化实现了一个 '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"
},
{
"type": "input_dummy",
"name": "column_input1",
},
{
"type": "input_value",
"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'], cId]))
return options
}
), '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
}
}
}
这是生成的块的快照:
tldr;
当另一个下拉列表的选定选项发生更改时,更新块中下拉字段的选项。
谢谢,
乌特卡什
感谢来自 Google Blockly groups at https://groups.google.com/g/blockly/c/Vh_zPLrqjdw/m/TWHehaQ1AgAJ 的 @beka。
这里的主要问题是概念上的。一个区块有
- 输入:可以包含值块(拼图输入)或语句块(乐高输入)之类的字段行
- 字段:类似于 HTML。这些可以是文本框、下拉菜单、图像等。
输入和字段都可以有名称。最好以不同的方式命名它们。
正如在我的扩展中看到的那样,我接受了我的输入 this.getInput('columnInput')
并附加了一个具有相同名称的字段 .appendField
。因此,输入有一个同名的字段。
更正如下:
- 扩展:
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
})
- 更新块初始化 onchange 中所有下拉列表的函数
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'], cId]))
return options
}
), 'column_input_field') // updated the field name different from input name
当然,如果您在 this.getInput('').removeField('')
期间遇到任何问题,请记录输入对象 console.log(this.getInput(''))
并进行评估。
我一直在尝试在 Blockly 工作区中创建一个自定义块,该块会根据同一块中先前下拉字段的选择来更改下拉字段中的选项。 关于区块:-
- 有三个下拉字段
- 全部使用 Blockly.Extensions 动态填充
- 所有代码都在下面
我已经为块初始化实现了一个 '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"
},
{
"type": "input_dummy",
"name": "column_input1",
},
{
"type": "input_value",
"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'], cId]))
return options
}
), '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
}
}
}
这是生成的块的快照:
tldr; 当另一个下拉列表的选定选项发生更改时,更新块中下拉字段的选项。
谢谢, 乌特卡什
感谢来自 Google Blockly groups at https://groups.google.com/g/blockly/c/Vh_zPLrqjdw/m/TWHehaQ1AgAJ 的 @beka。
这里的主要问题是概念上的。一个区块有
- 输入:可以包含值块(拼图输入)或语句块(乐高输入)之类的字段行
- 字段:类似于 HTML。这些可以是文本框、下拉菜单、图像等。
输入和字段都可以有名称。最好以不同的方式命名它们。
正如在我的扩展中看到的那样,我接受了我的输入 this.getInput('columnInput')
并附加了一个具有相同名称的字段 .appendField
。因此,输入有一个同名的字段。
更正如下:
- 扩展:
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 })
- 更新块初始化 onchange 中所有下拉列表的函数
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'], cId])) return options } ), 'column_input_field') // updated the field name different from input name
当然,如果您在 this.getInput('').removeField('')
期间遇到任何问题,请记录输入对象 console.log(this.getInput(''))
并进行评估。