Ext.form.Panel load() vs. loadRecord() - javascript

I have strange problem with loading form panel with json request response.
In previous projects I used to load detail panel from grid store by using loadRecord(record)
The store has associated model so record's embedded objects are mapped to model's properties and form renders those fields without any problem.
Once I had to load form directly with response from form.load() I can't see properties from record's embedded objects.
For example from json
{
"message":null,
"success":true,
"data":{
"code":"1",
"name":"Canon Canada",
"modifiedBy":null,
"modifiedAt":null,
"address":{
"street":"6390 Dixie",
"suite":null,
"city":"Mississauga",
"provinceCode":"ON",
"postalCode":"L5T1P7"
},
...
}
}
I see rendered 'code' and 'name' properties, but not 'street' and 'city'.
Here is form.Panel code
Ext.define('App.view.billto.BillToDetailForm' ,{
extend : 'Ext.form.Panel'
,layout: 'form'
,alias : 'widget.BillToDetailForm'
,autoHeight: true
,bodyPadding: 10
,fieldDefaults: MainAppViewConfig.fieldDefaults
,defaults: {xtype: 'fieldcontainer',layout:'hbox', anchor: '100%'}
,items : [ { defaults: {xtype: 'textfield', allowBlank: false},
items: [{name: 'code', fieldLabel:'Bill To Code'}
,{name: 'name',fieldLabel: 'Name'}]}
,{ defaults: {xtype: 'textfield', allowBlank: false},
items: [{name: 'address.suite', fieldLabel:'Suite'}
,{name: 'address.street', fieldLabel:'Street'}]}
...
]
,loadContentForCode: function(code){
//this.getForm().trackResetOnLoad = true;
this.getForm().load({ method: 'GET',url: 'billtoDetail',
params:{'code':code},
waitMsg: 'Loading...',
/*success:function(form, action) {
console.log('BillToDetailForm:loadContentForCode callback on success '+this);
var responseObj = Ext.JSON.decode(action.response.responseText,true);
var billToModel = Ext.create('MPS.model.BillToModel',responseObj.data);
form.loadRecord(billToModel);
}*/
});
}
});
As you can see I even did unsuccessful attempt to reload form in success handler.
Also I have noticed that var billToModel = Ext.create('MPS.model.BillToModel',responseObj.data);
hasn't properly populated model's fields 'street' and 'city'. That's also might be the cause of the problem.
Ext.define('MPS.model.BillToModel', {
extend: 'Ext.data.Model'
,idProperty:'code'
,fields: [
{name: 'code', type: 'string'},
{name: 'name', type: 'string'},
{name: 'street',mapping:'address.street', type: 'string'},
{name: 'city', mapping:'address.city', type: 'string'},
...
]
});
Could you please point the real cause of the problem or advice any solution.
Thank you.

I just made fiddle for you. Take a look how it is working and try the same with your code:
Sencha Fiddle - How associated data works
If this something that you are looking for just mark as answered.

Related

How to create a dynamic (on the fly) form in Sencha Touch

I am working in a sencha touch ap and I need to generate views with dynamic forms.
Configuration comes from the backend (JSON) and depending of this I paint a component or other.. for example:
"auxiliaryGroups": [
{
"id": "1000",
"name": "Basic Data",
"fields": [
{
"id": "1001",
"name": "Company name",
"editable": true,
"mandatory": true,
"calculation": true,
"internalType": "T",
"type": "textfield",
"options": []
}
]
}
],
Where type is related xtype in Sencha.
In the view I am creating all options of fields:
{
xtype : 'fieldset',
itemId: 'auxiliaryFieldsGroup3',
title: 'Requirements',
//cls : 'headerField',
items:[
{
xtype: 'togglefield',
name: 'f6',
label: 'Auxiliary field R1'
},
{
xtype: 'selectfield',
name: 'f10',
label: 'Auxiliary field R5',
placeHolder: 'Select one..',
options: [
{text: 'First Option', value: 'first'},
{text: 'Second Option', value: 'second'},
{text: 'Third Option', value: 'third'}
]
},
{
xtype: 'textfield'
}
]
}
And I receive the configuration from the server, I understand the view like a store of different fields, and from the controller, it should add only fields specified in the json object.
How to create this dynamically following MVC concept?
Thank you
I assume that you have all the fields in the auxiliaryGroups.fields array.
After loading the form data from AJAX you can do it like this in your success call.
succses:function(response){
var response = Ext.decode(response.responseText);
var fields = response.auxiliaryGroups.fields;
var form = Ext.create("Ext.form.Panel",{
// here your form configuration.
cls:"xyz"
});
Ext.Array.forEach(fields,function(field){
var formField = {
xtype: field.type,
label: field.name,
name: field.id
};
form.add(formField);
});
Ext.Viewport.add(form);
form.show();
}
Based on my comment on your question, my idea about dynamic form generation is using ExtJS syntax to load form definition would be something like the code below; of course it would be extended and the data can be loaded from the server.
Ext.require([
'Ext.form.*'
]);
Ext.onReady(function() {
var data = [{
fieldLabel: 'First Name',
name: 'first',
allowBlank: false
}, {
fieldLabel: 'Last Name',
name: 'last'
}, {
fieldLabel: 'Company',
name: 'company'
}, {
fieldLabel: 'Email',
name: 'email',
vtype: 'email'
}, {
xtype: 'timefield',
fieldLabel: 'Time',
name: 'time',
minValue: '8:00am',
maxValue: '6:00pm'
}];
var form = Ext.create('Ext.form.Panel', {
frame: true,
title: 'Simple Form',
bodyStyle: 'padding:5px 5px 0',
width: 350,
fieldDefaults: {
msgTarget: 'side',
labelWidth: 75
},
defaultType: 'textfield',
defaults: {
anchor: '100%'
}
});
form.add(data);
form.render(document.body);
});
update:
When you create a view in run-time, communication between view and controller might be problematic because the controller doesn't know anything about the view. considering that the controller is responsible for initializing the view with appropriate data and handling view's events, data binding mechanism in ExtJS can solve the first part (initializing the view) which is described at View Models and Data Binding, the second part (handling view's events) can be solved with general methods in the controller, every element in the view should send its event to some specific methods and the methods based on the parameters should decide what to do.
This approach makes your methods in the controller a little fat and complicated that is the price of having dynamic form.
It is worth to mention that EXTJS raises different events in the life cycle of controllers and views and you should take benefit of them to manage your dynamic form.
I don't know about Touch, but in ExtJS, I usually do it by using the add function of a fieldset. You just loop through all your records, and create the fields on the fly.
var field = Ext.create('Ext.form.field.Text'); //or Ext.form.field.Date or a number field, whatever your back end returns.
Then set correct config options on field then
formFieldset.add(field);

I want to read data from store for Extjs 4 but it shows [object object]

This is my model:
data: i
0: i
data: Object
events: Object
hasListeners: k
id: "region-ext-record-344"
index: 0
internalId: "ext-record-344"
modified: Object
phantom: false
raw: Array[2] // i want to get those two elements one displayField, another valueField
0: "01"
1: "Region 1"
length: 2
__proto__: Array[0]
store: i
stores: Array[1]
__proto__: Object
1: i
2: i
3: i
length: 4
__proto__: Array[0]
I can post the code if you want to!
I tried to read store like:
store: regionStore, but it is showing me an empty box with 4 empty lines equal to item count in my store, then I tried to do like store: regionStore.data.items and now it shows me [object object] lines, I totally get it why, but can't find solution for that. I am new to all ExtJs stuff, I am using ExtJs 4 though.
My model looks like that :
Ext.regModel('region', {
fields: [
{name: 'id', type: 'integer'},
{name: 'name', type: 'String'}
});
and my store looks like that:
var regionStore = new Ext.data.ArrayStore({
id: 'regionStore',
model: 'region',
data: MyDesktop.GridWindow.getRegionData() //that is data from ajax response
});
My combobox:
{
xtype: 'combobox',
value: "region",
store: regionStore,
width: 135,
id: 'regionCombo'
editable: false
}
You have tagged your question extjs 4.2, but your code is old style and not following recommendations. I really recommend you to read the manual, especially the introduction to MVC.
Ext.regModel is deprecated as of version 4.0.0. Change your code as follows and save it to the file app/model/Region.js :
Ext.define('MyApp.model.Region', {
extends: 'Ext.data.Model',
fields: [
{name: 'id', type: 'integer'},
{name: 'name', type: 'string'}
]
});
In file app/store/Regions.js :
Ext.define('MyApp.store.Regions', {
extends: 'Ext.data.ArrayStore',
//id: notice that id is no longer necessary
model: 'Region',
//data: you load the store from the server, so the data is loaded automatically
autoLoad: true
})
Your combobox becomes:
xtype: 'combobox',
value: 'region',
store: 'Regions',
width: 135,
id: 'regionCombo',
editable: false,
valueField: 'id',
displayField: 'name'
I never used extjs before 4.2, but it seems the changes introduced with version 4 are important. It may be difficult to adopt the new paradigms. But I'm sure it radically simplifies your code. You certainly never will regret this step.
Also with the release of version 5.0, I think it's time to develop new habits and leave ExtJs 2.0 coding style behind.
You started off correctly, but you didn't specify which fields to use. Add the missing configuration :
store: regionStore,
valueField: 'id',
displayField: 'name'
For a combobox you can define a store inline as :
store: [[1, 'first option'], [2, 'second option']],
In this case you will not need to declare the value and the display field. They are implicit.

How can I display a store value to a pannel? using EXTJS

I have data.xml file as follow
<root>
<tag2>
<key>12</key>
<spec>15</spec>
</tag2>
</root>
I want to display that key value and spec value on a panel window, here is the code I have, but I stuck at displaying. How can I display it out?
Ext.define('tag2',{
extend: 'Ext.data.Model',
fields: [{name: 'key', type: 'float'},
{name: 'spec', type: 'float'}]
});
var tag2Store= Ext.create('Ext.data.Store',{
model: 'tag2',
autoLoad:true,
proxy:{
type: 'ajax',
url: 'data.xml',
reader:{
type: 'xml',
record: 'tag2'
}
}
});
Ext.create('Ext.Window',{
title: 'tag2',
width: 400,
height:500,
x:400,
y:300,
renderTo: Ext.getBody(),
store: tag2Store,
hidden: false,
maximizable: true,
layout: 'fit',
id: 'tag2',
html: 'key = , spec = '
});
right at the html
html: 'key = , spec = '
I want
html: 'key = 12 , spec = 15 '
But I don't know what to do here
Thanks
You would use the tpl property to provide a template for the data that you want rendered.
See the Template docs on how to use it: http://docs.sencha.com/extjs/4.1.3/#!/api/Ext.XTemplate
Also window does not have a store property that it knows what to do with. You need to apply the data to the template yourself if you are using a window component. Otherwise you can use a DataView component : http://docs.sencha.com/extjs/4.1.3/#!/api/Ext.view.View

How to remotely sort an Ext grid column that renders a nested object?

Simple question here, and I'm really surprised I cannot find an answer to it anywhere.
I have the following product model:
Ext.define('Product', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'},
{name: 'manufacturer', type: 'auto'}, // i.e. nested object literal
],
});
As can be seen, a product has a nested object inside it that contains details about a manufacturer (id, name, description, etc.).
I display products in an Ext.grid.Panel, like so:
Ext.create('Ext.grid.Panel', {
title: 'Products',
...
remoteSort: true,
columns: [
{text: 'Id', dataIndex: 'id', sortable: true},
{text: 'Name', dataIndex: 'name', sortable: true},
{text: 'Manufacturer', dataIndex: 'manufacturer', sortable: true, renderer: function(manufacturer) {
return manufacturer.name; // render manufacturer name
}
},
],
});
As you can see, all three columns are configured to be sortable, and I am using remote sorting. This works for the first two columns, but the third column (manufacturer) is giving me trouble.
For instance, when a user sorts the grid by product name, Ext sends the following JSON to the server:
{ sort: [{ property: 'name', direction: 'ASC' }] }
This is fine, because the server knows to simply sort by each product's name property.
But when a user sorts the grid by manufacturer, the JSON sent is:
{ sort: [{ property: 'manufacturer', direction: 'ASC' }] }
Since the manufacturer is an object, this does not give the server any idea which property of the manufacturer it should sort by! Is it the manufacturer's id? Or is it the manufacturer's name? Or something else?
For my grid, since I render the manufacturer's name, I'd like to sort it by name. But I see no way to tell the server this. And I certainly don't want to make my server just sort by the manufacturer's name all the time.
If the JSON was sent like this it would be ideal:
{ sort: [{ property: 'manufacturer.name', direction: 'ASC' }] }
Sadly, Ext does not seem to do that (?). So, what's the solution?
Okay, I asked on the Sencha Forums and got a response. It appears you can override getSortParam() in the column config. Example:
columns: [
...
{
header: 'Manufacturer',
dataIndex: 'manufacturer',
sortable: true,
renderer: function(manufacturer) {
return manufacturer.name; // render manufacturer name
},
getSortParam: function() {
return 'manufacturer.name';
},
}
...
]
This will send the ideal JSON I described in my OP. Now I just need to make my server parse this properly! :)

Submitting form in Sencha Touch

I have created a form and am trying to send its contents to a server. I used the forms example from sensa.com as a template. The form sends a message to my server, but only with my the disable caching value and not any of the form values, for example [url]/register?_dc=1829384859324 . I also modified the example to use my server url and my server received the same type of request with only _dc=... from the example.
Is there some explicit way I have to list the fields I want sent to the server?
My form code is listed below. When I call submit, I use form.submit({method: 'get'});
var formBase = {
scroll: 'vertical',
url : 'MYURL/register',
standardSubmit : false,
items: [{
xtype: 'fieldset',
title: 'Personal Info',
instructions: 'Please enter the information above.',
defaults: {required: true,labelAlign: 'left',labelWidth: '40%'},
items: [
{ xtype: 'textfield',name : 'first',label: 'First Name',useClearIcon: true,autoCapitalize : false
}, { xtype: 'textfield',name : 'last',label: 'Last Name',useClearIcon: true,autoCapitalize : false
}, { xtype: 'passwordfield',name : 'password',label: 'Password',useClearIcon: false
}, {xtype: 'textfield',name : 'phone',label: 'Phone Number',
}, {xtype: 'emailfield', name : 'email',label: 'Email',placeHolder: 'you#email.com',useClearIcon: true
}]
}],
listeners : {
submit : function(form, result){
console.log('success',Ext.toArray(arguments));
},
exception : function(form, result){
console.log('failure', Ext.toArray(arguments));
}
}
I've just started using Sencha Touch myself, but I'm posting my form a bit different. I've created a submit button, and given that button a handler. The code that gets executed is the following:
this.loginView.submit({
method: 'POST',
waitTitle: 'Connecting',
waitMsg: 'Sending data...',
success: function(form, result) {
Ext.Msg.alert('Login succeeded!', result.response.reason);
},
failure: function(form, result){
Ext.Msg.alert('Login Failed!', result.response.reason);
}
});
In which this.loginView refers to an Ext.form.FormPanel object (I'm separating controller-code and view-code, which I highly recommend!). Another method you could try is create your own AJAX request (using Ext.Ajax.request) and retrieve your form params using the getValues(); method from the FormPanel object.
I hope it helps!
You have to set the form property standardSubmit to true.
This post is quite old, but there might be others having similar issues with form submitting.
If you are new to Sencha and you have a form which is submitting nothing, you probably followed this tutorial Building your first app
It has a problem. Form items MUST HAVE NAME which is missing in the example.
Items should look something like the following:
items: [
{
xtype: 'textfield',
name: 'name',
label: 'Name'
},
{
xtype: 'emailfield',
name: 'email',
label: 'Email'
},
{
xtype: 'textareafield',
name: 'message',
label: 'Message'
}
]

Categories

Resources