I want to read json data from file - content of the json file shown below
{
"form": {
"fields" : [
{
"field":"textfield",
"name": "username",
"constrain": "5-10",
"value": ""
},
{
"field":"textfield",
"name": "password",
"constrain": "5-10",
"value": ""
},
{
"field":"datepickerfield",
"name": "Birthday",
"constrain": "5-10",
"value": "new Date()"
},
{
"field":"selectfield",
"name": "Select one",
"options":[
{"text": "First Option", "value": 'first'},
{"text": "Second Option", "value": 'second'},
{"text": "Third Option", "value": 'third'}
]
},
]
}
}
Model
Ext.define('dynamicForm.model.Form', {
extend: 'Ext.data.Model',
config: {
fields: [
{name: 'field', type: 'string'},
{name: 'name', type: 'string'},
{name: 'constrain', type: 'string'},
{name: 'value', type: 'string'}
],
hasMany: {model: 'dynamicForm.model.SelectOption', name: 'options'}
}
});
Ext.define('dynamicForm.model.SelectOption', {
extend: 'Ext.data.Model',
config: {
fields: [
{name: 'text', type: 'string'},
{name: 'value', type: 'string'}
]
}
});
store
Ext.define('dynamicForm.store.FormStore', {
extend : 'Ext.data.Store',
storeId: 'formStore',
config : {
model : 'dynamicForm.model.Form',
proxy : {
type : 'ajax',
url : 'form.json',
reader : {
type : 'json',
rootProperty : 'form.fields'
}
},
autoLoad: true
}
});
This what i tried so for.
var fromval = Ext.create('dynamicForm.store.FormStore');
fromval.load(function (){
console.log(fromval);
// i added register view which having form panel with id "testForm"
Ext.Viewport.add({
xtype : 'register'
});
for(i=0; i< fromval.getCount(); i++) {
console.log("------");
Ext.getCmp('testForm').add({
xtype: fromval.getAt(i).data.field,
label: fromval.getAt(i).data.name,
value: fromval.getAt(i).data.value,
options: [
{text: "First Option", value: "first"},
{text: "Second Option", value: "second"},
{text: "Third Option", value: "third"}
]
});
}
});
two text fileds and date are woking good, but i don't know how to get options for select field from store, just heard coded now.
over all Based on the above json data, i need to create sencha form dynamically.
Better to follow MVC structure:
Create a model:
Ext.define('MyApp.model.FormModel', {
extend: 'Ext.data.Model',
config: {
fields: ["field","name"]
}
});
A store with proxy:
Ext.define('MyApp.store.FormStore',{
extend: 'Ext.data.Store',
config:
{
model: 'MyApp.model.FormModel',
autoLoad:true,
proxy:
{
type: 'ajax',
url : 'FormData.json', //Your file containing json data
reader:
{
rootProperty:'form.fields'
}
}
}
});
The formData.json file:
{
"form": {
"fields" : [
{
"field":"textfield",
"name": "username"
},
{
"field":"textfield",
"name": "password"
},
]
}
}
And then use the FormStore to fill the form data as you need.
Ext.define('MyApp.view.LoginPage', {
extend: 'Ext.form.Panel',
config: {
items:{
xtype:'fieldset',
layout:'vbox',
items:[{
flex:1,
xtype:'textfield',
id:'namefield',
placeHolder:'Username'
},{
flex:1,
xtype:'passwordfield',
id:'passwordfield',
placeHolder:'Password'
}]
},
listeners:{
painted:function()
{
var store=Ext.getStore('FormStore');
while(!store.isLoaded())
{
console.log("loading...");
}
var record=store.getAt(0);
Ext.getCmp('namefield').setValue(record.data.name);
Ext.getCmp('passwordfield').setValue(record.data.password);
}
}
}
});
{
"data":[
{
"xtype":"textfield",
"title":"UserName",
"name": "username"
},
{
"xtype":"textfield",
"title":"password",
"name": "password"
},
{
"xtype":"textfield",
"title":"phone no",
"name": "birthday"
},
{
"xtype":"textarea",
"title":"address",
"name": "address"
}
]
}
Ext.define('dynamicForm.model.FormModel', {
extend: 'Ext.data.Model',
fields: ['field', 'name']
});
Ext.define('dynamicForm.store.FormStore', {
extend : 'Ext.data.Store',
model : 'dynamicForm.model.FormModel',
proxy :
{
type : 'ajax',
url : 'data/user.json',
reader :
{
type : 'json',
rootProperty:'data'
},
autoLoad: true
}
});
Ext.define('dynamicForm.view.DynaForm',{
extend:'Ext.form.Panel',
alias:'widget.df1',
items:[]
});
Ext.application({
name:'dynamicForm',
appFolder:'app',
controllers:['Users'],
launch:function(){
Ext.create('Ext.container.Viewport',{
items:[
{
xtype:'df1',
items:[]
}
]
});
}
});
Ext.define('dynamicForm.controller.Users',{
extend:'Ext.app.Controller',
views:['DynaForm'],
models:['FormModel'],
stores:['FormStore'],
refs:[
{
ref:'form1',
selector:'df1'
}
],
init:function(){
console.log('in init');
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});
},
onPanelRendered: function() {
var fromval=this.getFormStoreStore();
var form=this.getForm1();
fromval.load({
scope: this,
callback: function(records ,operation, success) {
Ext.each(records, function(rec) {
var json= Ext.encode(rec.raw);
var response=Ext.JSON.decode(json);
for (var i = 0; i < response.data.length; i++) {
form.add({
xtype: response.data[i].xtype,
fieldLabel: response.data[i].title,
name: response.data[i].name
});
}
//form.add(Ext.JSON.decode(json).data);
form.doLayout();
});
}
});
}
});
It will be done automatically if you insert it into any extjs component content :
var jsonValues = "{
"form": {
"fields" : [
{
"field":"textfield",
"name": "username"
},
{
"field":"textfield",
"name": "password"
},
]
}
}";
var panel = new Ext.Panel({
id : 'myPanel',
items : [jsonValues]
});
panel.show();
Related
We are creating a new version our API (v2) adopting the JSON:API specification (https://jsonapi.org/). I'm not being able to port the ExtJS model associations (belongs_to) to the new pattern.
The ExtJS documentation only shows how to use a nested relation in the same root node (https://docs.sencha.com/extjs/4.2.2/#!/api/Ext.data.association.Association).
v1 data (sample):
{
"data": [
{
"id": 1,
"description": "Software Development",
"area_id": 1,
"area": {
"id": 1,
"code": "01",
"description": "Headquarters"
}
},
],
"meta": {
"success": true,
"count": 1
}
}
v2 data (sample):
{
"data": [
{
"id": "1",
"type": "maint_service_nature",
"attributes": {
"id": 1,
"description": "Software Development",
"area_id": 1
},
"relationships": {
"area": {
"data": {
"id": "1",
"type": "area"
}
}
}
}
],
"included": [
{
"id": "1",
"type": "area",
"attributes": {
"id": 1,
"code": "01",
"description": "Headquarters"
}
}
],
"meta": {
"success": true,
"count": 1
}
}
My model:
Ext.define('Suite.model.MaintServiceNature', {
extend: 'Ext.data.Model',
fields: [
{ desc: "Id", name: 'id', type: 'int', useNull: true },
{ desc: "Area", name: 'area_id', type: 'int', useNull: true },
{ desc: "Description", name: 'description', type: 'string', useNull: true, tableIdentification: true }
],
associations: [
{
type: 'belongsTo',
model: 'Suite.model.Area',
foreignKey: 'area_id',
associationKey: 'area',
instanceName: 'Area',
getterName: 'getArea',
setterName: 'setArea',
reader: {
type: 'json',
root: false
}
}
],
proxy: {
type: 'rest',
url: App.getConf('restBaseUrlV2') + '/maint_service_natures',
reader: {
type: 'json',
root: 'data',
record: 'attributes',
totalProperty: 'meta.count',
successProperty: 'meta.success',
messageProperty: 'meta.errors'
}
}
});
Any ideias on how to setup the association to work with the v2 data?
I'm honestly taking a stab at this one... I haven't used Ext JS 4 in years, and I wouldn't structure my JSON like JSON:API does, but I think the only way you can accomplish this is by rolling your own reader class. Given that you have generic properties for your data structure, this reader should work for all scenarios... although, I'm not too familiar with JSON:API, so I could be totally wrong. Either way, this is what I've come up with.
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.define('MyReader', {
extend: 'Ext.data.reader.Json',
alias: 'reader.myReader',
root: 'data',
totalProperty: 'meta.count',
successProperty: 'meta.success',
messageProperty: 'meta.errors',
/**
* #override
*/
extractData: function (root) {
var me = this,
ModelClass = me.model,
length = root.length,
records = new Array(length),
dataConverter,
convertedValues, node, record, i;
for (i = 0; i < length; i++) {
node = root[i];
var attrs = node.attributes;
if (node.isModel) {
// If we're given a model instance in the data, just push it on
// without doing any conversion
records[i] = node;
} else {
// Create a record with an empty data object.
// Populate that data object by extracting and converting field values from raw data.
// Must pass the ID to use because we pass no data for the constructor to pluck an ID from
records[i] = record = new ModelClass(undefined, me.getId(attrs), attrs, convertedValues = {});
// If the server did not include an id in the response data, the Model constructor will mark the record as phantom.
// We need to set phantom to false here because records created from a server response using a reader by definition are not phantom records.
record.phantom = false;
// Use generated function to extract all fields at once
me.convertRecordData(convertedValues, attrs, record, me.applyDefaults);
if (me.implicitIncludes && record.associations.length) {
me.readAssociated(record, node);
}
}
}
return records;
}
});
Ext.define('Suite.model.Area', {
extend: 'Ext.data.Model',
fields: [{
name: 'type',
type: 'string'
}]
});
Ext.define('Suite.model.MaintServiceNature', {
extend: 'Ext.data.Model',
fields: [{
desc: "Id",
name: 'id',
type: 'int',
useNull: true
}, {
desc: "Area",
name: 'area_id',
type: 'int',
useNull: true
}, {
desc: "Description",
name: 'description',
type: 'string',
useNull: true,
tableIdentification: true
}],
associations: [{
type: 'belongsTo',
model: 'Suite.model.Area',
associatedName: 'Area',
foreignKey: 'area_id',
associationKey: 'relationships.area.data',
instanceName: 'Area',
getterName: 'getArea',
setterName: 'setArea'
}],
proxy: {
type: 'rest',
url: 'data1.json',
reader: {
type: 'myReader'
}
}
});
Suite.model.MaintServiceNature.load(null, {
callback: function (record) {
console.log(record.getData(true));
}
});
}
});
I have set of models and a store as given below.
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
'id', 'name', 'total'],
hasMany: {
model: 'Order',
name: 'orders'
},
proxy: {
type: 'rest',
url: 'users.json',
reader: {
type: 'json',
root: 'users'
}
}
});
Ext.define('Order', {
extend: 'Ext.data.Model',
fields: [
'id', 'total'],
hasMany: {
model: 'OrderItem',
name: 'orderItems',
associationKey: 'order_items'
},
belongsTo: 'User'
});
Ext.define('OrderItem', {
extend: 'Ext.data.Model',
fields: [
'id', 'price', 'quantity', 'order_id', 'product_id'],
belongsTo: ['Order', {model: 'Product', associationKey: 'product'}]
});
var store = Ext.create('Ext.data.Store', {
model: 'User'
});
And below is the json file which I use to load data.
{
"users": [
{
"id": "123",
"name": "Ed",
"orders": [
{
"id": "50",
"total": "100",
"order_items": [
{
"id" : "20",
"price" : "40",
"quantity": "2",
"product" : {
"id": "1000",
"name": "MacBook Pro"
}
},
{
"id" : "21",
"price" : "20",
"quantity": "3",
"product" : {
"id": "1001",
"name": "iPhone"
}
}
]
}
]
},
{
"id": "124",
"name": "Nisha",
"orders": [
{
"id": "52",
"total": "1004",
"order_items": [
{
"id" : "22",
"price" : "40",
"quantity": "23",
"product" : {
"id": "1002",
"name": "Nokia"
}
},
{
"id" : "23",
"price" : "100",
"quantity": "3",
"product" : {
"id": "1003",
"name": "apple"
}
}
]
}
]
}
]
}
I am loading the user IDs to L1_combo_box as below and according to the user ID the user selects from the L1_combo_box, I need to load order_item ids to L2_combo_box .
For example, I load user ids 123, 124 to L1_combo_box and when user selects 123 from L1 combo box, I need to load 20,21 to L2 combo box. If user selects 124, then I need to load 22,23.
Below is the partially completed code. can anyone help me to complete this?
var searchFormFieldsetItems = [
{
xtype: 'fieldcontainer',
combineErrors: true,
name: 'search_form_fieldset_items',
msgTarget: 'side',
fieldLabel: '',
defaults: {
hideLabel: true
},
items: [{
xtype: 'combo',
name: 'L1_combo_box',
displayField: 'id',
valueField: 'id',
queryMode: 'remote',
store:store,
listeners: {
change: {
fn: function(combo, value) {
var store1 = 'users/orders/order_items/';//This line is partially completed
L2_combo_box.bindStore(store1);
}
}
}
},{
xtype: 'combo',
name: 'L2_combo_box',
displayField: 'id',
valueField: 'id'
}
]
}
];
For this you need to use select for combobox and inside of select event you need to use loadData() method of store to adding data in second combo.
In this FIDDLE, I have created a demo using your code and put my efforts for showing data in second combo. I hope this will help/guide you to achieve your requirement.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.define('User', {
extend: 'Ext.data.Store',
autoLoad: true,
alias: 'store.user',
fields: ["id", "name", "orders"],
proxy: {
type: 'ajax',
url: 'users.json',
reader: {
type: 'json',
rootProperty: 'users'
}
}
});
Ext.define('Order', {
extend: 'Ext.data.Store',
alias: 'store.order',
field: ["id", "price", "quantity", "product"],
storeId: 'order'
});
Ext.create('Ext.form.Panel', {
title: 'Example Combo',
bodyPadding: 5,
defaults: {
width: 250
},
// The fields
defaultType: 'combo',
items: [{
name: 'L1_combo_box',
displayField: 'id',
valueField: 'id',
queryMode: 'local',
emptyText: 'Select user',
store: {
type: 'user'
},
listeners: {
select: function (combo, rec) {
var L2_combo_box = combo.up('form').getForm().findField('L2_combo_box'),
order = rec.get('orders') || [],
data = [];
//reset combo value
L2_combo_box.reset();
//If order have multipe data then need use forEach for all data
order.forEach(item => {
data = data.concat(item.order_items);
});
//load data in combo store
Ext.getStore('order').loadData(data);
}
}
}, {
emptyText: 'Select order items',
name: 'L2_combo_box',
displayField: 'id',
valueField: 'id',
queryMode: 'local',
store: {
type: 'order'
}
}],
renderTo: Ext.getBody()
});
}
});
I have a php-script, which returns the following JSON
[
{
"Code":0,
"Message":"No problem"
},
{
"name":"o016561",
"status":1,
"locks":[
{
"ztn":"155320",
"dtn":"20131111",
"idn":"78"
},
{
"ztn":"155320",
"dtn":"20131111",
"idn":"91"
}
]
},
{
"name":"o011111",
"status":1,
"locks":[
{
"ztn":"155320",
"dtn":"20131111",
"idn":"91"
}
]
},
{
"name":"o019999",
"status":0,
"locks":[
]
},
{
"name":"o020000",
"status":0,
"locks":[
]
},
{
"name":"o020001",
"status":0,
"locks":[
]
}
]
Edit:
The grid should look something like this:
I've been able to load name and status into my grid - so far so good. But the more important part is, that I need the nested data in the locks-array being loaded into my grid, but I just can't get my code working. Any help would be appreciated.
I'm using ExtJS 4.2 if that matters.
Edit 2:
I tried
Ext.define("Locks", {
extend: 'Ext.data.Model',
fields: [
'ztn',
'dtn',
'idn'
]
});
Ext.define("ConnectionModel", {
extend: 'Ext.data.Model',
fields: ['name', 'status'],
hasMany: [{
model: 'Locks',
name: 'locks'
}]
});
var store = Ext.create('Ext.data.Store', {
model: "ConnectionModel",
autoLoad: true,
proxy: {
type: 'ajax',
reader: {
type: 'json',
root: 'name'
}
}
});
but it seemed to be wrong in multiple ways...
and it would be awesome if ztn and dtn could be displayed just seperated with a whitespace in the same column
You can add a renderer to the column. In that renderer you can do anything with the record...
Here's a working fiddle:
http://jsfiddle.net/Vandeplas/MWeGa/3/
Ext.create('Ext.grid.Panel', {
title: 'test',
store: store,
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Status',
dataIndex: 'status'
}, {
text: 'idn',
renderer: function (value, metaData, record, rowIdx, colIdx, store, view) {
values = [];
record.locks().each(function(lock){
values.push(lock.get('idn'));
});
return values.join('<br\>');
}
}, {
text: 'ztn + dtn',
renderer: function (value, metaData, record, rowIdx, colIdx, store, view) {
values = [];
record.locks().each(function(lock){
values.push(lock.get('ztn') + ' ' + lock.get('dtn'));
});
return values.join('<br\>');
}
}],
height: 200,
width: 600,
renderTo: Ext.getBody()
});
Note
If you have control over your backend you better change the form of your data more like this:
{
"code": 0,
"message": "No problem",
"success": true,
"data": [
{
"name": "o016561",
"status": 1,
"locks": [
{
"ztn": "155320",
"dtn": "20131111",
"idn": "78"
},
{
"ztn": "155320",
"dtn": "20131111",
"idn": "91"
}
]
},
{
"name": "o011111",
"status": 1,
"locks": [
{
"ztn": "155320",
"dtn": "20131111",
"idn": "91"
}
]
}
]
}
That way you don't mix your control data (success, message, code,...) with your data and the proxy picks it up correctly (it can be a cause of the problems your experiencing). I added a success boolean => Ext picks it up and goes to the failure handler. It helps a lot with your exception handling.
Here is the proxy for it:
proxy: {
type: 'ajax',
api: {
read: ___URL____
},
reader: {
type: 'json',
root: 'data',
messageProperty: 'message'
}
}
I'm trying to load a store from JSON received from webservices. But all the data from the JSON goes under the 'raw' column of the items in the store...
I can't figure out why, my code seems correct.
Any help is welcome.
My Model :
Ext.define('App.model.Node', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'id', type: 'int' },
{ name: 'version', type: 'int' },
{ name: 'user_id', type: 'int' },
{ name: 'tstamp', type: 'date' },
{ name: 'changeset_id', type: 'int' },
{ name: 'tags', type: 'string' },
{ name: 'geom', type: 'string'}
],
idProperty: 'id'
}
});
My Store :
Ext.define('App.store.NodeStore', {
extend: 'Ext.data.Store',
xtype: 'nodestore',
requires: [
'Ext.data.proxy.Rest'
],
config: {
model: 'App.model.Node',
storeId: 'nodeStore',
autoLoad: true,
proxy: {
type:'rest',
url:'http://localhost/server/nodes',
reader: {
type:'json',
rootProperty: 'nodes'
},
noCache: false,
limitParam: false,
headers: {
'Accept' : 'application/json'
}
}
}
});
My JSON :
{
"nodes": [
{
"id": "454467",
"version": 6,
"user_id": 52015,
"tstamp": "2008-12-27 21:38:45",
"changeset_id": "634766",
"tags": "",
"geom": "0101000020E6100000409CD1A0B29321405455682096804740"
},
{
"id": "454468",
"version": 8,
"user_id": 52015,
"tstamp": "2009-12-23 20:47:15",
"changeset_id": "3437205",
"tags": "",
"geom": "0101000020E6100000357C0BEBC69321409EC02ACD9C804740"
},
{
"id": "454469",
"version": 7,
"user_id": 52015,
"tstamp": "2009-12-23 20:47:15",
"changeset_id": "3437205",
"tags": "",
"geom": "0101000020E6100000347914F8D4932140B8BBBD5AA4804740"
}
]
}
And when I do a
var nodeStore = Ext.getStore('nodeStore');
nodeStore.load();
console.log(nodeStore.getData());
we can see the following object, with my data in the raw column under items...
I figured it out, my code is correct and the only thing missing is a callback in the load() function :
nodeStore.load({
callback: function(records, operation, success) {
console.log(records);
console.log(nodeStore.getCount());
nodeStore.each(function(element) {
console.log(element.data.id);
});
},
scope: this,
});
The problem was I was trying to access the store before it loaded the data. Now I'm waiting that all the data is loaded to access it, and it works.
Hi I'm trying to load a local JSON file in Sencha Touch 2.
I'm using phonegap 1.4 and iOS 5, testing in VM.
Here is the code:
Ext.define("User", {
extend: 'Ext.data.Model',
config: {
fields: [
'id', 'name'
],
hasMany: {model: 'Order', name: 'orders'},
proxy: {
type: 'ajax',
url : 'users.json',
reader: {
type: 'json',
root: 'users'
}
}
}
});
Ext.define("Order", {
extend: 'Ext.data.Model',
config: {
fields: [
'id', 'total'
],
hasMany : {model: 'OrderItem', name: 'orderItems', associationKey: 'order_items'},
belongsTo: 'User'
}
});
Ext.define("OrderItem", {
extend: 'Ext.data.Model',
config: {
fields: [
'id', 'price', 'quantity', 'order_id', 'product_id'
],
belongsTo: ['Order', {model: 'Product', associationKey: 'product'}]
}
});
Ext.define("Product", {
extend: 'Ext.data.Model',
fields: [
'id', 'name'
],
hasMany: 'OrderItem'
});
var store = Ext.create('Ext.data.Store', {
model: "User"
});
store.load({
callback: function() {
//the user that was loaded
var user = store.first();
//console.log("Orders for " + user.get('name') + ":")
alert(user.get('name'));
//iterate over the Orders for each User
user.orders().each(function(order) {
console.log("Order ID: " + order.getId() + ", which contains items:");
//iterate over the OrderItems for each Order
order.orderItems().each(function(orderItem) {
//we know that the Product data is already loaded, so we can use the synchronous getProduct
//usually, we would use the asynchronous version (see Ext.data.association.BelongsTo)
var product = orderItem.getProduct();
});
});
}
});
The JSON file:
{
"users": [
{
"id": 123,
"name": "Ed",
"orders": [
{
"id": 50,
"total": 100,
"order_items": [
{
"id" : 20,
"price" : 40,
"quantity": 2,
"product" : {
"id": 1000,
"name": "MacBook Pro"
}
},
{
"id" : 21,
"price" : 20,
"quantity": 3,
"product" : {
"id": 1001,
"name": "iPhone"
}
}
]
}
]
}
]
}
The alert says 'undefined', any help? Many thanks
In Sencha Touch 2 the reader object should use rootProperty instead of root.