Как скрыть / удалить поле в Blockly?

Как скрыть поле на основе изменения выпадающего значения.

Я добавил поле ввода под названием "A". У меня есть раскрывающееся поле. Если я выберу значение в выпадающем меню, скажем "Удалить поле А", то поле ввода должно быть удалено.

Я попытался удалить поле. Но это не сработало. Любые другие методы? или как правильно использовать 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');

1 ответ

Решение

Хорошо, так что здесь нет вашего полного кода, но я думаю, что вижу вашу проблему здесь.

Короткий ответ заключается в том, что в предоставленном вами коде я не вижу, что вы делаете что-либо в функциях обратного вызова при выборе нового значения в вашем блоке, и при этом я не вижу, чтобы вы сохраняли его из / читая его из XML. Возможно, что-то из этого было пропущено, но в целях недопущения того, чтобы вы играли в комментарии "добавьте больше кода", я просто сделаю краткое изложение здесь.

Позвольте мне показать вам пример кода и пройтись по всему, что я делаю, чтобы заставить это дело работать:

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();
    }
};

Несколько замечаний по поводу этой ситуации, в дополнение к моим пояснительным комментариям:

  1. Вы не должны строго использовать мой this.columnType строительство. Вместо этого вы можете передать columnType значение в updateShape и использовать this.getFieldValue('typeSelector') или ввод вашей функции обратного вызова (handleTypeSelection). Я предпочитаю это делать, потому что я часто делаю гораздо более сложные блоки, где трудно или неэффективно каждый раз получать подходящее значение, и this.whateverMyValueNameIs это легче.
  2. Аналогично вместо this.removeInput а также this.appendDummyInput в updateShape, ты можешь использовать removeField а также appendFieldкак был твой первый инстинкт. Однако, если вы сделаете это, вам нужно будет убедиться, что вы назвали вход, к которому вы хотите добавить свое поле, чтобы удалить его. В большинстве случаев я предпочитаю просто добавлять / удалять весь ввод, поскольку он также позволяет мне менять метки и т. Д.
  3. Каждый раз, когда вы вносите какие-либо изменения в ответ на значение раскрывающегося списка, вам, вероятно, следует добавить domToMutation а также mutationToDom чтобы сохранить это значение в атрибуте мутации, а затем прочитать его и соответствующим образом обновить ваш блок. Это применимо, даже если у вас нет фактического мутатора в вашем блоке.
  4. Обратите внимание на комментарии TODO здесь; поскольку я не знал значений для viewsList и cardsList, я не предоставлял их и не предоставлял никакой другой конфигурации блоков для вас.

Это может немного сбивать с толку, поэтому, если они у вас есть, задайте любые дополнительные вопросы. Мне потребовалось некоторое время, чтобы овладеть этим, я сам. (Я могу запросить дополнительные примеры кода у вас, если мне неясно, что вы пытаетесь сделать.)

Удачи!

Другие вопросы по тегам