¿Práctica recomendada para anular clases / propiedades en ExtJS?

Tengo un Ext.form.field.Text y quiero anular la función setValue .

¿Cuál es la forma recomendada de anular esta funcionalidad de clase en ExtJS? Ext.override ?

Para aclarar: me refiero a una modificación de clase real, una modificación / extensión permanente prevista de una clase , que siempre debe hacerse extendiendo una clase. Pero no es una solución temporal solo para un problema específico (corrección de errores, etc.) .

Tiene al menos cuatro opciones para anular miembros de Clases (Ext)

  • Creo que el prototipo es bien conocido y le permite anular un miembro para todas las instancias de una clase. Puedes usarlo como

     Ext.view.View.prototype.emptyText = ""; 

    Si bien no puedes usarlo como

     // callParent is NOT allowed for prototype Ext.form.field.Text.prototype.setValue = function(val) { var me = this, inputEl = me.inputEl; if (inputEl && me.emptyText && !Ext.isEmpty(value)) { inputEl.removeCls(me.emptyCls); me.valueContainsPlaceholder = false; } me.callParent(arguments); me.applyEmptyText(); return me; }; 

    Aquí hay un JSFiddle

    Esta variante no debe usarse para modificaciones de clase reales.

  • Ext.override hace casi lo mismo que el prototipo, pero se aplica por completo al sistema de clases ExtJS que le permite usar callParent()

    Puedes usarlo como

     // callParent is allowed for override Ext.override('Ext.form.field.Text', { setValue: function(val) { this.callParent(['In override']); return this; } }); 

    Aquí hay un JSFiddle (error de cp corregido! Gracias a @nogridbag )

    Caso práctico : me enfrenté a un mal comportamiento (creo que aún existe) de un radiogrupo en el que ExtJS espera un objeto (par clave-valor) para la configuración correcta del valor. Pero tengo solo un entero en mi back-end. Primero apliqué una solución usando Ext.override para el método setValue() y luego extendí desde radiogroup. Ahí solo hago un par clave-valor del valor dado y llamo al método padre con eso.

    Como @rixo mencionó, esto se puede usar para anular un miembro de instancia. Y, por lo tanto, puede estar calificado para anular incluso mixinas (nunca lo probé)

     var panel = new Ext.Panel({ ... }); Ext.override(panel, { initComponent: function () { // extra processing... this.callParent(); } }); 

    Esta variante no debe usarse para modificaciones de clase reales.

  • Extender una clase existente para aplicar comportamiento y representación adicionales. Use esta variante para crear un subtipo que se comporte diferente sin perder el tipo original.

    En el siguiente ejemplo, ampliamos el campo de texto con un método para cambiar el color de la etiqueta cuando establecemos un nuevo valor llamado setColored y setValue método setValue para eliminar un color de etiqueta cuando se llama directamente a setValue

     Ext.define('Ext.ux.field.Text',{ extend: 'Ext.form.field.Text', widget: 'uxtextfield', setColored: function(val,color) { var me = this; if (me.settedCls) { me.removeCls(me.settedCls); } me.addCls(color); me.settedCls = color; me.setValue(val,true); }, setValue: function(val,take) { var me = this; if (!take && me.settedCls) { me.removeCls(me.settedCls); } me.callParent(arguments); return me; } }); 

    Aquí hay un JSFiddle

  • Anulación por instancia ocurrirá en casos muy raros y podría no ser aplicable a todas las propiedades. En tal caso (donde no tengo un ejemplo a la mano) tiene una sola necesidad de un comportamiento diferente y puede considerar anular una configuración solo por instancia. Básicamente, usted hace tales cosas todo el tiempo cuando aplica una configuración en la creación de clases, pero la mayoría de las veces simplemente anula los valores predeterminados de las propiedades de configuración, pero también puede anular las propiedades que hacen referencia a las funciones. Esto anula completamente la implementación y es posible que no permita el acceso al tipo de línea (si existe) lo que significa que no puede usar callParent . Puede intentarlo con setValue para ver que no se puede aplicar a una cadena existente. Pero, de nuevo, es posible que enfrente algunos casos excepcionales en los que esto sea útil, incluso cuando solo sea durante el desarrollo y se vuelva a implementar para que sea productivo. Para tal caso, debe aplicar la anulación después de crear el específico utilizando Ext.override como se mencionó anteriormente.

    Importante: ¡No tiene acceso a la instancia de clase llamando a this si no usa Ext.override !

Si me perdí algo o algo es (ya no) correcto, por favor comenten o siéntanse libres de editarlo.

Como lo comentó @Eric

Ninguno de estos métodos le permite anular mixins (como Ext.form.field.Field). Dado que las funciones de mezcla se copian en clases en el momento en que define la clase, debe aplicar sus modificaciones a las clases objective directamente

La respuesta de @sra es excelente y fue muy útil para mí al obtener una comprensión más profunda de la funcionalidad de reemplazo disponible en Ext, pero no incluye la manera en que más comúnmente implemento reemplazos que se ve así:

 Ext.define('my.application.form.field.Text' { override: 'Ext.form.field.Text' getValue: function () { // your custom functionality here arguments[1] = false; // callParent can be used if desired, or the method can be // re-written without reference to the original this.callParent(arguments) } }); 

Todavía estoy usando Ext. 5, entonces cargaría este archivo en mi Application.js y lo agregaría al array require, que aplica la anulación a la aplicación globalmente. Creo que los proyectos de Ext 6 incluyen una carpeta de anulación y simplemente agregar este archivo a esa carpeta garantiza que se aplique la anulación.