forms - ExtJS 4-एक आवश्यक क्षेत्र पर एक लाल तारांकन चिह्नित करें




extjs4 required-field (8)

मुझे यह समस्या है जहां मुझे फ़ील्ड के बगल में एक लाल तारांकन जोड़ने की ज़रूरत है जब फ़ील्ड को "आवश्यक" (या अनुमति allowBlank: false ) के रूप में चिह्नित किया जाता है

ExtJS3 में, हम Ext.layout.FormLayout को ओवरराइड करके आसानी से इस हैक को प्राप्त कर सकते हैं:

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

लेकिन यह ExtJS4 में असंभव है। FormLayout अब लागू नहीं है, और वास्तव में Ext.form.field.Base नामक Ext.form.Labelable का उपयोग करके Ext.form.field.Base द्वारा लेबल प्रस्तुत किए Ext.form.Labelable

अफसोस की बात है, न तो Ext.form.Labelable या Ext.form.Labelable विस्तार करना मेरे लिए व्यावहारिक है। Ext.form.field.Base विस्तारित घटक Ext.form.field.Base कोई प्रभाव नहीं प्राप्त करते हैं। यहां तक ​​कि अगर मैंने मिश्रणों को बदल दिया है, तो टेम्पलेट अभी भी काम नहीं करेगा।

तो यहां मेरा समाधान आओ, जहां मैंने Ext.form.field.Base पर बहुत कठोर ओवरराइड किया Ext.form.field.Base , और यह अनुसरण के रूप में काम करता है ( मेरा उदाहरण देखें )

यह केवल ExtJS 4.0.7 के लिए है। ExtJS 4.0.2a पर इसका उपयोग करने के लिए आपको 4.0.2a /src/form/Labelable.js में पाए गए अनुसार के अनुसार labelableRenderTpl को संशोधित करने की आवश्यकता है

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


})();

और इसलिए मेरे पास सभी आवश्यक फ़ील्ड में अच्छा तारांकन जोड़ा गया है।

प्रश्न यह है कि इस तरह कुछ हासिल करने का कोई आसान तरीका है? ओवरराइडिंग बहुत कठोर है, अगर हम मिश्रणों का उपयोग कर सकते हैं तो सबसे अच्छा है, लेकिन मिक्सर व्यवहार को ओवरराइड नहीं कर सकते हैं

ध्यान दें

इसका कारण यह है कि मैंने उन क्षेत्रों को अनुकूलित किया है जिन्हें बेस Text , Combo , FieldContainer से विस्तारित करने की आवश्यकता है। विस्तारित क्षेत्र में मिक्सिन टेम्पलेट के साथ भी गड़बड़ नहीं करता है । वे बहुत जिद्दी हैं। शायद अब के लिए सबसे अच्छा तरीका बेस क्लास को ओवरराइड कर रहा है ... कामकाजी उदाहरण देखें

https://code.i-harness.com


Extjs 4.1

जब फ़ील्ड में फ़ील्ड है लेबल का उपयोग करें:

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

यदि फ़ील्ड में फ़ील्ड नहीं है लेबल लेबल कॉन्फ़िगरेशन विकल्पों के संयोजन का उपयोग करते हैं, तो hideLabel कॉन्फ़िगरेशन गलत होना चाहिए:

//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>'

इसके अलावा, आप इस समाधान को ड्रैसिल प्लगइन के साथ मिश्रित कर सकते हैं, जिसमें सभी फ़ील्ड को एक साथ अनुकूलित करने का एक आसान तरीका है।


असल में मुझे लगता है कि fieldSubTpl और / या labelableRenderTpl करने labelableRenderTpl का उपयोग करना * ईवेंट श्रोता का उपयोग करने से एक क्लीनर दृष्टिकोण है। घटनाओं को रोका जा सकता है, श्रोताओं को अलग किया जा सकता है।

मुझे लगता है कि ओपी (लियोनेल चैन) की चिंता यह थी कि Ext.override का उपयोग करना हैकी है और वह 100% सही है। लेकिन अगर हम फॉर्म कॉन्फ़िगरेशन स्तर पर कस्टम टीपीएल पास करते हैं तो यह बुरा नहीं है:

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',.....

टीपीएल के साथ कुछ गलत हो सकता है, मैंने कोशिश नहीं की है।


आप कुछ भी ओवरराइड और विस्तार भी कर सकते हैं और इस तरह एक नियंत्रक कार्रवाई बना सकते हैं:

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

एक दृष्टिकोण जो आपको अधिक सुरुचिपूर्ण लगता है, किसी भी फ़ील्ड लेबल में एक सीएसएस क्लास जोड़ रहा है जिसे allowBlank=false के साथ चिह्नित किया गया है और सीएसएस में अपना अनिवार्य संकेतक शैली है।

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

    extend: 'Ext.form.Panel',

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

});

फिर आप अपने फ़ील्ड लेबल को सीएसएस में स्टाइल कर सकते हैं :after छद्म उपयोगिता के :after :

.x-required:after {
    content: ' *';
    color: red;
    font-weight: bold;
}

मेरे पास थोड़ा छोटा समाधान है। मैं इस तरह के फॉर्म 'प्रीडैड' घटना का उपयोग करने का सुझाव देता हूं:

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

यहां demo


मैंने इसके लिए एक प्लगइन बनाया है।

इस ExtJS 4.1 (कम से कम) काम करता है।

इस तरह प्रयोग करें:

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

या, "तारांकन" को अनुकूलित करने के लिए:

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

प्लगइन के लिए कोड यहां दिया गया है:

/**
 * 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;

        }

    });

यदि आप फ़ील्ड लेबल के लिए लाल * प्रदर्शित करना चाहते हैं तो हम फ़ील्ड लेबल का उपयोग कर सकते हैं जो यह करता है।

उदाहरण के लिए नीचे दिया गया कोड लेबल नाम "नाम" के साथ नया टेक्स्ट फ़ील्ड बनाता है और लाल तारांकन प्रदर्शित होता है

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

एक्सटी जेएस 4.1.1 के लिए यह काम करता है:

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




required-field