ExtJS Having More Than One vType Applied To A Field
I have seen examples that use built-in vTypes and custom ones for a field, but never a custom and built-in vType together. For example, here is one I am currently using in my code which I have found from the Sencha examples and forums (many thanks):
//Add the additional 'advanced' VTypes
Ext.apply(Ext.form.VTypes, {
daterange : function(val, field) {
var date = field.parseDate(val);
if(!date){
return false;
}
if (field.startDateField) {
var start = Ext.getCmp(field.startDateField);
if (!start.maxValue || (date.getTime() != start.maxValue.getTime())) {
start.setMaxValue(date);
start.validate();
}
}
else if (field.endDateField) {
var end = Ext.getCmp(field.endDateField);
if (!end.minValue || (date.getTime() != end.minValue.getTime())) {
end.setMinValue(date);
end.validate();
}
}
/*
* Always return true since we're only using this vtype to set the
* min/max allowed values (these are tested for after the vtype test)
*/
return true;
}
});
Although this prevents the users from picking start and end dates that are not chronologically correct and quite nicely I might add, it overrides the default which checks that the user entered a date in correct format. Any way to have both the advanced vType and the default working at the same time? Now users can simply put letters in these fields or incorrect date formats and there answers will be submitted with no error checking! If something already exists for me to have multiple vTypes, I don't want to have to rewrite what is already written and reinvent the wheel.
Thanks for your time,
elshae
EDIT I am adding more of the form code by request. It's very long, so I have cut some of it out. I hope this will be enough...
this.captchaURL = "captcha/CaptchaSecurityImages.php?width=160&height=80&characters=4&t=";
var boxCaptcha = new Ext.BoxComponent({
columnWidth:.35,
autoEl: {
tag:'img'
,id: 'activateCodeImg'
,src:this.captchaURL+new Date().getTime()
}
});
boxCaptcha.on('render',function (){
var curr = Ext.get('activateCodeImg');
curr.on('click',this.onCapthaChange,this);
},this);
function onCapthaChange(){
var captchaURL = this.captchaURL;
var curr = Ext.get('activateCodeImg');
curr.slideOut('b', {callback: function(){
Ext.get( 'activateCodeImg' ).dom.src= captchaURL+new Date().getTime();
curr.slideIn('t');
}},this);
}
function getLang(){
// decode language passed in url
var locale = window.location.search
? Ext.urlDecode(window.location.search.substring(1))
: '';
return locale['lang'];
}//end getLang()
var form;
var lang = getLang();
var languageFile;
var localeFile;
if (lang == 'chn'){
languageFile = 'chinese.json';
localeFile = '../ext-3.3.1/src/locale/ext-lang-zh_CN.js';
}
else if (lang == 'eng'){
languageFile = 'english.json';
}
else if (lang == 'tib'){
languageFile = 'tibetan.json';
localeFile = '../ext-3.3.1/src/locale/ext-lang-zh_CN.js';
}
$.getScript(localeFile, function(){
var i18n = {};
$.getJSON(languageFile, i18n, function(data) { i18n = data.i18n;
Ext.BLANK_IMAGE_URL = '../ext-3.3.1/resources/images/default/s.gif';
//Add the additional 'advanced' VTypes
Ext.apply(Ext.form.VTypes, {
daterange : function(val, field) {
var date = field.parseDate(val);
if(!date){
return false;
}
if (field.startDateField) {
var start = Ext.getCmp(field.startDateField);
if (!start.maxValue || (date.getTime() != start.maxValue.getTime())) {
start.setMaxValue(date);
start.validate();
}
}
else if (field.endDateField) {
var end = Ext.getCmp(field.endDateField);
if (!end.minValue || (date.getTime() != end.minValue.getTime())) {
end.setMinValue(date);
end.validate();
}
}
/*
* Always return true since we're only using this vtype to set the
* min/max allowed values (these are tested for after the vtype test)
*/
return true;
}
});
Ext.onReady(function(){
Ext.QuickTips.init();
form = new Ext.form.FormPanel({
id: 'scholarshipForm',
//labelWidth: 200, // label settings here cascade unless overridden
url:'scholarshipSubmit.php',
method: 'POST',
frame:true,
layout: 'form',
title: i18n.Apply,
bodyStyle:'padding:10px 10px 0',
width: 610,
itemCls: 'formStyle',
items: [{
xtype:'fieldset',
checkboxToggle:false,
labelWidth: 200,
title: i18n.Student_Information,
autoHeight:true,
layout: 'form',
defaults: {width: 210},
collapsed: false,
items :[{
xtype: 'textfield',
fieldLabel: i18n.First_Name,
allowBlank:false,
name: 'first',
maskRe: /([a-zA-Z\s]+)$/,
msgTarget: 'side'
},{
xtype: 'textfield',
fieldLabel: i18n.Last_Name,
allowBlank:false,
msgTarget: 'side',
name: 'last',
maskRe: /([a-zA-Z\s]+)$/
},{
xtype: 'radiogroup',
fieldLabel: i18n.Gender,
name: 'gender',
columns: 1,
rows: 2,
allowBlank:false,
msgTarget: 'side',
items: [
{boxLabel: i18n.Male, name: 'sex', inputValue: i18n.Male},
{boxLabel: i18n.Female, name: 'sex', inputValue: i18n.Female}
]
},{
xtype: 'datefield',
fieldLabel: i18n.Date_of_Birth,
name: 'birthdate',
id: 'birthdate',
allowBlank:false,
msgTarget: 'side',
minValue: '02/24/1950',
maxValue: '02/24/1990',
//width: 210
},{
xtype: 'textfield',
fieldLabel: i18n.Place_of_Birth,
allowBlank:f开发者_C百科alse,
name: 'pob',
msgTarget: 'side'
},/*{
xtype: 'compositefield',
fieldLabel: 'Phone',
// anchor : '-20',
// anchor : null,
msgTarget: 'under',
items: [
{xtype: 'displayfield', value: '('},
{xtype: 'textfield', name: 'phone1', width: 29, allowBlank: false},
{xtype: 'displayfield', value: ')'},
{xtype: 'textfield', name: 'phone2', width: 29, allowBlank: false, margins: '0 5 0 0'},
{xtype: 'textfield', name: 'phone3', width: 48, allowBlank: false}
]
}*/{
xtype: 'textfield',
fieldLabel: i18n.Phone,
msgTarget: 'under',
name: 'phone',
allowBlank: false,
maskRe: /[0-9]/,
msgTarget: 'side'
},{
xtype: 'textfield',
fieldLabel: i18n.Email,
name: 'email',
vtype:'email',
msgTarget: 'under',
allowBlank: false
},{
xtype: 'fieldset',
fieldLabel: i18n.Instant_Messaging + '1 '.sup(),
name: 'IM',
labelWidth: 50,
defaults: {width: 120},
items:[{
xtype: 'textfield',
fieldLabel: 'MSN',
name: 'msn'
},{
xtype: 'textfield',
fieldLabel: 'Skype',
name: 'skype'
}]}
]
},{
xtype:'fieldset',
title: i18n.Previous_Schooling + '2 '.sup(),
collapsible: false,
autoHeight:true,
labelWidth: 150,
// defaultType: 'textfield',
items :[{xtype: 'tabpanel',
activeTab: 0,
width: 550,
defaults:{autoHeight:true, bodyStyle:'padding:10px'},
title:'Previous Schooling',
items :[{
title: i18n.School + ' 1',
layout:'form',
defaults: {width: 250},
items: [{
xtype: 'textfield',
fieldLabel: i18n.School_Name,
allowBlank:false,
//width: 250,
name: 'nos1',
msgTarget: 'side',
maskRe: /([a-zA-Z0-9\s]+)$/
},{
xtype:'fieldset',
title: i18n.Language_Medium + '3 '.sup(),
collapsible: false,
width: 400,
autoHeight:true,
labelWidth: 50,
items :[{
xtype: 'radiogroup',
fieldLabel: i18n.Tibetan,
name: 'Tibetan1',
labelWidth: 100,
columns: [110, 60, 70, 50],
rows: 1,
itemCls: 'x-check-group-alt',
width: 300,
//defaults: {width: 200},
allowBlank:false,
msgTarget: 'side',
//vertical: true,
// cls: 'languages',
items: [
{boxLabel: i18n.Mother_Tongue, name: 'tibetan1', inputValue: i18n.Mother_Tongue},
{boxLabel: i18n.Fluent, name: 'tibetan1', inputValue: i18n.Fluent},
{boxLabel: i18n.Scholar, name: 'tibetan1', inputValue: i18n.Scholar},
{boxLabel: i18n.None, name: 'tibetan1', inputValue: i18n.None}
]
},{
xtype: 'radiogroup',
fieldLabel: i18n.Chinese,
name: 'Chinese1',
columns: [110, 60, 70, 50],
rows: 1,
width: 300,
itemCls: 'x-check-group-alt',
allowBlank:false,
msgTarget: 'side',
items: [
{boxLabel: i18n.Mother_Tongue, name: 'chinese1', inputValue: i18n.Mother_Tongue},
{boxLabel: i18n.Fluent, name: 'chinese1', inputValue: i18n.Fluent},
{boxLabel: i18n.Scholar, name: 'chinese1', inputValue: i18n.Scholar},
{boxLabel: i18n.None, name: 'chinese1', inputValue: i18n.None}
]
},{
xtype: 'radiogroup',
fieldLabel: i18n.English,
name: 'English1',
width: 300,
columns: [110, 60, 70, 50],
rows: 1,
itemCls: 'x-check-group-alt',
allowBlank:false,
msgTarget: 'side',
items: [
{boxLabel: i18n.Mother_Tongue, name: 'english1', inputValue: i18n.Mother_Tongue},
{boxLabel: i18n.Fluent, name: 'english1', inputValue: i18n.Fluent},
{boxLabel: i18n.Scholar, name: 'english1', inputValue: i18n.Scholar},
{boxLabel: i18n.None, name: 'english1', inputValue: i18n.None}
]
},{
xtype: 'textfield',
fieldLabel: i18n.Other,
width: 250,
emptyText: i18n.Type_Lang,
itemCls: 'x-check-group-alt',
name: 'other1text',
id: 'other1text',
maskRe: /([a-zA-Z\s]+)$/
},{
xtype: 'radiogroup',
name: 'Other1',
columns: [110, 60, 70, 50],
rows: 1,
width: 300,
itemCls: 'x-check-group-alt',
msgTarget: 'side',
items: [
{boxLabel: i18n.Mother_Tongue, name: 'other1', inputValue: i18n.Mother_Tongue},
{boxLabel: i18n.Fluent, name: 'other1', inputValue: i18n.Fluent},
{boxLabel: i18n.Scholar, name: 'other1', inputValue: i18n.Scholar},
{boxLabel: i18n.None, name: 'other1', inputValue: i18n.None}
]
}]},{
xtype: 'datefield',
fieldLabel: i18n.Enrollment_Start,
allowBlank:false,
msgTarget: 'side',
name: 'enrollStart1',
id: 'enrollStart1',
vtype: 'daterange',
//width: 250,
endDateField: 'enrollEnd1'
// minValue: '02/24/1950'
},{
xtype: 'datefield',
fieldLabel: i18n.Enrollment_End,
allowBlank:false,
msgTarget: 'side',
name: 'enrollEnd1',
id: 'enrollEnd1',
vtype: 'daterange',
// width: 250,
startDateField: 'enrollStart1'
},{
xtype: 'textfield',
fieldLabel: i18n.Degree,
allowBlank:false,
name: 'degree1',
msgTarget: 'side',
//width: 250,
maskRe: /([a-zA-Z0-9\s]+)$/
}]},{
title: i18n.School + ' 2',
layout:'form',
defaults: {width: 250},
items: [{
xtype: 'textfield',
fieldLabel: i18n.School_Name,
// allowBlank:false,
name: 'nos2',
msgTarget: 'side',
maskRe: /([a-zA-Z0-9\s]+)$/
},{
...
...
...
buttons: [{
text: i18n.Submit,
handler: function(){
form.getForm().submit({
params:{lang: lang},
success: function(form, action) {
Ext.Msg.alert(i18n.Success, action.result.msg);
},
failure: function(form, action) {
switch (action.failureType) {
case Ext.form.Action.CLIENT_INVALID:
Ext.Msg.alert(i18n.Failure, i18n.Client_Error);
break;
case Ext.form.Action.CONNECT_FAILURE:
Ext.Msg.alert(i18n.Failure, i18n.Ajax_Error);
break;
case Ext.form.Action.SERVER_INVALID:
Ext.Msg.alert(i18n.Failure, action.result.msg);
}//end switch
}
});
}
},{
text: i18n.Reset,
handler: function(){
form.getForm().reset();
}
}]
});
form.render(document.body);
}); //End Ext.onReady
});//End $.getJSON
});//End $.getScript
If you look at the Ext JS source code, you will see that vType is additional validation to the fields and the default validations are executed. So, even if you have 'daterange' as a new vType, the existing date check is executed.
Now, regarding the user keying in the right format.. are you talking about the date format m/d/y and d/m/y ? the format property should take care of this. You can have format: 'm/d/Y' set to both of your datefields.
Regarding user keying in simple text instead of date, I was not able to replicate that! May you should show your form code along with your question. Have a look at this:
i looked for an similar issue. I found a solution, maybe it is also helpful for your issue.
You can give your field ann additional parameter (e.g. vTypes), declare this field as Array.
Than you are able to use it everywhere like this:
field.vtypes.forEach(function(vType)
{
vErrors[vType] = Ext.data.validations[vType]('', val);
});
You recive an array with Vtype and a boolean for error state ;)
精彩评论