-
10 May 2011 12:09 AM #1
Submit form elements that are inside a dataview
Submit form elements that are inside a dataview
For an app I'm building I have to manually hack together some elements Sencha offers, but I'm now running into a problem.
With some help of other forum posts I have been able to set up a panel (dataview), in which form elements are rendered inside an XTemplate (code below).
All good and well, until the point that the user will want to submit the input data. As I'm forced to use a dataview (formpanel doesn't allow xtemplate usage per row), I can't just use the standard submit function(s). The dataview.submit functions doesn't exist obviously.
To give you an idea of why I need to combine Xtemplate and Form elements I have attached a screenshot of the current situation (I need to be able to 'design' the form).

For the code of the Form/Template:
-> (For debugging reasons I have attached a handler to every single button in the template to all act like a submit button ( verwerkForm(); ).PHP Code:'<div id="form-container">',
'<tpl for=".">',
'<div id="vraag-container">',
'<div id="id">',
'<div id="nummer" class="{[this.listClasses(xindex, xcount)]}">',
'<p>{id}</p>',
'</div>',
'</div>',
'<div id="inhoud">',
'<div id="vraag">',
'<p>{vraag}</p>',
'</div>',
'<div id="input">',
'<div id="element">',
'{[ this.addCmp({ xtype: values.antwoordtype, id:values.id }) ]}',
'</div>',
'<div id="label">',
'<tpl if="antwoordtype==\'sliderfield\'">',
'<p>Label</p>',
'</tpl>',
'</div>',
'<div id="foto">',
'<div id="toggle">',
'{[ this.addCmp({ xtype:"togglefield" }) ]}',
'</div>',
'<div id="text">',
'{[ this.addCmp({ xtype:"textfield", style: "margin-top: 5px; border: 1px solid grey;" }) ]}',
'</div>',
'</div>',
'<div id="opmerking">',
'{[ this.addCmp({ ui: "action", text: "Opmerking", xtype:"button", height: 30, style: "margin-top: 8px", handler: function() { verwerkForm(); } }) ]}',
'</div>',
'</div>',
'</div>',
'</div>',
'</tpl>',
'</div>',
What I have tried so far is:
1) Force <form> tags around the TPL Loop with a certain ID ('myForm'). When the user presses any of the buttons this code executed:
This submit functions works, yet it just passes the raw div data of the Xtemplate. So I don't recieve any input values, just all the ID's of the div's etc.PHP Code:myForm.submit({
url: "success.json"
});
2
Attach an ID to the input element (for example the slider). Then when the user presses a button I fetch the element(s) (getCmp).
This seems to work, but ID's won't work in the long run (there are multiple sliders so I would have to use a class or dynamic ID).
====
So for the main question.
-> How do I get the values of the various form elements inside my Dataview? Can I somehow loop through al the form/input/slider elements inside a Dataview (?) then merge it and post it with a new Ajax Request?
Or if anyone one knows an easier alternative (using a xtemplate with a form) I would also love to hear about it.
-
10 May 2011 2:52 AM #2
A little update, I have puzzled some more and have come up with a solution to get al the Slider values.
The form is largly the same as in the previous post but with one big difference -> Every slider now gets his own unique ID ("slider" + id). The ID comes from the datamodel that the stores uses. So I have now got a slider1, slider2, slider3, etc.
Within this function that is called by the handler of the button I now do the following;
-> Make an array that will be used to store the slider dataPHP Code:
sliderData = new Array();
for(var i = 0; i < 10; i++) {
sliderData[i] = Ext.getCmp('slider' + i).getValue();
}
console.log(sliderData);
Ext.Ajax.request({
url: 'php/json.php',
method: 'post',
params: { sliders: Ext.encode(sliderData) }
});
-> Loop through sliders (now still static) and collect the value's (getCmp to get it, and then getValue to get the value)
-> Start a new AJAX request
-> Fill the param of the Ajax request with the sliderData-array. Mind you, Ext.encode is needed to send the array as a real array.
There is still some work left (slider, toggles, textinputs) but I'm getting somewhere now :-).
Still, if anyone knows a faster solution to what I'm doing right now, please say so!
-
10 May 2011 5:39 AM #3Sencha - Senior Forum Manager
- Join Date
- Mar 2007
- Location
- St. Louis, MO
- Posts
- 34,118
- Vote Rating
- 453
What does you addCmp method look like in your XTemplate?
Mitchell Simoens @SenchaMitch
Sencha Inc, Senior Forum Manager
________________
http://www.JSONPLint.com - Source to lint your JSONP!
Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
https://github.com/mitchellsimoens
Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/
Need more help with your app? Hire Sencha Services services@sencha.com
Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is almost in print!
When posting code, please use BBCode's CODE tags.
-
10 May 2011 5:47 AM #4
I have got several, but the only difference everytime is the xtype. The slider one looks like this:
It uses an override function that I found in another topic;PHP Code:'{[ this.addCmp({ xtype: values.antwoordtype, value: 3, minValue: 1, maxValue: 5, id: "slider" + values.id }) ]}',
PHP Code:
(function () {
var originalOverwrite = Ext.XTemplate.prototype.overwrite;
Ext.override(Ext.XTemplate, {
overwrite: function () {
//execute the base overwrite method
originalOverwrite.apply(this, arguments);
//then, render any components that addCmp might have added
while (this.templateComponents.length > 0) {
var el = this.templateComponents.shift();
if (Ext.get(el.renderTo) != null) {
var newel = new Ext.create(el);
}
}
},
//an array to store the initialconfigs of the components-to-be
templateComponents:[],
templateIdCount:0,
//Pushes an initialConfig to the array so that
//a component can be later created and rendered.
//It also generates a div container for the component
//with a random id if no id was provided
addCmp: function (initConfig) {
var wrapperId = "ext-comp-wrapper-";
if (initConfig.id != void (0)) {
wrapperId += initConfig.id;
} else {
//wrapperId += Math.random().toString().replace(".", "");
wrapperId += (this.templateIdCount++).toString() + Math.random().toString().replace(".", "");
}
initConfig.renderTo = wrapperId;
this.templateComponents.push(initConfig);
//return '<div id="' + wrapperId + '"' + (initConfig.width == void(0) ? '' : ' style="width:'+ initConfig.width +'px"') + '></div>';
return '<div id="' + wrapperId + '" class="y-wrapper"></div>';
},
addCmpTo: function (container, initConfig, collection) {
if (collection == void(0)){
this.addCmpTo(container, initConfig, this.templateComponents);
} else {
if (collection.length > 0){
for (var i=0; i<collection.length; i++){
if (collection[i].id == container){
if (collection[i].items == void(0)){
collection[i].items = [];
}
collection[i].items.push(initConfig);
break;
}
if (collection[i].items != void(0)){
this.addCmpTo(container, initConfig, collection[i].items);
}
}
}
}
return;
}
});
})();
-
10 May 2011 6:14 AM #5Sencha - Senior Forum Manager
- Join Date
- Mar 2007
- Location
- St. Louis, MO
- Posts
- 34,118
- Vote Rating
- 453
Can't spend too much time right now but here is something that is going in the right direction...
Code:var originalOverwrite = Ext.XTemplate.prototype.overwrite; Ext.override(Ext.XTemplate, { overwrite: function () { //execute the base overwrite method originalOverwrite.apply(this, arguments); //then, render any components that addCmp might have added while (this.templateComponents.length > 0) { var el = this.templateComponents.shift(); if (Ext.get(el.renderTo) != null) { var newel = new Ext.create(el); } } }, //an array to store the initialconfigs of the components-to-be templateComponents:[], templateIdCount:0, //Pushes an initialConfig to the array so that //a component can be later created and rendered. //It also generates a div container for the component //with a random id if no id was provided addCmp: function (initConfig) { var me = this, wrapperId = "ext-comp-wrapper-", afterRenderFunc = Ext.emptyFn; if (initConfig.id != void (0)) { wrapperId += initConfig.id; } else { //wrapperId += Math.random().toString().replace(".", ""); wrapperId += (this.templateIdCount++).toString() + Math.random().toString().replace(".", ""); } initConfig.renderTo = wrapperId; me.items = new Ext.util.MixedCollection(); if (!Ext.isDefined(initConfig.listeners)) { initConfig.listeners = {}; } else { if (Ext.isDefined(initConfig.listeners.afterrender)) { afterRenderFunc = initConfig.listeners.afterrender; } } Ext.apply(initConfig.listeners, { afterrender : function(cmp) { me.items.add(wrapperId, cmp); afterRenderFunc(cmp); } }); me.templateComponents.push(initConfig); return '<div id="' + wrapperId + '" class="y-wrapper"></div>'; }, addCmpTo: function (container, initConfig, collection) { if (collection == void(0)){ this.addCmpTo(container, initConfig, this.templateComponents); } else { if (collection.length > 0){ for (var i=0; i<collection.length; i++){ if (collection[i].id == container){ if (collection[i].items == void(0)){ collection[i].items = []; } collection[i].items.push(initConfig); break; } if (collection[i].items != void(0)){ this.addCmpTo(container, initConfig, collection[i].items); } } } } return; } }); Ext.regModel('TestModel', { fields : ['name'] }); var store = new Ext.data.Store({ model : 'TestModel', data : [ { name : 'Mitchell Simoens' } ] }); var btnHandler = function(btn) { var me = this, items = me.items, values = {}; items.each(function(cmp) { if (Ext.isFunction(cmp.getValue)) { values[cmp.name] = cmp.getValue(); } }); console.log(values); }; var dataview = new Ext.DataView({ renderTo : Ext.getBody(), store : store, itemSelector : 'div.testRow', tpl : new Ext.XTemplate( '<tpl for=".">', '<div class="testRow">', '{[ this.addCmp({ xtype : "textfield", placeHolder : "Test", name : "TestOne" }) ]}', '{[ this.addCmp({ xtype : "button", text : "Test", scope : this, handler : function() { this.btnHandler() }, listeners : { afterrender: function() { console.log("button rendered") } } }) ]}', '</div>', '</tpl>', { dataview : dataview, btnHandler : btnHandler } ) });Mitchell Simoens @SenchaMitch
Sencha Inc, Senior Forum Manager
________________
http://www.JSONPLint.com - Source to lint your JSONP!
Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
https://github.com/mitchellsimoens
Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/
Need more help with your app? Hire Sencha Services services@sencha.com
Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is almost in print!
When posting code, please use BBCode's CODE tags.
-
10 May 2011 6:24 AM #6
Wow, thanks, looks good! (Definitely like a step in the right direction).
I'll adapt the code to my 'app' tonight (GMT+1) and will post my results!
-
11 May 2011 12:00 AM #7
Mitchell,
I have adapted your code to my application and it works!
As my dataview uses a seperate Xtemplate I had to alter the code a bit, but when I press the submit button all the values of the different components are returned (and stored in the object).
I did make a little adjustment to the button handler, as I use (dynamic) ID's on the components (and no name's currently) I changed the handler to the following;
I think your solution (dynamically looping through the available components) is studier on the long term than my own hack and slash solution of collection slider/toggle values by ID (see previous posts).PHP Code:var btnHandler = function(btn) {
var me = this,
items = me.items,
values = {};
items.each(function(cmp) {
if (Ext.isFunction(cmp.getValue)) {
console.log(cmp.id + " ----> " + cmp.getValue());
values[cmp.id] = cmp.getValue();
}
});
};
I'll thinker with the code some more, thanks for the help so far!!
-
7 Feb 2013 12:48 AM #8
Hi Guys,
I tried implementing this feature into my application. But I dont see the button appear on the page. Could you please look through my attached code and let me know what I am missing or what I am basically doing wrong.
Much appreciate a quick response.
FYI: I am a begineer to ExtJs 4.1.x
Code:var originalOverwrite = Ext.XTemplate.prototype.overwrite; Ext.override(Ext.XTemplate, { overwrite: function () { //execute the base overwrite method originalOverwrite.apply(this, arguments); //then, render any components that addCmp might have added while (this.templateComponents.length > 0) { var el = this.templateComponents.shift(); if (Ext.get(el.renderTo) != null) { var newel = new Ext.create(el); } } }, //an array to store the initialconfigs of the components-to-be templateComponents:[], templateIdCount:0, //Pushes an initialConfig to the array so that //a component can be later created and rendered. //It also generates a div container for the component //with a random id if no id was provided addCmp: function (initConfig) { var me = this, wrapperId = "ext-comp-wrapper-", afterRenderFunc = Ext.emptyFn; if (initConfig.id != void (0)) { wrapperId += initConfig.id; } else { //wrapperId += Math.random().toString().replace(".", ""); wrapperId += (this.templateIdCount++).toString() + Math.random().toString().replace(".", ""); } initConfig.renderTo = wrapperId; me.items = new Ext.util.MixedCollection(); if (!Ext.isDefined(initConfig.listeners)) { initConfig.listeners = {}; } else { if (Ext.isDefined(initConfig.listeners.afterrender)) { afterRenderFunc = initConfig.listeners.afterrender; } } Ext.apply(initConfig.listeners, { afterrender : function(cmp) { me.items.add(wrapperId, cmp); afterRenderFunc(cmp); } }); me.templateComponents.push(initConfig); return '<div id="' + wrapperId + '" class="y-wrapper"></div>'; }, addCmpTo: function (container, initConfig, collection) { if (collection == void(0)){ this.addCmpTo(container, initConfig, this.templateComponents); } else { if (collection.length > 0){ for (var i=0; i<collection.length; i++){ if (collection[i].id == container){ if (collection[i].items == void(0)){ collection[i].items = []; } collection[i].items.push(initConfig); break; } if (collection[i].items != void(0)){ this.addCmpTo(container, initConfig, collection[i].items); } } } } return; } }); Ext.define('Upsell.view.productview.ProductList', { extend : 'Upsell.view.productview.BasePanel', alias : 'widget.productviewlist', requires : [ 'Ext.button.Button' ], config: { title: 'Hello World', store : 'ProductLists', listTpl : Ext.create('Ext.XTemplate', '<tpl for=".">', '<h2 class="prorductviewh2">{PROD_NAME}</h2>', '<div class="row-fluid productview">', '<div class="span10">', '<img src="{PROD_IMAGE}" class="leftimage" title="{PROD_NAME}" />', '<div class="content">{PROD_DESCRIPTION}</div>', '</div>', '<div class="span2">', '{[ this.addCmp({xtype:"button", text:"Product Trial"}) ]}', //'<div class="productview-producttrail">{[ this.returnButtonField({}) ]}</div>', //'<div class="productview-producttrail"></div><div class="productview-learnmore"></div><div class="productview-purchasenow"></div>', '</div>', '</div>', '</tpl>', { dataview : this } ) }, initComponent : function(){ this.initConfig(this.initialConfig); //this.implementTemplateOverride(); Ext.apply(this, { width : '100%', //height : '100%', autoScroll : true, layout : { type : 'card' }, activeItem : 0, items : [ { xtype : 'panel', layout : 'fit', frame : false, border : 0, items : [ { xtype : 'dataview', tpl : this.getListTpl(), trackOver : true, itemId : 'available', itemSelector : 'div.productview', //autoScroll : true, listeners : { refresh : function(){ var producttrail = Ext.query('div.productview-producttrail'), learnmore = Ext.query('div.productview-learnmore'), purchasenow = Ext.query('div.productview-purchasenow'), i; for(i in producttrail){ Ext.create('Ext.button.Button', { text : 'Product Trail', //ui : 'action', scale : 'small', width : 110, action : 'trial', renderTo:producttrail[i] }); } for(i in learnmore){ Ext.create('Ext.button.Button', { text : 'Learn More', width : 110, action : 'learn', //ui : 'action', scale : 'small', renderTo:learnmore[i] }); } for(i in purchasenow){ Ext.create('Ext.button.Button', { text : 'Purchase Now', action : 'purchase', width : 110, ui : 'action', scale : 'medium', renderTo:purchasenow[i] }); } } }, store : this.getStore() } ] } ] }); this.callParent(arguments); } });
Similar Threads
-
form inside of a window - then accessing form elements
By webg in forum Ext 2.x: Help & DiscussionReplies: 2Last Post: 3 Jan 2008, 9:28 AM -
Form elements inside grid
By gregsimons in forum Ext 1.x: Help & DiscussionReplies: 1Last Post: 25 Jun 2007, 1:52 AM -
Form Elements gets removed inside form tags
By booshan in forum Ext 1.x: Help & DiscussionReplies: 0Last Post: 16 Apr 2007, 7:45 AM


Reply With Quote