4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
13 * @class Roo.form.BasicForm
14 * @extends Roo.util.Observable
15 * Supplies the functionality to do "actions" on forms and initialize Roo.form.Field types on existing markup.
17 * @param {String/HTMLElement/Roo.Element} el The form element or its id
18 * @param {Object} config Configuration options
20 Roo.form.BasicForm = function(el, config){
21 Roo.apply(this, config);
23 * The Roo.form.Field items in this form.
24 * @type MixedCollection
26 this.items = new Roo.util.MixedCollection(false, function(o){
27 return o.id || (o.id = Roo.id());
32 * Fires before any action is performed. Return false to cancel the action.
34 * @param {Action} action The action to be performed
39 * Fires when an action fails.
41 * @param {Action} action The action that failed
45 * @event actioncomplete
46 * Fires when an action is completed.
48 * @param {Action} action The action that completed
55 Roo.form.BasicForm.superclass.constructor.call(this);
58 Roo.extend(Roo.form.BasicForm, Roo.util.Observable, {
60 * @cfg {String} method
61 * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
64 * @cfg {DataReader} reader
65 * An Roo.data.DataReader (e.g. {@link Roo.data.XmlReader}) to be used to read data when executing "load" actions.
66 * This is optional as there is built-in support for processing JSON.
69 * @cfg {DataReader} errorReader
70 * An Roo.data.DataReader (e.g. {@link Roo.data.XmlReader}) to be used to read data when reading validation errors on "submit" actions.
71 * This is completely optional as there is built-in support for processing JSON.
75 * The URL to use for form actions if one isn't supplied in the action options.
78 * @cfg {Boolean} fileUpload
79 * Set to true if this form is a file upload.
82 * @cfg {Object} baseParams
83 * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
86 * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
94 * @cfg {Boolean} trackResetOnLoad If set to true, form.reset() resets to the last loaded
95 * or setValues() data instead of when the form was first created.
97 trackResetOnLoad : false,
100 * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
101 * element by passing it or its id or mask the form itself by passing in true.
104 waitMsgTarget : undefined,
107 initEl : function(el){
108 this.el = Roo.get(el);
109 this.id = this.el.id || Roo.id();
110 this.el.on('submit', this.onSubmit, this);
111 this.el.addClass('x-form');
115 onSubmit : function(e){
120 * Returns true if client-side validation on the form is successful.
123 isValid : function(){
125 this.items.each(function(f){
134 * Returns true if any fields in this form have changed since their original load.
137 isDirty : function(){
139 this.items.each(function(f){
149 * Performs a predefined action (submit or load) or custom actions you define on this form.
150 * @param {String} actionName The name of the action type
151 * @param {Object} options (optional) The options to pass to the action. All of the config options listed
152 * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
153 * accept other config options):
155 Property Type Description
156 ---------------- --------------- ----------------------------------------------------------------------------------
157 url String The url for the action (defaults to the form's url)
158 method String The form method to use (defaults to the form's method, or POST if not defined)
159 params String/Object The params to pass (defaults to the form's baseParams, or none if not defined)
160 clientValidation Boolean Applies to submit only. Pass true to call form.isValid() prior to posting to
161 validate the form on the client (defaults to false)
163 * @return {BasicForm} this
165 doAction : function(action, options){
166 if(typeof action == 'string'){
167 action = new Roo.form.Action.ACTION_TYPES[action](this, options);
169 if(this.fireEvent('beforeaction', this, action) !== false){
170 this.beforeAction(action);
171 action.run.defer(100, action);
177 * Shortcut to do a submit action.
178 * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
179 * @return {BasicForm} this
181 submit : function(options){
182 this.doAction('submit', options);
187 * Shortcut to do a load action.
188 * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
189 * @return {BasicForm} this
191 load : function(options){
192 this.doAction('load', options);
197 * Persists the values in this form into the passed Roo.data.Record object in a beginEdit/endEdit block.
198 * @param {Record} record The record to edit
199 * @return {BasicForm} this
201 updateRecord : function(record){
203 var fs = record.fields;
205 var field = this.findField(f.name);
207 record.set(f.name, field.getValue());
215 * Loads an Roo.data.Record into this form.
216 * @param {Record} record The record to load
217 * @return {BasicForm} this
219 loadRecord : function(record){
220 this.setValues(record.data);
225 beforeAction : function(action){
226 var o = action.options;
228 if(this.waitMsgTarget === true){
229 this.el.mask(o.waitMsg, 'x-mask-loading');
230 }else if(this.waitMsgTarget){
231 this.waitMsgTarget = Roo.get(this.waitMsgTarget);
232 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
234 Roo.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle || 'Please Wait...');
240 afterAction : function(action, success){
241 this.activeAction = null;
242 var o = action.options;
244 if(this.waitMsgTarget === true){
246 }else if(this.waitMsgTarget){
247 this.waitMsgTarget.unmask();
249 Roo.MessageBox.updateProgress(1);
250 Roo.MessageBox.hide();
257 Roo.callback(o.success, o.scope, [this, action]);
258 this.fireEvent('actioncomplete', this, action);
260 Roo.callback(o.failure, o.scope, [this, action]);
261 this.fireEvent('actionfailed', this, action);
266 * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
267 * @param {String} id The value to search for
270 findField : function(id){
271 var field = this.items.get(id);
273 this.items.each(function(f){
274 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
280 return field || null;
285 * Mark fields in this form invalid in bulk.
286 * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
287 * @return {BasicForm} this
289 markInvalid : function(errors){
290 if(errors instanceof Array){
291 for(var i = 0, len = errors.length; i < len; i++){
292 var fieldError = errors[i];
293 var f = this.findField(fieldError.id);
295 f.markInvalid(fieldError.msg);
301 if(typeof errors[id] != 'function' && (field = this.findField(id))){
302 field.markInvalid(errors[id]);
310 * Set values for fields in this form in bulk.
311 * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
312 * @return {BasicForm} this
314 setValues : function(values){
315 if(values instanceof Array){ // array of objects
316 for(var i = 0, len = values.length; i < len; i++){
318 var f = this.findField(v.id);
321 if(this.trackResetOnLoad){
322 f.originalValue = f.getValue();
326 }else{ // object hash
329 if(typeof values[id] != 'function' && (field = this.findField(id))){
331 if (field.setFromData &&
333 field.displayField &&
334 // combos' with local stores can
335 // be queried via setValue()
336 // to set their value..
337 (field.store && !field.store.isLocal)
341 sd[field.valueField] = typeof(values[field.hiddenName]) == 'undefined' ? '' : values[field.hiddenName];
342 sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
343 field.setFromData(sd);
346 field.setValue(values[id]);
350 if(this.trackResetOnLoad){
351 field.originalValue = field.getValue();
360 * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
361 * they are returned as an array.
362 * @param {Boolean} asString
365 getValues : function(asString){
366 var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
367 if(asString === true){
370 return Roo.urlDecode(fs);
374 * Clears all invalid messages in this form.
375 * @return {BasicForm} this
377 clearInvalid : function(){
378 this.items.each(function(f){
386 * @return {BasicForm} this
389 this.items.each(function(f){
396 * Add Roo.form components to this form.
397 * @param {Field} field1
398 * @param {Field} field2 (optional)
399 * @param {Field} etc (optional)
400 * @return {BasicForm} this
403 this.items.addAll(Array.prototype.slice.call(arguments, 0));
409 * Removes a field from the items collection (does NOT remove its markup).
410 * @param {Field} field
411 * @return {BasicForm} this
413 remove : function(field){
414 this.items.remove(field);
419 * Looks at the fields in this form, checks them for an id attribute,
420 * and calls applyTo on the existing dom element with that id.
421 * @return {BasicForm} this
424 this.items.each(function(f){
425 if(f.isFormField && !f.rendered && document.getElementById(f.id)){ // if the element exists
433 * Calls {@link Ext#apply} for all fields in this form with the passed object.
434 * @param {Object} values
435 * @return {BasicForm} this
437 applyToFields : function(o){
438 this.items.each(function(f){
445 * Calls {@link Ext#applyIf} for all field in this form with the passed object.
446 * @param {Object} values
447 * @return {BasicForm} this
449 applyIfToFields : function(o){
450 this.items.each(function(f){
458 Roo.BasicForm = Roo.form.BasicForm;