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 * childForms - used for multi-tab forms
107 * allFields - full list of fields.
113 * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
114 * element by passing it or its id or mask the form itself by passing in true.
117 waitMsgTarget : undefined,
120 initEl : function(el){
121 this.el = Roo.get(el);
122 this.id = this.el.id || Roo.id();
123 this.el.on('submit', this.onSubmit, this);
124 this.el.addClass('x-form');
128 onSubmit : function(e){
133 * Returns true if client-side validation on the form is successful.
136 isValid : function(){
138 this.items.each(function(f){
147 * Returns true if any fields in this form have changed since their original load.
150 isDirty : function(){
152 this.items.each(function(f){
162 * Performs a predefined action (submit or load) or custom actions you define on this form.
163 * @param {String} actionName The name of the action type
164 * @param {Object} options (optional) The options to pass to the action. All of the config options listed
165 * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
166 * accept other config options):
168 Property Type Description
169 ---------------- --------------- ----------------------------------------------------------------------------------
170 url String The url for the action (defaults to the form's url)
171 method String The form method to use (defaults to the form's method, or POST if not defined)
172 params String/Object The params to pass (defaults to the form's baseParams, or none if not defined)
173 clientValidation Boolean Applies to submit only. Pass true to call form.isValid() prior to posting to
174 validate the form on the client (defaults to false)
176 * @return {BasicForm} this
178 doAction : function(action, options){
179 if(typeof action == 'string'){
180 action = new Roo.form.Action.ACTION_TYPES[action](this, options);
182 if(this.fireEvent('beforeaction', this, action) !== false){
183 this.beforeAction(action);
184 action.run.defer(100, action);
190 * Shortcut to do a submit action.
191 * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
192 * @return {BasicForm} this
194 submit : function(options){
195 this.doAction('submit', options);
200 * Shortcut to do a load action.
201 * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
202 * @return {BasicForm} this
204 load : function(options){
205 this.doAction('load', options);
210 * Persists the values in this form into the passed Roo.data.Record object in a beginEdit/endEdit block.
211 * @param {Record} record The record to edit
212 * @return {BasicForm} this
214 updateRecord : function(record){
216 var fs = record.fields;
218 var field = this.findField(f.name);
220 record.set(f.name, field.getValue());
228 * Loads an Roo.data.Record into this form.
229 * @param {Record} record The record to load
230 * @return {BasicForm} this
232 loadRecord : function(record){
233 this.setValues(record.data);
238 beforeAction : function(action){
239 var o = action.options;
241 if(this.waitMsgTarget === true){
242 this.el.mask(o.waitMsg, 'x-mask-loading');
243 }else if(this.waitMsgTarget){
244 this.waitMsgTarget = Roo.get(this.waitMsgTarget);
245 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
247 Roo.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle || 'Please Wait...');
253 afterAction : function(action, success){
254 this.activeAction = null;
255 var o = action.options;
257 if(this.waitMsgTarget === true){
259 }else if(this.waitMsgTarget){
260 this.waitMsgTarget.unmask();
262 Roo.MessageBox.updateProgress(1);
263 Roo.MessageBox.hide();
270 Roo.callback(o.success, o.scope, [this, action]);
271 this.fireEvent('actioncomplete', this, action);
273 Roo.callback(o.failure, o.scope, [this, action]);
274 this.fireEvent('actionfailed', this, action);
279 * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
280 * @param {String} id The value to search for
283 findField : function(id){
284 var field = this.items.get(id);
286 this.items.each(function(f){
287 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
293 return field || null;
298 * Mark fields in this form invalid in bulk.
299 * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
300 * @return {BasicForm} this
302 markInvalid : function(errors){
303 if(errors instanceof Array){
304 for(var i = 0, len = errors.length; i < len; i++){
305 var fieldError = errors[i];
306 var f = this.findField(fieldError.id);
308 f.markInvalid(fieldError.msg);
314 if(typeof errors[id] != 'function' && (field = this.findField(id))){
315 field.markInvalid(errors[id]);
323 * Set values for fields in this form in bulk.
324 * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
325 * @return {BasicForm} this
327 setValues : function(values){
328 if(values instanceof Array){ // array of objects
329 for(var i = 0, len = values.length; i < len; i++){
331 var f = this.findField(v.id);
334 if(this.trackResetOnLoad){
335 f.originalValue = f.getValue();
339 }else{ // object hash
342 if(typeof values[id] != 'function' && (field = this.findField(id))){
344 if (field.setFromData &&
346 field.displayField &&
347 // combos' with local stores can
348 // be queried via setValue()
349 // to set their value..
350 (field.store && !field.store.isLocal)
354 sd[field.valueField] = typeof(values[field.hiddenName]) == 'undefined' ? '' : values[field.hiddenName];
355 sd[field.displayField] = typeof(values[field.name]) == 'undefined' ? '' : values[field.name];
356 field.setFromData(sd);
359 field.setValue(values[id]);
363 if(this.trackResetOnLoad){
364 field.originalValue = field.getValue();
369 if (this.childForms) {
370 Roo.each(this.childForms, function (f) {
379 * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
380 * they are returned as an array.
381 * @param {Boolean} asString
384 getValues : function(asString){
385 if (this.childForms) {
386 // copy values from the child forms
387 Roo.each(this.childForms, function (f) {
389 Roo.each(f.allFields, function (e) {
390 if (e.name && e.getValue && this.findField(e.name)) {
391 this.findField(e.name).setValue(e.getValue());
400 var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
401 if(asString === true){
404 return Roo.urlDecode(fs);
408 * Clears all invalid messages in this form.
409 * @return {BasicForm} this
411 clearInvalid : function(){
412 this.items.each(function(f){
416 Roo.each(this.childForms || [], function (f) {
426 * @return {BasicForm} this
429 this.items.each(function(f){
433 Roo.each(this.childForms || [], function (f) {
442 * Add Roo.form components to this form.
443 * @param {Field} field1
444 * @param {Field} field2 (optional)
445 * @param {Field} etc (optional)
446 * @return {BasicForm} this
449 this.items.addAll(Array.prototype.slice.call(arguments, 0));
455 * Removes a field from the items collection (does NOT remove its markup).
456 * @param {Field} field
457 * @return {BasicForm} this
459 remove : function(field){
460 this.items.remove(field);
465 * Looks at the fields in this form, checks them for an id attribute,
466 * and calls applyTo on the existing dom element with that id.
467 * @return {BasicForm} this
470 this.items.each(function(f){
471 if(f.isFormField && !f.rendered && document.getElementById(f.id)){ // if the element exists
479 * Calls {@link Ext#apply} for all fields in this form with the passed object.
480 * @param {Object} values
481 * @return {BasicForm} this
483 applyToFields : function(o){
484 this.items.each(function(f){
491 * Calls {@link Ext#applyIf} for all field in this form with the passed object.
492 * @param {Object} values
493 * @return {BasicForm} this
495 applyIfToFields : function(o){
496 this.items.each(function(f){
504 Roo.BasicForm = Roo.form.BasicForm;