PDA

View Full Version : Using a json_encode response to dynamically build a form. Is it possible?



kevin-berry
11 May 2010, 1:47 PM
Hi,

I have a JSON object that gathers N fields, all of which have 9 attributes.

An example of the JSON returned from json_encode($form_fields) is:


[
["73", "field1", "text", "field1", "1", "lbl_regular", "form_text_area", "t" null],
["74", "field2", "text", "field2", "2", "lbl_regular", "form_text_area", "t", null]
. . . .
]I would like to use that response to build my Ext.FormPanel. right now I have it hardcoded as to what goes on the form, but I would like to generate the form based on that JSON output. So for example, that code would build the following:


var field1 =
{
xtype:'fieldset',
title: 'field1',
collapsible:true,
autoHeight:true,
items :[{
xtype:'textarea',
labelStyle: 'width:0px',
hideLabel:true,
name: 'meta_data',
id: 'meta_data',
height:75,
width:'100%',
autoScroll:true,
emptyText: 'Add comments here',
}]
};

var field2 =
{
xtype:'fieldset',
title: 'field1',
collapsible:true,
autoHeight:true,
items :[{
xtype:'textarea',
labelStyle: 'width:0px',
hideLabel:true,
name: 'meta_data',
id: 'meta_data',
height:75,
width:'100%',
autoScroll:true,
emptyText: 'Add comments here',
}]
};and it would insert them into the panel in the rank order (denoted by "1" and "2" respectively), so in the panel, they would appear:


var fp = new Ext.FormPanel
({
frame: true,
url:backendURL,
applyTo:'content',
items: [{
layout: 'column',
border: false,
},
field1, //rank "1"
field2, //rank "2"
],
buttons: default_buttons
}); //End actual form creation
Is this even possible? Basically, the JSON response tells me what elements I have on the form. It varies. I could have 2 textboxes with some labels on them, and five checkboxes (which I want to group into a checkboxgroup var. Or maybe another form has only 3 checkboxes. The database tells me this stuff and it's recorded in the JSON object, but I'm not sure how I'd use the object to dynamically build the form.

The previous implementation would gather the information from the database and make an XML doc out of it, which it would then transform to HTML. The idea is to avoid XML and HTML altogether and just render the form using ExtJS.

Does anyone have any ideas?

Thanks for your help!

Kevin

VinylFox
11 May 2010, 6:52 PM
Yes, it is 100% possible. You just need to loop through your array and create an array of config objects that Ext JS can use in the forms items config. Not terribly difficult at all.

PS. There is a trailing comma in your example 'field1' after the emptyText property.

kevin-berry
13 May 2010, 12:38 PM
So, as a follow up, this is probably a really dumb question, but I can't find the answer. Maybe I'm doing things the wrong way, but here's my problem:

I have PHP Form class which gets the form fields and returns them in a multidimensional array as PHP.

I do this:

<?php
$obj = json_encode($data);
?>

So now $obj is a json_encoded string that has my data. Peachy. How the heck do I move this variable over to my ExtJS namespace/app to read it from ExtJS (and not from PHP) and work with it from there?

At the end of the day I want to have an ExtJS function that says: if the JSON element "rank" is 1, this thing goes at the top of the form. etc etc.

I just don't know how to move the json_encoded php variable over to the javascript Ext application I have...

kevin-berry
14 May 2010, 4:02 PM
Hi again, so after playing with it some more, I learned a bit more about getting the json_encode over to ExtJS.

That said, I have the following JSON that is coming in from json_object.php:



[{"id":"84","name":"Communities","type":"label","label":"Communities","rank":"1","label_css_class":"lbl_regular","css_class":"","searchable":"t","node_type":null,"node_rank":null,"value":"2"},{"id":"85","name":"Community1","type":"checkbox","label":"Community1","rank":"2","label_css_class":"lbl_checkbox","css_class":"","searchable":"t","node_type":null,"node_rank":null,"value":"2"},{"id":"86","name":"Community2","type":"checkbox","label":"Community2","rank":"3","label_css_class":"lbl_checkbox","css_class":"","searchable":"t","node_type":null,"node_rank":null,"value":"2"},{"id":"87","name":"Community3","type":"checkbox","label":"Community3","rank":"4","label_css_class":"lbl_checkbox","css_class":"","searchable":"t","node_type":null,"node_rank":null,"value":"2"},{"id":"88","name":"Comments","type":"text","label":"Comments","rank":"5","label_css_class":"lbl_regular","css_class":"form_text_area","searchable":"t","node_type":null,"node_rank":null,"value":"3"},{"id":"89","name":"Some Other Field","type":"other","label":"Some Other Field","rank":"6","label_css_class":"lbl_regular","css_class":"","searchable":"t","node_type":null,"node_rank":null,"value":null}]


That said, I want to use that data to build my form. Basically, I want to parse it. If I see a checkbox, that goes in a specific form element.

So my first task is to use the data with Ext. So I make a JsonStore, right? Like so:



var dataStore = new Ext.data.JsonStore
({
url:'json_object.php',
idProperty: 'id',
fields: [
{name: 'id'},
{name: 'name'},
{name: 'type'},
{name: 'label'},
{name: 'rank'},
{name: 'label_css_class'},
{name: 'css_class'},
{name: 'searchable'},
{name: 'node_type'},
{name: 'node_rank'},
{name: 'value'}
]
});
dataStore.load();


Now, how can I make sure I am even storing the data right? I mean, I barely know what the JsonStore is for. I'm hoping it's just a place I can store that json_encoded object to parse and use when I need to.

Because in the end, I want to parse that, find all the checkboxes, and put them in to this:



var Group_Checker =
{
xtype:'fieldset',
title: 'Group Check',
collapsible: true,
autoHeight:true,
itemCls:'x-check-group-alt',
columns: 1,
store: dataStore,
items: [{
html: '<p class="bodyText">From the list below, select the groups ' +
'that you would like to allow to see this submission.</p>',

}, //checkbox_items
]
};


Can anyone give me some suggestions to prod me in the right direction to accomplish this, because I'm drowning in code here that I'm hardly understanding, and I don't quite know if I'm doing this properly, or *how* to do it.

Thanks!

Kevin

giri_sri_d
14 May 2010, 5:09 PM
Hello Kevin,

The task that you want to accomplish has to be completed in 4 steps.

1. Get the data from the server in json format, store it in some store
2. Start looping through that data
3. Create xtype
4. Add that to Form panel which you have created earlier.

As of now you already completed task 1 which is getting data from server to browser and you choose to store the data as json.
Now next task is to loop through the data, to do this task you can use "each" function in JsonStore class. (Please go through ext documentation)

so your code may look like



dataStore.each(myfunction)
and you define myfunction (This is where you are performing step 3) as follows.



function myfunction(record){
var tempObj = {
xtype:record.data.type, (You may have to check if this is the correct way to get the value from the record)
labelStyle: 'width:0px',
hideLabel:true,
name: record.data.Comments,
id: 'meta_data',
height:75,
width:'100%',
autoScroll:true,
emptyText: 'Add comments here'

}
formPanel.add(tempObj); (Step 5)
}
Try to use to firefox and fire bug that will help you to what's happening in myfunction if you set a debugger point.

kevin-berry
17 May 2010, 3:24 PM
Hi,

So I added the function and began molding it to suit my needs, however when I ran firebug, the debugger consumed the first curly brace ( { ) but then skipped the function entirely until it came to the curly brace of the next bit (even though I have a number of switch and if statements with opening braces in getRecords).



function getRecords(record)
{ <-- got to here
...
}

var Group_Check
{ <-- skipped right to here
...
}I currently have the function in the onReady portion of the .js file. Should it be in some other scope? (I read somewhere that Ext.onReady was for when the page was fully loaded, and this function is used to help load the page).

Secondly, in the example you provided, you pass a record variable to the function. Is this a keyword or something, because I have not defined anything as such in my code. How does the program know what a 'record' is when executing the getRecords function? From what I've read, records are created by specifying the 'fields' option in the JsonStore object.

Thanks for your help thus far. I think I'm making my way on track now, I'm just a bit confused about those two hiccups. :)

Kevin

VinylFox
20 Jun 2010, 3:19 AM
The record argument to the myfunction function is automatically passed in when you use the stores each method.

So dataStore.each(myfunction) says: call myfunction for each row in the store and pass in the current record as the argument.