PDA

View Full Version : How to load a nested model into a single form



STi88
4 Oct 2012, 8:31 AM
I've created a script to dynamically generate a form, but I'm having problem loading the data of the nested model. I've tried loading the whole record and I've tried loading each sub store, but neither works.
I've through about using form.load(), but from my understanding that requires a proxy connection and also require to store json data inside a 'data' array.

I'm having problem loading the store data into form fields. For static forms I normally use loadRecord to load the nested model into a form, but in this case all the fields are nested in their own little model, so would there be a way to load each nested model value into their own field with loadRecord?
The HeaderModel stores field set information.
The purpose of ColumnModel is to create the container that will surround a set of fields, for styling purpose. It simply creates two columns of fields.
The FieldModel stores the field specific attributes and data.

Does anyone have any suggestions on how might I approach this problem?

Here's the code:




<div id="view-@pageSpecificVar" class="grid-container even"></div><div id="button"></div>
<script>

Ext.define('HeaderForm', {
extend: 'Ext.form.Panel',
initComponent: function () {
var me = this;
Ext.applyIf(me, {
id: Ext.id(),
defaultType: 'textfield'
});
me.callParent(arguments);
}
});

// Define our data model
Ext.define('HeaderModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'HeaderSequence', type: 'int'}
],
hasMany:[
{ name: 'Columns', model: 'ColumnModel' }
],
proxy: {
type: 'ajax',
actionMethods: { create: 'POST', read: 'GET', update: 'POST', destroy: 'POST' },
url: '@Url.Content("~/Test/Header")',
timeout: 1200000,
},
});

Ext.define('ColumnModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'ColumnWidth', type: 'float'}
],
hasMany:[
{ name: 'Fields', model: 'FieldModel'}
],
belongsTo: 'HeaderModel'
});

Ext.define('FieldModel', {
extend: 'Ext.data.Model',
fields: [
{ name: 'XType', type: 'string'},
{ name: 'FieldLabel', type: 'string'},
{ name: 'Name', type: 'string'},
{ name: 'Data', type: 'string'},
{ name: 'FieldSpecify', type: 'bool'}
],
belongsTo: 'ColumnModel'
});

var store = Ext.create('Ext.data.Store', {
storeId: 'HeaderStore',
model: 'HeaderModel',
autoDestroy: true,
listeners: {
load: function (result, records, successful, eOpts) {
//console.log(result);
var form = dynamicForm(records[0]);
form.add(submitButton);
form.render('view-@pageSpecificVar');
}
}
});

store.load();

var dynamicForm = function(record) {

var form = new HeaderForm();
var columnContainer = new Ext.widget({
xtype: 'container',
layout: 'column'
});
var formItems = new Ext.util.MixedCollection();

Ext.each(record.ColumnsStore.data.items, function(item) {

Ext.iterate(item.data, function (key, value) {


var fieldContainer = new Ext.widget({
xtype: 'container',
columnWidth: value
});

Ext.each(item.FieldsStore.data.items, function(item) {
if(item.data["FieldSpecify"]) {
fieldContainer.add(new Ext.widget({
xtype: item.data["XType"],
fieldLabel: item.data["FieldLabel"],
name: item.data["Name"],
//value: item.data["Name"]
}));
}
}, this);

columnContainer.add(fieldContainer);

}, this);

}, this);

formItems.add(columnContainer);

form.add(formItems.items);

Ext.each(record.ColumnsStore.data.items, function(item) {
Ext.each(item.FieldsStore.data.items, function(fields) {
form.loadRecord(fields);
});
});

//form.loadRecord(record);

return form;
};

var submitButton = new Ext.widget({
xtype: 'toolbar',
dock: 'bottom',
items:[{
xtype: 'button',
text: 'Save',
handler: function(button) {
var basic = button.up('form').form;
basic.updateRecord(basic.getRecord());
var store = Ext.StoreMgr.get('HeaderStore');
store.each(function(record) {
record.dirty = true;
});
store.sync();
}
}]
});
</script>



Here's a sample of the json response object:



{
"HeaderSequence":1,
"Columns":[{
"ColumnWidth":0.5,"Fields":[
{"XType":"textfield","FieldLabel":"FieldA","Name":"NameA","Data":"A","FieldSpecify":true},
{"XType":"textfield","FieldLabel":"FieldB","Name":"NameA","Data":"B","FieldSpecify":true}]
},{
"ColumnWidth":0.5,"Fields":[
{"XType":"textfield","FieldLabel":"FieldA2","Name":"NameA2","Data":"A2","FieldSpecify":true},
{"XType":"textfield","FieldLabel":"FieldB2","Name":"NameB2","Data":"B2","FieldSpecify":true}]
}
]}

Thanks

mitchellsimoens
10 Oct 2012, 9:19 AM
Can you resolve the record that you need to use?

STi88
10 Oct 2012, 9:41 AM
I've figure out how to load the nested model into the form. We can't simply use load or loadRecord, as by default that method tries to get a model's data and iterate through the data object and call setValues.
What I have to do is manually get the basic form element and call setValues myself to assign the values.


// loop through each field store to load the data into the form by field id
Ext.each(record.ColumnsStore.data.items, function(item) {
Ext.each(item.FieldsStore.data.items, function(fields) {
form.getForm().setValues([{ id: fields.data['Id'], value: fields.data['DisplayName'] }]);
});
});

To Follow up with that, a custom submit handler needs to be put in place as well. Which loops through the store and sets the submitted value to store before sync the store.


// define form submit button
var submitButton = new Ext.widget({
xtype: 'toolbar',
dock: 'bottom',
items:[{
xtype: 'button',
text: 'Save',
handler: function(button) {
// get basic form for button
var basic = button.up('form').form;
// get form submit values
var formSubmitValues = basic.getValues();
// get header store
var store = Ext.StoreMgr.get('HeaderStore');
// loop through each field store and update the data values by id from the form
store.each(function(record) {
Ext.each(record.ColumnsStore.data.items, function(item) {
Ext.each(item.FieldsStore.data.items, function(fields) {
fields.data['Data'] = formSubmitValues[fields.data['Id']];
});
});
// mark the record as dirty to be sync
record.dirty = true;
});
// sync store object with the database
store.sync();
}
}]
});