ExtJS 4 - 在必填字段上标记红色星号

时间:2011-10-31 05:53:30

标签: forms extjs extjs4 required-field

我遇到此问题,当字段标记为“必需”(或fieldLabel

时,我需要在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的mixins呈现的。

可悲的是,延伸Ext.form.Labelable或覆盖Ext.form.Labelable对我来说都不合适。来自Ext.form.field.Base的扩展组件不会受到任何影响。即使我交换了mixins,模板仍然无效。

所以这里是我的解决方案,我对Ext.form.field.Base进行了非常严格的覆盖,并且它的工作原理如下(Check out my example

仅适用于ExtJS 4.0.7。要在ExtJS 4.0.2a上使用它,您需要根据4.0.2a labelableRenderTpl

中找到的/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); })();
Text

所以我在所有必填字段中添加了漂亮的星号。

问题是,有没有更简单的方法来实现这样的目标?覆盖非常苛刻,如果我们可以使用mixin最好,但mixin不能覆盖行为

注意

这背后的原因是因为我有自定义的字段需要从基础ComboFieldContainer,{{1}}进行扩展。 Mixins in the extended field doesn't even mess with the template。他们太固执了。也许现在最好的方法是重写基类... Check out the working example

11 个答案:

答案 0 :(得分:28)

我的解决方案有点短。我建议使用form的'beforeadd'事件,如下所示:

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

答案 1 :(得分:6)

你可以覆盖类似于extjs3 bun的布局组件,因为没有fieldLayout,我已经覆盖Ext.layout.Layout。它与分子人的解决方案非常相似,但它更为通用。适用于除表格之外的其他容器中使用的字段。

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

这比你的解决方案简单但不是更好,例如也用于字段集here

答案 2 :(得分:5)

您也可以覆盖和扩展任何内容,只需创建一个控制器操作:

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

答案 3 :(得分:5)

对于 Ext JS 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);
    }
});

答案 4 :(得分:4)

Extjs 4.1

当该字段具有fieldLabel时使用:

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

如果该字段没有fieldLabel使用配置选项的组合,则hideLabel配置必须为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>'

此外,您可以将此解决方案与Drasill插件混合使用,这样可以轻松地一次自定义所有字段。

答案 5 :(得分:4)

您可能会发现更优雅的方法是将css类添加到标有allowBlank=false的任何字段标签,并在CSS中设置您的强制指示符。

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

    extend: 'Ext.form.Panel',

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

});

然后,您可以使用:after伪实用程序在CSS中设置字段标签的样式:

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

答案 6 :(得分:2)

我为此制作了一个插件。

使用此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;

        }

    });

答案 7 :(得分:1)

实际上我认为使用fieldSubTpl和/或labelableRenderTpl来添加*比使用事件监听器更简洁。事件可以停止,侦听器可以分离。

我认为OP(Lionel Chan)的担心是使用Ext.override有点hacky并且他100%正确。但是如果我们在表单配置级别传递自定义tpl,那就不错了:

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

tpl可能有问题,我没试过。

答案 8 :(得分:1)

如果您不想覆盖任何内容,请将星号放在labelSeparator中:

{
  xtype: 'textfield',
  fieldLabel: 'Name',
  name: 'requestor_name',
  allowBlank: false,
  labelSeparator : ': <span style="color:red">*</span>'
}

答案 9 :(得分:0)

如果要为字段标签显示红色*,我们可以使用fieldlabel来执行此操作。

例如,以下代码创建标签名称为“Name”的新文本字段,并显示红色星号

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

答案 10 :(得分:0)

他们有很多方法可以做到这一点,上面你可以找到的很少,我建议的是:

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

只需将星号和标签文本放在单个html属性中即可。