ExtJS 4 - 在必填字段上标记红色星号
我遇到这个问题,当字段标记为“必需”(或 allowBlank: false
)时,我需要在 fieldLabel
旁边添加一个红色星号。
在 ExtJS3 中,我们可以通过重写Ext.layout.FormLayout
,可以轻松实现此 hack,如下所示:
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 进行了非常严格的覆盖,其工作原理如下(查看我的示例)
这仅适用于 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);
})();
并且所以我在所有必填字段中添加了漂亮的星号。
问题是,有没有更简单的方法来实现这样的目标?重写是相当苛刻的,如果我们可以使用 mixins 最好,但是 mixins 不能重写行为
注意
这背后的原因是因为我有自定义字段需要从基本 文本
、组合
、FieldContainer
。 扩展字段中的 Mixins 甚至不会扰乱模板。他们只是太固执了。也许现在最好的方法是覆盖基类... 查看工作示例
I have this problem where I need to add a red asterisk beside a fieldLabel
when a field is marked as "required" (or allowBlank: false
)
In ExtJS3, we can have this hack easily by overriding Ext.layout.FormLayout
as follow:
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'
};
}
});
But this is impossible in ExtJS4. FormLayout
is no longer applicable, and labels are in fact rendered by Ext.form.field.Base
by using a mixins called Ext.form.Labelable
.
Sadly, neither extending the Ext.form.Labelable
or overriding Ext.form.Labelable
is workable for me. The extended components from Ext.form.field.Base
does not receive any effect from it. Even if I swapped the mixins, the templates still would not work.
So here come my solution, where I did a very harsh override over Ext.form.field.Base
, and it works as follow (Check out my example)
This is for ExtJS 4.0.7 only. To use it on ExtJS 4.0.2a you need to modify the labelableRenderTpl
according to the one found in 4.0.2a /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);
})();
And so I have the nice asterisk added to all the required fields.
Question is, is there any easier way to achieve something like this? Overriding is pretty harsh, best if we can use mixins, but mixins cannot override the behavior
Note
The reason behind this is because I have customized fields that needed to be extended from the base Text
, Combo
, FieldContainer
. Mixins in the extended field doesn't even mess with the template. They are just too stubborn. Perhaps the best way for now is by overriding the Base class... Check out the working example
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
我为此制作了一个插件。
(至少)适用于 ExtJS 4.1。
像这样使用 if :
或者,自定义“星号”:
这是插件的代码:
I've made a plugin for this.
Works this ExtJS 4.1 (at least).
Use if like this :
Or, to customize the "asterisk":
Here is the code for the plugin :
实际上我认为使用 fieldSubTpl 和/或 labelableRenderTpl 添加 * 是比使用事件侦听器更干净的方法。事件可以停止,监听器可以分离。
我认为 OP(Lionel Chan)担心的是使用 Ext.override 有点老套,他是 100% 正确的。但是,如果我们在表单配置级别传递自定义 tpl,情况并没有那么糟糕:
tpl 可能有问题,我还没有尝试过。
Actually I think using fieldSubTpl and/or labelableRenderTpl to add the * is a cleaner approach than using the event listener. Events can be stopped, listeners can be detached.
I think OP(Lionel Chan)'s concern was that using Ext.override is kinda hacky and he's 100% right. But if we pass the custom tpl in at the form configuration level it's not that bad:
There could be something wrong with the tpl, i haven't tried.
如果您不想覆盖任何内容,请将星号放入 labelSeparator 中:
If you don't want to override anything, put the asterisk in the labelSeparator:
如果您希望字段标签显示红色 *,我们可以使用 fieldlabel 来执行此操作。
例如,以下代码创建标签名称为“Name”的新文本字段,并显示红色星号
If you want red * to be displayed for a field label we can use fieldlabel which does this.
For example the below code creates new text field with label name "Name" and red asterisk is displayed
有很多方法可以做到这一点,但您可以在上面找到其中的几种,我的建议是:
您可以简单地将星号和标签文本放在单个 html 属性中。
Their are so many ways to do this and few of which you can find above, what I am suggesting is:
Simply you can put both asterisk and Label text in single html property.
我有一个更短的解决方案。我建议使用表单的“beforeadd”事件,如下所示:
这是演示
I have a little bit shorter solution. I suggest to use form's 'beforeadd' event like this:
Here is demo
鉴于没有 fieldLayout,您仍然可以重写类似于 extjs3 面包的布局组件,我已经重写了
Ext.layout.Layout
。它与分子人的解决方案非常相似,但更通用。适用于表单以外的其他容器中使用的字段。这比您的解决方案更简单,但不一定更好,例如也在字段集中使用此处
You can still override the layout component similar to extjs3 bun given that there is no fieldLayout, I've overriden
Ext.layout.Layout
. It's quite similar to molecule man's solution but it's more general. Working for fields used in other containers than forms.This is simpler than your solution but not necesarely better, se example also used in fieldsets here
您还可以覆盖和扩展任何内容,只需创建一个控制器操作,如下所示:
You can also override and extend nothing and just create a controller action like so:
对于Ext JS 4.1.1,这有效:
For Ext JS 4.1.1 this works:
Extjs 4.1
当字段有 fieldLabel 时使用:
如果字段没有 fieldLabel 使用配置选项的组合,则 hideLabel 配置必须为 false:
此外,您可以将此解决方案与 Drasill 插件混合使用,并有一个简单的自定义方法一次所有字段。
Extjs 4.1
When the field has a fieldLabel use:
If the field don't have a fieldLabel use a combination of config options, the hideLabel config must be false:
Also, you can mix this solution with Drasill plugin an have a easy way to customise all fields at once.
您可能会发现更优雅的方法是将 CSS 类添加到任何标有
allowBlank=false
的字段标签,并在 CSS 中设置强制指示器的样式。然后,您可以使用
:after
伪实用程序在 CSS 中设置字段标签的样式:An approach that you might find more elegant is adding a css class to any field label that is marked with
allowBlank=false
and style your mandatory indicator in CSS.You can then style your field label in CSS with an
:after
pseudo utility: