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,
101 * allFields - full list of fields.
107 * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
108 * element by passing it or its id or mask the form itself by passing in true.
111 waitMsgTarget : undefined,
114 initEl : function(el){
115 this.el = Roo.get(el);
116 this.id = this.el.id || Roo.id();
117 this.el.on('submit', this.onSubmit, this);
118 this.el.addClass('x-form');
122 onSubmit : function(e){
127 * Returns true if client-side validation on the form is successful.
130 isValid : function(){
132 this.items.each(function(f){
141 * Returns true if any fields in this form have changed since their original load.
144 isDirty : function(){
146 this.items.each(function(f){
156 * Performs a predefined action (submit or load) or custom actions you define on this form.
157 * @param {String} actionName The name of the action type
158 * @param {Object} options (optional) The options to pass to the action. All of the config options listed
159 * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
160 * accept other config options):
162 Property Type Description
163 ---------------- --------------- ----------------------------------------------------------------------------------
164 url String The url for the action (defaults to the form's url)
165 method String The form method to use (defaults to the form's method, or POST if not defined)
166 params String/Object The params to pass (defaults to the form's baseParams, or none if not defined)
167 clientValidation Boolean Applies to submit only. Pass true to call form.isValid() prior to posting to
168 validate the form on the client (defaults to false)
170 * @return {BasicForm} this
172 doAction : function(action, options){
173 if(typeof action == 'string'){
174 action = new Roo.form.Action.ACTION_TYPES[action](this, options);
176 if(this.fireEvent('beforeaction', this, action) !== false){
177 this.beforeAction(action);
178 action.run.defer(100, action);
184 * Shortcut to do a submit action.
185 * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
186 * @return {BasicForm} this
188 submit : function(options){
189 this.doAction('submit', options);
194 * Shortcut to do a load action.
195 * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
196 * @return {BasicForm} this
198 load : function(options){
199 this.doAction('load', options);
204 * Persists the values in this form into the passed Roo.data.Record object in a beginEdit/endEdit block.
205 * @param {Record} record The record to edit
206 * @return {BasicForm} this
208 updateRecord : function(record){
210 var fs = record.fields;
212 var field = this.findField(f.name);
214 record.set(f.name, field.getValue());
222 * Loads an Roo.data.Record into this form.
223 * @param {Record} record The record to load
224 * @return {BasicForm} this
226 loadRecord : function(record){
227 this.setValues(record.data);
232 beforeAction : function(action){
233 var o = action.options;
235 if(this.waitMsgTarget === true){
236 this.el.mask(o.waitMsg, 'x-mask-loading');
237 }else if(this.waitMsgTarget){
238 this.waitMsgTarget = Roo.get(this.waitMsgTarget);
239 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
241 Roo.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle || 'Please Wait...');
247 afterAction : function(action, success){
248 this.activeAction = null;
249 var o = action.options;
251 if(this.waitMsgTarget === true){
253 }else if(this.waitMsgTarget){
254 this.waitMsgTarget.unmask();
256 Roo.MessageBox.updateProgress(1);
257 Roo.MessageBox.hide();
264 Roo.callback(o.success, o.scope, [this, action]);
265 this.fireEvent('actioncomplete', this, action);
267 Roo.callback(o.failure, o.scope, [this, action]);
268 this.fireEvent('actionfailed', this, action);
273 * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
274 * @param {String} id The value to search for
277 findField : function(id){
278 var field = this.items.get(id);
280 this.items.each(function(f){
281 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
287 return field || null;
292 * Mark fields in this form invalid in bulk.
293 * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
294 * @return {BasicForm} this
296 markInvalid : function(errors){
297 if(errors instanceof Array){
298 for(var i = 0, len = errors.length; i < len; i++){
299 var fieldError = errors[i];
300 var f = this.findField(fieldError.id);
302 f.markInvalid(fieldError.msg);
308 if(typeof errors[id] != 'function' && (field = this.findField(id))){
309 field.markInvalid(errors[id]);
317 * Set values for fields in this form in bulk.
318 * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
319 * @return {BasicForm} this
321 setValues : function(values){
322 if(values instanceof Array){ // array of objects
323 for(var i = 0, len = values.length; i < len; i++){
325 var f = this.findField(v.id);
328 if(this.trackResetOnLoad){
329 f.originalValue = f.getValue();
333 }else{ // object hash
336 if(typeof values[id] != 'function' && (field = this.findField(id))){
338 if (field.setFromData &&
340 field.displayField &&
341 // combos' with local stores can
342 // be queried via setValue()
343 // to set their value..
344 (field.store && !field.store.isLocal)
348 sd[field.valueField] = typeof(values[field.hiddenName]) == 'undefined' ? '' : values[field.hiddenName];
349 sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
350 field.setFromData(sd);
353 field.setValue(values[id]);
357 if(this.trackResetOnLoad){
358 field.originalValue = field.getValue();
363 if (this.childForms) {
364 Roo.each(this.childForms, function (f) {
373 * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
374 * they are returned as an array.
375 * @param {Boolean} asString
378 getValues : function(asString){
379 if (this.childForms) {
380 // copy values from the child forms
381 Roo.each(this.childForms, function (f) {
383 Roo.each(f.allFields, function (e) {
384 if (e.name && e.getValue && this.findField(e.name)) {
385 this.findField(e.name).setValue(e.getValue());
394 var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
395 if(asString === true){
398 return Roo.urlDecode(fs);
402 * Clears all invalid messages in this form.
403 * @return {BasicForm} this
405 clearInvalid : function(){
406 this.items.each(function(f){
414 * @return {BasicForm} this
417 this.items.each(function(f){
420 if (this.childForms) {
421 Roo.each(this.childForms, function (f) {
430 * Add Roo.form components to this form.
431 * @param {Field} field1
432 * @param {Field} field2 (optional)
433 * @param {Field} etc (optional)
434 * @return {BasicForm} this
437 this.items.addAll(Array.prototype.slice.call(arguments, 0));
443 * Removes a field from the items collection (does NOT remove its markup).
444 * @param {Field} field
445 * @return {BasicForm} this
447 remove : function(field){
448 this.items.remove(field);
453 * Looks at the fields in this form, checks them for an id attribute,
454 * and calls applyTo on the existing dom element with that id.
455 * @return {BasicForm} this
458 this.items.each(function(f){
459 if(f.isFormField && !f.rendered && document.getElementById(f.id)){ // if the element exists
467 * Calls {@link Ext#apply} for all fields in this form with the passed object.
468 * @param {Object} values
469 * @return {BasicForm} this
471 applyToFields : function(o){
472 this.items.each(function(f){
479 * Calls {@link Ext#applyIf} for all field in this form with the passed object.
480 * @param {Object} values
481 * @return {BasicForm} this
483 applyIfToFields : function(o){
484 this.items.each(function(f){
492 Roo.BasicForm = Roo.form.BasicForm;