フィールドに「必須」(またはallowBlank: false
)のマークが付けられている場合、fieldLabel
の横に赤いアスタリスクを追加する必要があるという問題があります。
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.Labelable
を拡張することも、Ext.form.Labelable
をオーバーライドすることもできません。 Ext.form.field.Base
の拡張コンポーネントは、それによる影響を受けません。ミックスインを入れ替えても、テンプレートは機能しません。
だからここに私の解決策があります、私はExt.form.field.Base
に対して非常に厳しいオーバーライドを行いました、そしてそれは次のように機能します( 私の例をチェックしてください )
これはExtJS 4.0.7専用です。 ExtJS 4.0.2aで使用するには、labelableRenderTpl
を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);
})();
そして、すべての必須フィールドにニースアスタリスクを追加しています。
質問は、このようなものを達成する簡単な方法はありますか?オーバーライドはかなり厳しく、ミックスインを使用できる場合に最適ですが、ミックスインは動作をオーバーライドできません
注
この背後にある理由は、ベースText
、Combo
、FieldContainer
から拡張する必要があるカスタマイズされたフィールドがあるためです。 拡張フィールドのMixinはテンプレートを混乱させることさえありません 。彼らはあまりにも頑固です。おそらく今のところ最良の方法は、Baseクラスをオーバーライドすることです... 実際の例を確認してください
私は少し短い解決策を持っています。次のようなフォームの「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 です
FieldLayoutがない場合、Ext.layout.Layout
をオーバーライドしたので、extjs3 bunと同様のレイアウトコンポーネントをオーバーライドできます。それは分子マンの解に非常に似ていますが、より一般的です。フォーム以外のコンテナで使用されるフィールドでの作業。
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
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);
}
});
何もオーバーライドして拡張せず、次のようなコントローラーアクションを作成することもできます。
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
}
});
}
});
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プラグインを組み合わせることで、すべてのフィールドを一度に簡単にカスタマイズできます。
よりエレガントな方法として、allowBlank=false
でマークされたフィールドラベルにcssクラスを追加し、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;
}
このためのプラグインを作成しました。
この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;
}
});
何もオーバーライドしたくない場合は、labelSeparatorにアスタリスクを入れます。
{
xtype: 'textfield',
fieldLabel: 'Name',
name: 'requestor_name',
allowBlank: false,
labelSeparator : ': <span style="color:red">*</span>'
}
実際、私は fieldSubTpl や labelableRenderTpl を使用して*を追加する方が、イベントリスナーを使用するよりもクリーンなアプローチだと思います。イベントを停止したり、リスナーを切り離したりできます。
OP(Lionel Chan)の懸念は、Ext.overrideを使用するのがちょっとハッキーで、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に問題がある可能性があります。試したことがありません。
フィールドラベルに赤*を表示する場合は、これを行う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
});
彼らはこれを行うための非常に多くの方法であり、そのうちのいくつかは上記で見つけることができますが、私が提案しているのは:
{
xtype : 'label',
html:'<span>First Name</span><span style="color: rgb(255, 0, 0); padding-left: 2px;">*</span>',
width:50,
}
単に、アスタリスクとラベルの両方のテキストを1つのhtmlプロパティに配置できます。