Actualiza un campo personalizado

En julio de 2019 (versión 2.20190722), se agregó una API de campos codificados más. El objetivo es que sea lo más retrocompatible posible. Esto significa que, si creaste un campo personalizado antes de julio de 2019, es muy probable que siga funcionando. Antes de decidir si tu campo personalizado debe actualizarse, debes leer la sección Áreas de peligro y realizar una prueba exhaustiva.

Debido a que hubo una falta de estandarización entre los campos antes de julio de 2019, es difícil cubrir todos los cambios que podría tener que hacer un desarrollador. En este documento, se intentan cubrir todos los cambios probables, pero si no se abarca algún tema que te interese, lee la sección sobre cómo obtener asistencia para la actualización.

Áreas de peligro

Las áreas de peligro son lugares conocidos donde la API cambió y tu campo podría dañarse.

Blockly.Field.register

Los campos ya no están registrados a través de Blockly.Field.register();. Ahora hay un espacio de nombres fieldRegistry que controla el registro.

Blockly.Field.register('my_field_name', myFieldClass);

Se convierte en lo siguiente:

Blockly.fieldRegistry.register('my_field_name', myFieldClass);

setText

El núcleo de Blockly ya no llama a la función setText, por lo que, si tu función setText contiene lógica, deberás moverla al paquete de funciones de control de valores, la función getText y las funciones de renderización (según lo que haga exactamente tu función setText).

CustomFields.UpgradeField.prototype.setText = function(newText) {
  // Do validation.
  if (typeof newText != 'string' || newText === this.text_) {
    return;
  }

  // Fire event.
  if (this.sourceBlock_ && Blockly.Events.isEnabled()) {
    Blockly.events.fire(new Blockly.Events.BlockChange(
        this.sourceBlock_, 'field', this.name, this.text_, newText
    ));
  }

  // Update text value.
  this.text_ = 'prefix' + newText;

  // Rerender.
  this.size_.width = 0;
};

Se convierte en lo siguiente:

CustomFields.UpgradeField.prototype.doClassValidation_ = function(newValue) {
  if (typeof newValue != 'string') {
    return null;
  }
  return newValue;
};

CustomFields.UpgradeField.prototype.getText = function() {
  return  'prefix' + this.value_;
}

Blockly controla automáticamente lo siguiente:

  • Verifica si el valor nuevo es diferente del valor anterior.
  • Actualizando el valor.
  • Activando eventos de cambio
  • Vuelve a renderizar el campo.

Deberás manejar lo siguiente:

Las actualizaciones recomendadas son lugares en los que se cambió la API de campo, pero si eliges no realizar cambios, es probable que tu campo siga funcionando.

SERIALIZABLES

Para obtener más información sobre las propiedades EDITABLE y SERIALIZABLE, consulta Propiedades editables y serializables.

CustomFields.UpgradeField.prototype.SERIALIZABLE = true;

La siguiente advertencia se puede pasar por alto, pero puedes resolverla si defines la propiedad SERIALIZABLE:

Detected an editable field that was not serializable. Please define
SERIALIZABLE property as true on all editable custom fields. Proceeding
with serialization.

La advertencia anterior significa que Blockly cree que quieres que el campo se serialice (porque la propiedad EDITABLE es verdadera), pero no podrá estar seguro hasta que definas la propiedad SERIALIZABLE. Si decides dejar esto así, todo funcionará correctamente y tu campo se serializará, pero recibirás advertencias de la consola.

size_.width

this.size_.width = 0;

Se convierte en lo siguiente:

this.isDirty_ = true;

La siguiente advertencia se puede omitir, pero puedes resolverla si configuras la propiedad isDirty_ en lugar de size_.width:

Deprecated use of setting size_.width to 0 to rerender a field. Set
field.isDirty_ to true instead.

La advertencia anterior significa que Blockly detectó que estás usando un método antiguo para volver a renderizar un campo y quiere que uses el nuevo método.

Para obtener más información sobre la propiedad isDirty_, consulta isDirty_.

init

La función init se convirtió en una función de plantilla para reducir el código duplicado en las subclases.

CustomFields.UpgradeField.prototype.init = function() {
  if (this.fieldGroup_) {
    // Already initialized once.
    return;
  }

  // Call superclass.
  CustomFields.UpgradeField.superClass_.init.call(this);

  // Create DOM elements.
  this.extraDom_ = Blockly.utils.dom.createSvgElement('image',
      {
        'height': '10px',
        'width': '10px'
      });
  this.extraDom_.setAttributeNS('http://www.w3.org/1999/xlink',
      'xlink:href', 'image.svg');
  this.extraDom_.style.cursor = 'pointer';
  this.fieldGroup_.appendChild(this.extraDom_);

  // Bind events.
  this.mouseOverWrapper_ =
    Blockly.browserEvents.bind(
        this.getClickTarget_(), 'mouseover', this, this.onMouseOver_);
  this.mouseOutWrapper_ =
    Blockly.browserEvents.bind(
        this.getClickTarget_(), 'mouseout', this, this.onMouseOut_);

  // Render.
  this.setValue(this.getValue());
};

Se convierte en lo siguiente:

CustomFields.UpgradeField.prototype.initView = function() {
  CustomFields.UpgradeField.superClass_.initView.call(this);

  this.extraDom_ = Blockly.utils.dom.createSvgElement('image',
      {
        'height': '10px',
        'width': '10px'
      });
  this.extraDom_.setAttributeNS('http://www.w3.org/1999/xlink',
      'xlink:href', 'image.svg');
  this.extraDom_.style.cursor = 'pointer';
  this.fieldGroup_.appendChild(this.extraDom_);
};

CustomFields.UpgradeField.prototype.bindEvents_ = function() {
  CustomFields.UpgradeField.superClass_.bindEvents_.call(this);

  this.mouseOverWrapper_ =
    Blockly.bindEvent_(
        this.getClickTarget_(), 'mouseover', this, this.onMouseOver_);
  this.mouseOutWrapper_ =
    Blockly.bindEvent_(
        this.getClickTarget_(), 'mouseout', this, this.onMouseOut_);
};

Esto significa que Blockly ahora procesa automáticamente lo siguiente:

  • Se verifica si el campo ya se inicializó.
  • Cómo crear el fieldGroup_
  • Renderiza el campo.
  • Información sobre la vinculación de la herramienta y mostrar eventos del editor.

Deberás manejar lo siguiente:

onMouseDown_

CustomFields.UpgradeField.prototype.onMouseDown_ = function(e) {
  // ...
};

Se convierte en lo siguiente:

CustomFields.UpgradeField.prototype.showEditor_ = function() {
  // ...
}

Te recomendamos que anules la función showEditor_ para controlar los clics del mouse, en lugar de la función onMouseDown_, ya que permite que la entrada pase a través del sistema de gestos.

Para obtener más información sobre los editores, consulta Editores.

setValue

La función setValue ahora es una función de plantilla para reducir el código duplicado en las subclases. Si la función setValue contiene lógica, considera refactorizarla para que se adapte a las rutas de control de valores descritas en Manejo de valores.

text_

Te recomendamos que nunca accedas a la propiedad text_ de tu campo ni la actualices directamente. En su lugar, usa la función getText para acceder al texto legible por el usuario de tu campo y la función setValue para actualizar el valor almacenado de tu campo.

Para obtener más información sobre el valor de un campo en comparación con su texto, consulta Anatomía de un campo.

Obtén asistencia para la actualización

Qué proporcionar

Cuando solicites asistencia, es mejor realizar las siguientes preguntas específicas:

No recomendado: "¿Cuál es el problema con este campo?"

También no se recomienda: “Ayúdame a actualizar este campo”.

Recomendado: "El texto del campo no se actualiza correctamente".

También es necesario proporcionar recursos a las personas que te ayudan. Estos archivos deberían ser fáciles de usar para otras personas.

No se recomienda:

  • Imágenes de código
  • Código incompleto.

Recomendado:

  • Completa el código del campo en formato de texto.
  • Imágenes de GIF de comportamiento de campo inadecuado.
  • Pasos para reproducir el comportamiento inadecuado de campos
  • La versión de Blockly desde la que realizas la actualización.

Dónde publicar

Publica preguntas de actualización en el foro de desarrolladores de Blockly.

Si estás seguro de que el problema es un problema con el núcleo de Blockly, también puedes publicar un problema en GitHub de Blockly. Si decides publicar un problema, completa toda la información solicitada.