如何在 Blockly 中 hide/remove 字段?
How to hide/remove field in Blockly?
如何根据下拉值的变化隐藏字段。
我添加了一个名为 'A' 的输入字段。我有一个下拉字段。如果我 select 下拉列表中的一个值,比如说 'Remove field A',那么应该删除输入字段。
我试过了removeField。但它没有用。还有其他方法吗?或者如何正确使用 remove-field?
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField('Type ')
.appendField(new Blockly.FieldDropdown(typeOptions), 'columnType');
// if columnType = Card, show the following:
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField(' Card: ')
.appendField(new Blockly.FieldDropdown(cardsList), 'cardValue');
// if columnType = view, show the following:
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField(' View ')
.appendField(new Blockly.FieldDropdown(viewsList), 'viewValue');
好的,所以这没有您的完整代码,但我想我在这里看到了您的问题。
简短的回答是,在您提供的代码中,我没有看到您在块中选择新值时在回调函数中执行任何操作,也没有看到您保存它 from/reading来自 XML。可能其中一些被遗漏了,但为了不让你在评论中播放 "include more code" 标签,我将在这里做一个简要说明。
让我向您展示一些示例代码,并介绍我为使这个案例成功所做的一切:
Blockly.Blocks['mySampleBlock'] = {
/**
* Initiate the block. This runs before domToMutation.
*/
init: function () {
var typeOptions = [['Card', 'card'], ['View', 'view']];
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField('Type ')
.appendField(new Blockly.FieldDropdown(typeOptions, this.handleTypeSelection.bind(this)), 'typeSelector');
// Initialize the value of this.columnType (used in updateShape)
this.columnType = this.getFieldValue('typeSelector');
// Avoid duplicating code by running updateShape to append your appropriate input
this.updateShape();
//@TODO: Do other block configuration stuff like colors, additional inputs, etc. here
},
/**
* This function runs each time you select a new value in your type selection dropdown field.
* @param {string} newType This is the new value that the field will be set to.
*
* Important note: this function will run BEFORE the field's value is updated. This means that if you call
* this.getFieldValue('typeSelector') within here, it will reflect the OLD value.
*
*/
handleTypeSelection: function (newType) {
// Avoid unnecessary updates if someone clicks the same field twice
if(this.columnType !== newType) {
// Update this.columnType to the new value
this.columnType = newType;
// Add or remove fields as appropriate
this.updateShape();
}
},
/**
* This will remove old inputs and add new inputs as you need, based on the columnType value selected
*/
updateShape: function () {
// Remove the old input (so that you don't have inputs stack repeatedly)
if (this.getInput('appendToMe')) {
this.removeInput('appendToMe');
}
// Append the new input based on the value of this.columnType
if(this.columnType === 'card') {
// if columnType = Card, show the following:
//@TODO: define values in cardsList here
var cardsList = [['Dummy Option','option']];
this.appendDummyInput('appendToMe')
.setAlign(Blockly.ALIGN_RIGHT)
.appendField(' Card: ')
.appendField(new Blockly.FieldDropdown(cardsList), 'cardValue');
} else if (this.columnType === 'view') {
// if columnType = view, show the following:
//@TODO: define values in viewsList here
var viewsList = [['Dummy Option','option']];
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField(' View ')
.appendField(new Blockly.FieldDropdown(viewsList), 'viewValue');
}
},
/**
* This function runs when saving your block to XML. This is important if you need to save your block to XML at any point and then either
* generate code from that XML or repopulate your workspace from that XML
*/
mutationToDom: function () {
var container = document.createElement('mutation');
// Do not use camelCase values for attribute names.
container.setAttribute('column_type', this.columnType);
// ALWAYS return container; this will be the input for domToMutation.
return container;
},
/**
* This function runs when loading your block from XML, after running init.
* It's very important for updating your block in response to values selected in a field.
*/
domToMutation: function (xmlElement) {
// This attribute should match the one you used in mutationToDom
var columnType = xmlElement.getAttribute('column_type');
// If, for whatever reason, you try to save an undefined value in column_type, it will actually be saved as the string 'undefined'
// If this is not an acceptable value, filter it out
if(columnType && columnType !== 'undefined') {
this.columnType = columnType;
}
// Run updateShape to append block values as needed
this.updateShape();
}
};
关于这种情况,除了我的解释性评论外,还有几点需要注意:
- 您不必严格使用我的
this.columnType
结构。相反,您可以将 columnType
值传递给 updateShape
并使用 this.getFieldValue('typeSelector')
或 'callback' 函数的输入 (handleTypeSelection
)。我倾向于更喜欢这个,因为我经常制作更复杂的块,每次都很难或低效地获得适当的值,而 this.whateverMyValueNameIs
更容易。
- 同样,您可以使用
removeField
和 appendField
,而不是 updateShape
中的 this.removeInput
和 this.appendDummyInput
,这是您的第一直觉。但是,如果您这样做,您将需要确保您已经命名了您打算附加字段的输入to/remove。在大多数情况下,我倾向于只 adding/removing 整个输入,因为它还可以让我更改标签等。
- 任何时候你对下拉列表的值做出任何更改,你应该添加
domToMutation
和 mutationToDom
以将该值保存到 mutation 属性,然后读取它out 并相应地更新你的块。即使您的块上没有实际的突变器,这也适用。
- 注意这里的TODO注释;由于我不知道viewsList和cardsList的值,所以我没有提供它们,也没有为您提供任何其他块配置。
这可能有点令人困惑,所以如果您有任何后续问题,请提出。我花了一段时间才掌握它,我自己。 (不过,如果我不清楚您要做什么,我可能会要求您提供额外的代码示例。)
祝你好运!
如何根据下拉值的变化隐藏字段。
我添加了一个名为 'A' 的输入字段。我有一个下拉字段。如果我 select 下拉列表中的一个值,比如说 'Remove field A',那么应该删除输入字段。
我试过了removeField。但它没有用。还有其他方法吗?或者如何正确使用 remove-field?
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField('Type ')
.appendField(new Blockly.FieldDropdown(typeOptions), 'columnType');
// if columnType = Card, show the following:
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField(' Card: ')
.appendField(new Blockly.FieldDropdown(cardsList), 'cardValue');
// if columnType = view, show the following:
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField(' View ')
.appendField(new Blockly.FieldDropdown(viewsList), 'viewValue');
好的,所以这没有您的完整代码,但我想我在这里看到了您的问题。
简短的回答是,在您提供的代码中,我没有看到您在块中选择新值时在回调函数中执行任何操作,也没有看到您保存它 from/reading来自 XML。可能其中一些被遗漏了,但为了不让你在评论中播放 "include more code" 标签,我将在这里做一个简要说明。
让我向您展示一些示例代码,并介绍我为使这个案例成功所做的一切:
Blockly.Blocks['mySampleBlock'] = {
/**
* Initiate the block. This runs before domToMutation.
*/
init: function () {
var typeOptions = [['Card', 'card'], ['View', 'view']];
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField('Type ')
.appendField(new Blockly.FieldDropdown(typeOptions, this.handleTypeSelection.bind(this)), 'typeSelector');
// Initialize the value of this.columnType (used in updateShape)
this.columnType = this.getFieldValue('typeSelector');
// Avoid duplicating code by running updateShape to append your appropriate input
this.updateShape();
//@TODO: Do other block configuration stuff like colors, additional inputs, etc. here
},
/**
* This function runs each time you select a new value in your type selection dropdown field.
* @param {string} newType This is the new value that the field will be set to.
*
* Important note: this function will run BEFORE the field's value is updated. This means that if you call
* this.getFieldValue('typeSelector') within here, it will reflect the OLD value.
*
*/
handleTypeSelection: function (newType) {
// Avoid unnecessary updates if someone clicks the same field twice
if(this.columnType !== newType) {
// Update this.columnType to the new value
this.columnType = newType;
// Add or remove fields as appropriate
this.updateShape();
}
},
/**
* This will remove old inputs and add new inputs as you need, based on the columnType value selected
*/
updateShape: function () {
// Remove the old input (so that you don't have inputs stack repeatedly)
if (this.getInput('appendToMe')) {
this.removeInput('appendToMe');
}
// Append the new input based on the value of this.columnType
if(this.columnType === 'card') {
// if columnType = Card, show the following:
//@TODO: define values in cardsList here
var cardsList = [['Dummy Option','option']];
this.appendDummyInput('appendToMe')
.setAlign(Blockly.ALIGN_RIGHT)
.appendField(' Card: ')
.appendField(new Blockly.FieldDropdown(cardsList), 'cardValue');
} else if (this.columnType === 'view') {
// if columnType = view, show the following:
//@TODO: define values in viewsList here
var viewsList = [['Dummy Option','option']];
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField(' View ')
.appendField(new Blockly.FieldDropdown(viewsList), 'viewValue');
}
},
/**
* This function runs when saving your block to XML. This is important if you need to save your block to XML at any point and then either
* generate code from that XML or repopulate your workspace from that XML
*/
mutationToDom: function () {
var container = document.createElement('mutation');
// Do not use camelCase values for attribute names.
container.setAttribute('column_type', this.columnType);
// ALWAYS return container; this will be the input for domToMutation.
return container;
},
/**
* This function runs when loading your block from XML, after running init.
* It's very important for updating your block in response to values selected in a field.
*/
domToMutation: function (xmlElement) {
// This attribute should match the one you used in mutationToDom
var columnType = xmlElement.getAttribute('column_type');
// If, for whatever reason, you try to save an undefined value in column_type, it will actually be saved as the string 'undefined'
// If this is not an acceptable value, filter it out
if(columnType && columnType !== 'undefined') {
this.columnType = columnType;
}
// Run updateShape to append block values as needed
this.updateShape();
}
};
关于这种情况,除了我的解释性评论外,还有几点需要注意:
- 您不必严格使用我的
this.columnType
结构。相反,您可以将columnType
值传递给updateShape
并使用this.getFieldValue('typeSelector')
或 'callback' 函数的输入 (handleTypeSelection
)。我倾向于更喜欢这个,因为我经常制作更复杂的块,每次都很难或低效地获得适当的值,而this.whateverMyValueNameIs
更容易。 - 同样,您可以使用
removeField
和appendField
,而不是updateShape
中的this.removeInput
和this.appendDummyInput
,这是您的第一直觉。但是,如果您这样做,您将需要确保您已经命名了您打算附加字段的输入to/remove。在大多数情况下,我倾向于只 adding/removing 整个输入,因为它还可以让我更改标签等。 - 任何时候你对下拉列表的值做出任何更改,你应该添加
domToMutation
和mutationToDom
以将该值保存到 mutation 属性,然后读取它out 并相应地更新你的块。即使您的块上没有实际的突变器,这也适用。 - 注意这里的TODO注释;由于我不知道viewsList和cardsList的值,所以我没有提供它们,也没有为您提供任何其他块配置。
这可能有点令人困惑,所以如果您有任何后续问题,请提出。我花了一段时间才掌握它,我自己。 (不过,如果我不清楚您要做什么,我可能会要求您提供额外的代码示例。)
祝你好运!