PDA

View Full Version : Custom Field Renderer



g13013
17 Mar 2009, 5:16 PM
this if my first extension that i post in the Ext forum, so i hope that will interest somone.
this is a classic field that render value after the blur event juste like grid cell rendering, and restore raw value when editing and calling getValue() mothod



/*
** A custom renderer field
** by g13013 - (2009)
**
** the default renderer is set to internal money rendering method
**
*/
Ext.ux.customRendererField = Ext.extend(Ext.form.Field, {


/**
*@param: {priceUnit} Money unit Ex : Algerian DZD
*
*/
priceUnit:'DZD',

/**
*@param: {priceDelemiter} Delemiter for the price space or ',' are a valid delemiter
*
*/
priceDelemiter:' ',

/**
*@param: {enableRenderer} set price rendering is enabled or no
*
*/
enableRenderer:true,


/**
*@param: {customRenderer} a custom renderer
*
*/

customRenderer:undefined,

initComponent : function(){
Ext.ux.customRendererField.superclass.initComponent.call(this);
if (this.priceDelemiter!=',' && this.priceDelemiter!=' ') this.priceDelemiter=' '
},

renderValue :function(action,disable) {//bypass enableRendering verification when desabling rendering
if (this.enableRenderer || disable) {
if (this.customRenderer===undefined){
this.RenderMoney(action) //if customRenderer is undefined call default renderer
} else {
this.customRenderer.call(this,action)
}
}
},

RenderMoney :function(action) {
if (!action & !this.el.dom.readOnly) {
this.el.dom.value=this.el.dom.value.replace(/[^0-9.]+/g,'');//replace all alphabetic ans special characters except '.'
} else {
value=this.el.dom.value.replace(/[^0-9.]+/g,'');//replace all alphabetic ans special characters except '.'
this.el.dom.value=SetMoney(value,this.priceDelemiter,this.priceUnit)//render in money format
}
},

onFocus : function(){
Ext.ux.customRendererField.superclass.onFocus.call(this);
this.renderValue(false);
},

onBlur : function(){
Ext.ux.customRendererField.superclass.onFocus.call(this);
this.renderValue(true);
},

setValue : function(v){
Ext.ux.customRendererField.superclass.setValue.call(this,v);
this.renderValue(true)
},

getValue : function(){
if(!this.rendered) {
return this.value;
}
this.renderValue(false)
var v = this.el.getValue();
if(v === this.emptyText || v === undefined){
v = '';
}
this.renderValue(true)
return v;
},

setenableRenderer: function (set) {
this.enableRenderer=set
if (set) {
this.renderValue(true);
} else {
this.renderValue(false,true);//disable rendering
}

}

});
Ext.reg('customrendererfield',Ext.ux.customRendererField)



function SetMoney (price,delemiter,unit){
/*
** render in Money format with somme adaptation for unit and delemiter changing posibility
** price price
** delemiter delemiter
** unit unit
** returns new String like (100,000.00 DZD) or (200 000.00 DZD)
*/
delemiter=(undefined===delemiter) ? (" ") : (delemiter)
unit=(undefined===unit) ? ("$") : (unit)
price = (Math.round((price-0)*100))/100;
price = (price == Math.floor(price)) ? price + (".00") : ((price*10 == Math.floor(price*10)) ? price + "0" : price);
price = String(price);
var ps = price.split('.');
var whole = ps[0];
var sub = ps[1] ? '.'+ ps[1] : '.00';
var r = /(\d+)(\d{3})/;
while (r.test(whole)) {
whole = whole.replace(r, '$1' + delemiter + '$2');
}
price = whole + sub;
if(price.charAt(0) == '-'){
return '-$' + price.substr(1);
}
return price+" "+unit;
}

/**************************************************************************
*** this function is the simple adaptation of the original php str_replace
*** i find it in the internet
*** that can help for value rendering process
**************************************************************************/
function str_replace(a, b, str) {
return str_replace2(str, a, b);
}
function str_replace2(SRs, SRt, SRu) {
/*
** Replace a token in a string
** s string to be processed
** t token to be found and removed
** u token to be inserted
** returns new String
*/
SRRi = SRs.indexOf(SRt);
SRRr = '';
if (SRRi == -1) return SRs;
SRRr += SRs.substring(0,SRRi) + SRu;
if ( SRRi + SRt.length < SRs.length)
SRRr += str_replace2(SRs.substring(SRRi + SRt.length, SRs.length), SRt, SRu);
return SRRr;
}


Screenshot:

Arno.Nyhm
3 Apr 2009, 8:02 AM
goog idea and it works for me. but i can not personalize it very well. i can not change it with a german locale and not use the . as thousend seperator etc.



i would like to see more a way like this:

a more general Renderer at TextFields.
TextField.setRenderer(TextFieldRenderer myRenderer);

and also a parser if the user can input also in the rendered layout
TextField.setInputParser(TextFieldInputParser myInputParser);

and maybe also a mask for the input:
TextField.setInputMask(TextFieldInputMask myInputMask);



then everybody can extend this parsers, renders etc. to fit his needs.

mjlecomte
3 Apr 2009, 11:20 AM
That would probably have more potential if you wired it up as a plugin.

Arno.Nyhm
5 Apr 2009, 11:35 PM
because i have not so much experience with extjs plugins. i will now read the docs for plugins ( http://extjs.com/learn/Tutorial:Writing_Ext_2_Plugins )

anyhow, please can you point a little bit how is the way to implement this as an plugin?

Arno.Nyhm
6 Apr 2009, 3:15 AM
anyhow, please can you point a little bit how is the way to implement this as an plugin?

the question is more whats the best way to handle the visual part / the storing of the value / validation etc.

i see in the solution above the solution is to exchange always the values between the visual presentation and the real value, also for validation etc.

is this a good solution or are there other better solutions?

g13013
21 Apr 2009, 6:22 PM
the question is more whats the best way to handle the visual part / the storing of the value / validation etc.

i see in the solution above the solution is to exchange always the values between the visual presentation and the real value, also for validation etc.

is this a good solution or are there other better solutions?

My problem was clear, i had some datas that the user can change, but showing the raw data as it, it can be not well clear, but if rendered when shown, the user can see the result more easily. Imagine a number that should be stored as a float in data base like "12345678912.12", showing this to the user can be hard to read, but if rendered like this "12,345,678,912.12", this is more clear and easy to update in the database when removing the formating, also the render method can be used as a validator, in this case we are sure that the returned data to the server is always in the good format. if you tested the example you can see in the second field that a used a custom renderer that shows the value and the rest of payment subtracted from the total price in the first field, but the only value that is submitted is the value entered by the user.
http://www.extjs.com/forum/attachment.php?attachmentid=12540&d=1237339339

Still a problem that i want to fix, the possibility to always submit the raw value when submiting a formPanel, acctually i can do this by disabling the renderer with the setenableRenderer() method before submit, and restore it after, but it can be done by overriding the formPanel to do this automatically for all childs fields.


a more general Renderer at TextFields.
TextField.setRenderer(TextFieldRenderer myRenderer);

will add this as soon as possible

and also a parser if the user can input also in the rendered layout
TextField.setInputParser(TextFieldInputParser myInputParser);
and maybe also a mask for the input:
TextField.setInputMask(TextFieldInputMask myInputMask);

try to use one of parsers or mask plugins that you can find in this forum whith this field and post us the results

wwwtd
9 Sep 2010, 6:31 PM
It doesn't work in IE6 .error:this.el is not defined!

g13013
11 Sep 2010, 7:34 AM
It doesn't work in IE6 .error:this.el is not defined!
I never tested it on IE6, and I'll do it as soon as possible.