ExtJS 4-marquer un astérisque rouge sur un champ obligatoire

J'ai ce problème lorsque j'ai besoin d'ajouter un astérisque rouge à côté d'un fieldLabel lorsqu'un champ est marqué comme "obligatoires" (ou allowBlank: false)

Dans ExtJS3, nous pouvons avoir ce hack facilement en remplaçant Ext.layout.FormLayout comme suit:

Ext.override(Ext.layout.FormLayout, {
    getTemplateArgs: function(field) {
        var noLabelSep = !field.fieldLabel || field.hideLabel;
        var labelSep = (typeof field.labelSeparator == 'undefined' ? this.labelSeparator : field.labelSeparator);
        if (!field.allowBlank) labelSep += '<span style="color: rgb(255, 0, 0); padding-left: 2px;">*</span>';
        return {
            id: field.id,
            label: field.fieldLabel,
            labelStyle: field.labelStyle||this.labelStyle||'',
            elementStyle: this.elementStyle||'',
            labelSeparator: noLabelSep ? '' : labelSep,
            itemCls: (field.itemCls||this.container.itemCls||'') + (field.hideLabel ? ' x-hide-label' : ''),
            clearCls: field.clearCls || 'x-form-clear-left'
        };
    }
});

Mais C'est impossible dans ExtJS4. FormLayout n'est plus applicable, et les étiquettes sont en fait rendues par Ext.form.field.Base en utilisant un mixin appelé Ext.form.Labelable.

Malheureusement, ni étendre le Ext.form.Labelable ou remplacer Ext.form.Labelable n'est réalisable pour moi. Les composants étendus de Ext.form.field.Base font reçoivent pas de se produire. Même si j'ai échangé les mixins, les modèles ne fonctionneraient toujours pas.

Voici donc ma solution, où j'ai fait un override très dur sur Ext.form.field.Base, et cela fonctionne comme suit ( consultez mon exemple )

Ceci est pour ExtJS 4.0.7 seulement. Pour l'utiliser sur ExtJS 4.0.2 un, vous devez modifier le labelableRenderTpl selon que l'on retrouve dans un 4.0.2/src/form/Labelable.js

(function() {

    var overrides =  {
        labelableRenderTpl: [
            '<tpl if="!hideLabel && !(!fieldLabel && hideEmptyLabel)">',
                '<label id="{id}-labelEl"<tpl if="inputId"> for="{inputId}"</tpl> class="{labelCls}"',
                    '<tpl if="labelStyle"> style="{labelStyle}"</tpl>>',
                    '<tpl if="fieldLabel">{fieldLabel}{labelSeparator}</tpl>',
                    '<tpl if="!allowBlank"><span style="color:red">*</span></tpl>',
                '</label>',
            '</tpl>',
            '<div class="{baseBodyCls} {fieldBodyCls}" id="{id}-bodyEl" role="presentation">{subTplMarkup}</div>',
            '<div id="{id}-errorEl" class="{errorMsgCls}" style="display:none"></div>',
            '<div class="{clearCls}" role="presentation"><!-- --></div>',
            {
                compiled: true,
                disableFormats: true
            }
        ],

        /**
         * @protected
         * Generates the arguments for the field decorations {@link #labelableRenderTpl rendering template}.
         * @return {Object} The template arguments
         */
        getLabelableRenderData: function() {
            var me = this,
                labelAlign = me.labelAlign,
                labelCls = me.labelCls,
                labelClsExtra = me.labelClsExtra,
                labelPad = me.labelPad,
                labelStyle;

            // Calculate label styles up front rather than in the Field layout for speed; this
            // is safe because label alignment/width/pad are not expected to change.
            if (labelAlign === 'top') {
                labelStyle = 'margin-bottom:' + labelPad + 'px;';
            } else {
                labelStyle = 'margin-right:' + labelPad + 'px;';
                // Add the width for border-box browsers; will be set by the Field layout for content-box
                if (Ext.isBorderBox) {
                    labelStyle += 'width:' + me.labelWidth + 'px;';
                }
            }

            return Ext.copyTo(
                {
                    inputId: me.getInputId(),
                    fieldLabel: me.getFieldLabel(),
                    labelCls: labelClsExtra ? labelCls + ' ' + labelClsExtra : labelCls,
                    labelStyle: labelStyle + (me.labelStyle || ''),
                    subTplMarkup: me.getSubTplMarkup(),
                    allowBlank: me.allowBlank
                },
                me,
                'hideLabel,hideEmptyLabel,fieldBodyCls,baseBodyCls,errorMsgCls,clearCls,labelSeparator',
                true
            );
        }
    };


    //Both field.Base and FieldContainer are affected, so need to cater for.
    Ext.override(Ext.form.field.Base, overrides);
    Ext.override(Ext.form.FieldContainer, overrides);


})();

Et j'ai donc le bel astérisque ajouté à tout le nécessaire Fields.

La Question Est, y a-t-il un moyen plus facile de réaliser quelque chose comme ça? La substitution est assez dure, mieux si nous pouvons utiliser mixins, mais mixins ne peut pas remplacer le comportement

Note

La raison derrière cela est parce que j'ai des champs personnalisés qui doit être étendu à partir de la base Text, Combo, FieldContainer. Mixins dans le champ étendu ne plaisante même pas avec le modèle . Ils sont tout simplement trop têtu. Peut-être la meilleure façon pour l'instant est en remplaçant la classe de Base... consultez l'exemple de travail

23
demandé sur Jonas 2011-10-31 09:53:30

11 réponses

J'ai une solution un peu plus courte. Je suggère d'utiliser l'événement' beforeadd ' du formulaire comme ceci:

Ext.define('Ext.ux.form', {
    extend: 'Ext.form.Panel',
    initComponent: function() {
      this.on('beforeadd', function(me, field){
        if (!field.allowBlank)
          field.labelSeparator += '<span style="color: rgb(255, 0, 0); padding-left: 2px;">*</span>';
      });
      this.callParent(arguments);
    }
});

Ici démo

27
répondu Molecular Man 2011-11-03 18:07:56

Vous pouvez toujours remplacer le composant de mise en page similaire à extjs3 Bun étant donné qu'il n'y a pas fieldLayout, j'ai remplacé Ext.layout.Layout. C'est assez similaire à la solution de molecule man, mais c'est plus général. Travailler pour les champs utilisés dans d'autres conteneurs que les formulaires.

Ext.override(Ext.layout.Layout, {
    renderItem: function(item, target, position) {
      if (item && !item.rendered && item.isFieldLabelable && item.fieldLabel && item.allowBlank == false) {
        item.fieldLabel += ' <span class="req" style="color:red">*</span>';
      }
      this.callOverridden(arguments);
    }
});

C'est plus simple que votre solution mais pas nécessairement mieux, se exemple également utilisé dans fieldsets ici

6
répondu nscrob 2011-11-03 17:52:54

Vous pouvez également remplacer et étendre rien et simplement créer une action de contrôleur comme ceci:

Ext.define('MyApp.controller.MyForm', {
    extend: 'Ext.app.Controller',

    markMandatoryFields: function(field, options) {
        if (field && field.isFieldLabelable && field.fieldLabel && field.allowBlank == false) {
            field.fieldLabel += ' <span class="req" style="color:red">*</span>';
        }
    },

    init: function() {
        this.control({
            "field": {
                beforerender: this.markMandatoryFields
            }
        });
    }
});
5
répondu Christiaan Westerbeek 2012-05-15 09:57:23

Pour Ext JS 4.1.1 cela fonctionne:

Ext.define('com.ideas.widgets.Base', {
    override : 'Ext.form.field.Base',
    initComponent : function()
    {
        if(this.allowBlank!==undefined && !this.allowBlank)
        {
            if(!this.labelSeparator)
            {
                this.labelSeparator = "";
            }
            this.labelSeparator += '<span style="color:red">*</span>';
        }
        this.callParent(arguments);
    }
});
5
répondu Varun Achar 2012-09-10 07:44:28

Extjs 4.1

Lorsque le champ a une étiquette de champ, utilisez:

fieldLabel: 'Name',
allowBlank: false,    
afterLabelTextTpl: "<span style="color:red;font-weight:bold" data-qtip="Required">*</span>"

Si le champ n'a pas de fieldLabel, utilisez une combinaison d'options de configuration, la configuration hideLabel doit être false:

//hideLabel: false
name: 'lastName',
emptyText: "Last Name",
allowBlank: false,    
labelWidth: 0,
fieldLabel: '',
hideEmptyLabel: false,
afterLabelTextTpl: '<span style="color:red;font-weight:bold" data-qtip="Required">*</span>'

En outre, vous pouvez mélanger cette solution avec le plugin Drasill et avoir un moyen facile de personnaliser tous les champs à la fois.

4
répondu Esteban Gatjens 2013-11-26 19:10:12

Une approche que vous pourriez trouver plus élégante consiste à ajouter une classe css à toute étiquette de champ marquée par allowBlank=false et à styliser votre indicateur obligatoire en CSS.

Ext.define('Ext.ux.form', {

    extend: 'Ext.form.Panel',

    listeners: {
        'beforeadd': function(){
            if (!field.allowBlank) {
                field.labelClsExtra = 'x-required';
            }
        }
    }

});

Vous pouvez ensuite styliser votre étiquette de champ en CSS avec un pseudo utilitaire :after:

.x-required:after {
    content: ' *';
    color: red;
    font-weight: bold;
}
4
répondu Hady 2014-05-02 00:17:22

J'ai fait un plugin pour cela.

Fonctionne avec ExtJS 4.1 (au moins).

Utilisez si comme ceci:

Ext.create('Ext.form.Panel', {
  ...
  plugins : "formlabelrequired"
  ...
});

Ou, pour personnaliser l '"astérisque":

Ext.create('Ext.form.Panel', {
  ...
  plugins : [{ptype:"formlabelrequired", asterisk:" (mandatory)"}]
  ...
});

Voici le code du plugin:

/**
 * Plugin (ptype = 'formlabelrequired') that adds "asterisk" to labels
 * for Fields with "allowBlank: false".
 */
Ext.define('Ext.ux.plugin.form.LabelRequired', {

        extend: 'Ext.AbstractPlugin',

        alias: 'plugin.formlabelrequired',

        asterisk: ' <span class="required"> *</span>',

        constructor: function() {

            this.callParent(arguments);

        },

        init: function(formPanel) {
            formPanel.on('beforerender', this.onBeforeRender, this);
        },

        /**
         * @private
         * Adds asterisk to labels.
         */
        onBeforeRender: function(formPanel) {

            var i, len, items;

            items = formPanel.query('[allowBlank=false]');

            for (i = 0, len = items.length; i < len; i++) {
                item = items[i];
                item.afterLabelTextTpl = (item.afterLabelTextTpl || "") + this.asterisk;
            }

            return true;

        }

    });
2
répondu Drasill 2013-01-17 16:14:13

En fait, je pense que l'utilisation de fieldSubTpl et / ou labelableRenderTpl pour ajouter le * est une approche plus propre que l'utilisation de l'écouteur d'événement. Les événements peuvent être arrêtés, les auditeurs peuvent être détachées.

Je pense que la préoccupation de L'OP(Lionel Chan)était que l'utilisation de L'Ext.override est un peu hacky et il a raison à 100%. Mais si nous passons le tpl personnalisé au niveau de la configuration du formulaire, ce n'est pas si mal:

Ext.create('Ext.form.Panel',{
    defaults:{
        fieldSubTpl:['<input id="{id}" type="{type}" ', 
        '<tpl if="name">name="{name}" </tpl>', 
        '<tpl if="size">size="{size}" </tpl>', 
        '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>', 
        'class="{fieldCls} {typeCls}" autocomplete="off" />',
        '<span>',
        '<tpl if="allowBlank==false">*</tpl>',
        '</span>',
        {
            compiled: true, 
            disableFormats: true
    }]},
    items : [{
        xtype : 'textfield',.....

Il pourrait y avoir quelque chose de mal avec le tpl, Je n'ai pas essayé.

1
répondu Chao 2011-11-06 05:04:17

Si vous ne voulez rien remplacer, placez l'astérisque dans labelSeparator:

{
  xtype: 'textfield',
  fieldLabel: 'Name',
  name: 'requestor_name',
  allowBlank: false,
  labelSeparator : ': <span style="color:red">*</span>'
}
1
répondu Evan Siroky 2014-06-19 01:59:48

Si vous voulez que le rouge * soit affiché pour une étiquette de champ, nous pouvons utiliser fieldlabel qui le fait.

Par exemple le code ci-dessous crée un nouveau champ de texte avec le nom de l'étiquette "Nom" et astérisque rouge s'affiche

var name = new Ext.form.TextField({
    fieldLabel : 'Label<span style=\"color:red;\" ext:qtip=\"This field is required\"> *</span>',
    name : 'name',
    id: 'Name',
    maxLength : 40,
    width : 205,
    allowBlank : false
});
0
répondu sandeep vanama 2014-06-18 07:26:15

Ils sont tellement de façons de le faire et peu dont vous pouvez trouver ci-dessus, ce que je suggère est:

 {
    xtype : 'label',
    html:'<span>First Name</span><span style="color: rgb(255, 0, 0); padding-left: 2px;">*</span>',
    width:50,
 }

Vous pouvez simplement mettre à la fois un astérisque et un texte D'étiquette dans une seule propriété html.

0
répondu Mayur Gite 2015-10-29 10:26:12