X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/0494b8d9b9bb03ab6c22b34dae81261e3cd7e3e6..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/examples/form/registration.js diff --git a/examples/form/registration.js b/examples/form/registration.js new file mode 100644 index 00000000..12bd096e --- /dev/null +++ b/examples/form/registration.js @@ -0,0 +1,237 @@ +Ext.require([ + 'Ext.form.*', + 'Ext.Img', + 'Ext.tip.QuickTipManager' +]); + +Ext.onReady(function() { + Ext.tip.QuickTipManager.init(); + + var formPanel = Ext.widget('form', { + renderTo: Ext.getBody(), + frame: true, + width: 350, + bodyPadding: 10, + bodyBorder: true, + title: 'Account Registration', + + defaults: { + anchor: '100%' + }, + fieldDefaults: { + labelAlign: 'left', + msgTarget: 'none', + invalidCls: '' //unset the invalidCls so individual fields do not get styled as invalid + }, + + /* + * Listen for validity change on the entire form and update the combined error icon + */ + listeners: { + fieldvaliditychange: function() { + this.updateErrorState(); + }, + fielderrorchange: function() { + this.updateErrorState(); + } + }, + + updateErrorState: function() { + var me = this, + errorCmp, fields, errors; + + if (me.hasBeenDirty || me.getForm().isDirty()) { //prevents showing global error when form first loads + errorCmp = me.down('#formErrorState'); + fields = me.getForm().getFields(); + errors = []; + fields.each(function(field) { + Ext.Array.forEach(field.getErrors(), function(error) { + errors.push({name: field.getFieldLabel(), error: error}); + }); + }); + errorCmp.setErrors(errors); + me.hasBeenDirty = true; + } + }, + + items: [{ + xtype: 'textfield', + name: 'username', + fieldLabel: 'User Name', + allowBlank: false, + minLength: 6 + }, { + xtype: 'textfield', + name: 'email', + fieldLabel: 'Email Address', + vtype: 'email', + allowBlank: false + }, { + xtype: 'textfield', + name: 'password1', + fieldLabel: 'Password', + inputType: 'password', + style: 'margin-top:15px', + allowBlank: false, + minLength: 8 + }, { + xtype: 'textfield', + name: 'password2', + fieldLabel: 'Repeat Password', + inputType: 'password', + allowBlank: false, + /** + * Custom validator implementation - checks that the value matches what was entered into + * the password1 field. + */ + validator: function(value) { + var password1 = this.previousSibling('[name=password1]'); + return (value === password1.getValue()) ? true : 'Passwords do not match.' + } + }, + + /* + * Terms of Use acceptance checkbox. Two things are special about this: + * 1) The boxLabel contains a HTML link to the Terms of Use page; a special click listener opens this + * page in a modal Ext window for convenient viewing, and the Decline and Accept buttons in the window + * update the checkbox's state automatically. + * 2) This checkbox is required, i.e. the form will not be able to be submitted unless the user has + * checked the box. Ext does not have this type of validation built in for checkboxes, so we add a + * custom getErrors method implementation. + */ + { + xtype: 'checkboxfield', + name: 'acceptTerms', + fieldLabel: 'Terms of Use', + hideLabel: true, + style: 'margin-top:15px', + boxLabel: 'I have read and accept the Terms of Use.', + + // Listener to open the Terms of Use page link in a modal window + listeners: { + click: { + element: 'boxLabelEl', + fn: function(e) { + var target = e.getTarget('.terms'), + win; + if (target) { + win = Ext.widget('window', { + title: 'Terms of Use', + modal: true, + html: '', + buttons: [{ + text: 'Decline', + handler: function() { + this.up('window').close(); + formPanel.down('[name=acceptTerms]').setValue(false); + } + }, { + text: 'Accept', + handler: function() { + this.up('window').close(); + formPanel.down('[name=acceptTerms]').setValue(true); + } + }] + }); + win.show(); + e.preventDefault(); + } + } + } + }, + + // Custom validation logic - requires the checkbox to be checked + getErrors: function() { + return this.getValue() ? [] : ['You must accept the Terms of Use'] + } + }], + + dockedItems: [{ + xtype: 'container', + dock: 'bottom', + layout: { + type: 'hbox', + align: 'middle' + }, + padding: '10 10 5', + + items: [{ + xtype: 'component', + id: 'formErrorState', + baseCls: 'form-error-state', + flex: 1, + validText: 'Form is valid', + invalidText: 'Form has errors', + tipTpl: Ext.create('Ext.XTemplate', ''), + + getTip: function() { + var tip = this.tip; + if (!tip) { + tip = this.tip = Ext.widget('tooltip', { + target: this.el, + title: 'Error Details:', + autoHide: false, + anchor: 'top', + mouseOffset: [-11, -2], + closable: true, + constrainPosition: false, + cls: 'errors-tip' + }); + tip.show(); + } + return tip; + }, + + setErrors: function(errors) { + var me = this, + baseCls = me.baseCls, + tip = me.getTip(); + + errors = Ext.Array.from(errors); + + // Update CSS class and tooltip content + if (errors.length) { + me.addCls(baseCls + '-invalid'); + me.removeCls(baseCls + '-valid'); + me.update(me.invalidText); + tip.setDisabled(false); + tip.update(me.tipTpl.apply(errors)); + } else { + me.addCls(baseCls + '-valid'); + me.removeCls(baseCls + '-invalid'); + me.update(me.validText); + tip.setDisabled(true); + tip.hide(); + } + } + }, { + xtype: 'button', + formBind: true, + disabled: true, + text: 'Submit Registration', + width: 140, + handler: function() { + var form = this.up('form').getForm(); + + /* Normally we would submit the form to the server here and handle the response... + form.submit({ + clientValidation: true, + url: 'register.php', + success: function(form, action) { + //... + }, + failure: function(form, action) { + //... + } + }); + */ + + if (form.isValid()) { + Ext.Msg.alert('Submitted Values', form.getValues(true)); + } + } + }] + }] + }); + +});