I have model Schedule which associated with another model Chamber.
And i'm getting the problem when associated model data is null.
It's normal behavior, cause it's not required field.
Upgrade: Schedule model is a part of scheduleTree model, which used by store loading data from server.
Ext.define('...SchedulesTree', {
extend : '...TreeStore',
model: "...ScheduleTree",
root: {
expanded: true,
text: "root",
children: [],
loaded: true
},
paramsAsHash : true,
proxy : {
type: "direct",
autoLoad: false,
api : {
read: registratorAction.getScheduleNode
},
reader: {
type: "json",
root : "records",
totalProperty: 'total'
}
}
});
Ext.define("...ScheduleTree", {
extend: "Ext.data.Model",
...
associations: [
{
type: "hasMany",
model: "Unimed.model.staff.Schedule",
name: "schedules",
getterName: "schedules"
}
]
});
Ext.define("...Schedule", {
extend: "Ext.data.Model",
fields: [
{name: "timeBegin", type: "date", dateFormat: "time"},
{name: "timeEnd", type: "date", dateFormat: "time"}
],
proxy: {
type: "direct",
reader: {
type: "json"
}
},
associations: [
{
type: "belongsTo",
model: "..LpuPosition",
associationKey: "lpuPosition",
getterName: "lpuPosition",
associatedName: "lpuPosition"
},
{
type: "belongsTo",
model: "...Chamber",
associationKey: "chamber",
getterName: "chamber",
associatedName: "chamber"
}
]
});
When i'm getting chamber:
chamber = schedule.chamber();
and there is no linked data i'm getting exception: 'Uncaught TypeError: undefined is not a function'.
I can make workaround by looking raw data, but may be there exists more elegance solution?
Related
I have a API that sends out a paginated result of data and I want it to be consumed my Ext JS app but I don't know how to supply the needed parameters.
Here is the response I expect:
{
"currentPage": 1,
"from": 1,
"items": [
{
"id": 1,
"customer": "Customer 1",
"movie": "Movie 1",
"dateRented": "2021-01-25T01:22:42.143",
"dateReturned": "2021-01-25T01:22:50.447"
},
{
"id": 2,
"customer": "Customer 2",
"movie": "Movie 2",
"dateRented": "2021-01-25T01:22:42.15",
"dateReturned": "2021-01-25T01:22:54.573"
}
],
"pageSize": 2,
"to": 2,
"totalCount": 1000003,
"totalPages": 500002,
"hasPreviousPage": false,
"hasNextPage": true
}
Here is the endpoint:
/api/Rentals/{currentPage}/{pageSize}
Here is my Ext store but I don't know how I will be able to pass the value for currentPage and pageSize:
Ext.define('Vidly.store.PagedRentals', {
extend: 'Ext.data.Store',
alias: 'store.pagedrentals',
storeId: 'pagedrentals',
model: 'Vidly.model.PagedRental',
autoLoad: true,
autoSync: true,
proxy: {
type: 'rest',
url: 'https://localhost:44313/api/Rentals/',
useDefaultXhrHeader: false,
reader: {
type: 'json',
headers: { 'Accept': 'application/json' },
},
writer: {
type: 'json',
writeAllFields: true
}
},
});
And here is the model:
Ext.define('Vidly.model.PagedRental', {
extend: 'Ext.data.Model',
fields: [
{ name: 'currentPage', type: 'int' },
{ name: 'from', type: 'int' },
{ name: 'to', type: 'int' },
{ name: 'pageSize', type: 'int' },
{ name: 'totalCount', type: 'int' },
{ name: 'totalPages', type: 'int' },
],
hasMany: 'Rental',
});
I hope someone can help me with my problem. Thank you.
Ext's rest proxy is designed to use standard REST APIs where paging and filtering options are passed in as query parameters. I.e. something like
https://localhost:44313/api/Rentals?start=1&limit=25
I would recommend to use this approach rather than a non standard REST API. It will enable you to use Ext's related features seamlessly.
If there is no way to change the API and you need to stick with your current server configuration then you need to create a custom proxy overriding some of the related functions. The best bet if you override the buildUrl function and pass your custom generated URL to the request object.
UPDATE
You can start with this code (also created a Fiddle):
Ext.define('Yournamespace.proxy.custom', {
extend: 'Ext.data.proxy.Rest',
alias: 'proxy.custom',
buildUrl: function(request) {
const url = this.callParent([request]);
const operation = request.getOperation();
console.log(url, this.getParams(operation))
return url;
}
});
Ext.define('User', {
extend: 'Ext.data.Model',
});
Ext.application({
name : 'Fiddle',
launch : function() {
var myStore = Ext.create('Ext.data.Store', {
model: 'User',
pageSize: 10,
proxy: {
type: 'custom',
url: 'https://localhost:44313/api/Rentals/',
reader: {
type: 'json',
rootProperty: 'users'
}
},
autoLoad: true
});
}
});
You can write your custom code to the buildUrl function. Currently only the default URL and the params are collected and logged there but it does the default stuff. You can tweak the URL here and return the new URL at the end.
Below code works fine with the data as in ReadOrder.json (below), however how to read the associated object when it is nested inside another object as in ReadOrderNested.json(below, within 'collection').
Question is more specifically can we use a mapping property or proxy's reader config with rootProperty (tried this approach with no luck)
Sencha fiddle : https://fiddle.sencha.com/#fiddle/9fb
Extjs version : 5.0.0
//Base Model
Ext.define('MyApp.model.Base', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int'
}],
schema: {
namespace: 'MyApp.model'
}
});
//Order Model
Ext.define('MyApp.model.Order', {
extend: 'MyApp.model.Base',
fields: [{
name: 'customer',
type: 'string'
}, {
name: 'paymentStatus',
type: 'string'
}]
});
//PaymentDetail Model
Ext.define('MyApp.model.PaymentDetail', {
extend: 'MyApp.model.Base',
fields: [{
name: 'orderId',
reference: 'Order'
}, {
name: 'cardNumber',
type: 'string'
}, {
name: 'status',
type: 'string'
}]
});
Ext.define('MyApp.store.OrderStore', {
extend: 'Ext.data.Store',
model: 'MyApp.model.Order',
proxy: {
type: "rest",
url: 'Order.json',
appendId: false,
api: {
create: undefined,
read: 'ReadOrder.json',
update: 'UpdateOrder.json',
destroy: undefined
},
reader: {
type: 'json',
rootProperty: 'order'
},
writer: {
writeAllFields: true,
allDataOptions: {
persist: true,
associated: true
}
}
},
});
Ext.application({
name: 'MyApp',
launch: function() {
var orderStore = Ext.create('MyApp.store.OrderStore');
orderStore.load({
callback: function(records) {
var order = this.first();
debugger;
var paymentDetailList = order.paymentDetails();
paymentDetailList.each(function(paymentDetail) {
//Print initial values of payment detail
console.log(paymentDetail.get('cardNumber'));
console.log(paymentDetail.get('status'));
})
}
});
}
});
Data : ReadOrder.json
{ "success": true,
"order": [{
"id": 1,
"customer": "Philip J. Fry",
"paymentStatus": "AWAIT_AUTH",
"paymentDetails": [{
orderId : 1,
"cardNumber": "4111111111",
"status": 'CREATED'
}, {
orderId : 1,
"cardNumber": "4222222222",
"status": "CREATED"
}]
}]
}
How to read with this data when the associated object is nested inside 'collection', ReadOrderNested.json:
{ "success": true,
"order": [{
"id": 1,
"customer": "Philip J. Fry",
"paymentStatus": "AWAIT_AUTH",
"paymentDetails": {
"collection" : [{
orderId : 1,
"cardNumber": "4111111111",
"status": 'CREATED'
}, {
orderId : 1,
"cardNumber": "4222222222",
"status": "CREATED"
}]}
}]
}
I am using ExtJS 4, dunno whether there is a difference. I am using a model with fields like this:
fields: [{
name: 'id',
type: 'int'
},{
name: 'paymentDetails'
}],
and when loading one model into a form
form.load(record);
Ext.getStore("paymentDetailsStore").removeAll();
Ext.getStore("paymentDetailsStore").loadRawData(record.get("paymentDetails"));
with paymentDetailsStore bound to a grid which is in the same window as the form.
I have a problem with loading data from store. Please tell me what I do wrong. I am using ExtJS 4.1.
Request sends properly, i haven't troubles like file not found or something like that. It also works if I had few stores, and any of this stores loading one 'data type' to his model, for example urls1. But if I have one store and one big model, data don't display.
I have a JSON like this:
{
"root": {
"tName": "name",
"urls1": [{
"url": "http:// ..... :09'"
}, {
"url": "http:// ..... :10'"
}],
"perS": "",
"perD": "",
"urls2": [{
"url": "http:// ..... :0009'"
}, {
"url": "http:// ..... :0010'"
}],
"val2": "",
"list2": [{
"level": "lvl1"
}, {
"level": "lvl2"
}],
"types": [{
"type": "type2"
}, {
"type": "type4"
}],
"accs": [{
"login": "login",
"pass": "p1",
"port": "8858",
"conType": "type3",
}, {
"login": "login3",
"pass": "p13",
"port": "88583",
"conType": "type2",
}]
}
}
My Model:
Ext.define('ACT.model.myModel', {
extend: 'Ext.data.Model',
fields: [
{name: 'tname'},
{name: 'urls1'},
{name: 'psec'},
{name: 'pday'},
{name: 'urls2'},
{name: 'list2'},
{name: 'types'},
{name: 'accs'},
]
});
My Store:
Ext.define('ACT.store.dataStore', {
extend: 'Ext.data.Store',
storeId:'mStore',
model: 'ACT.model.myModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: 'resources/data/configuration/MyConfig.json',
reader: {
type: 'json',
root: 'root',
successProperty: 'success'
}
}
});
and my initComponent function in view:
initComponent: function() {
var me = this;
this.columns = [
{
xtype: 'checkcolumn',
text: ' ',
width: 100,
sortable: false,
hideable: false,
allowBlank: false
},
{
text: 'URL',
width: '85%',
dataIndex: 'urls1',
sortable: true,
hideable: false
}]
this.callParent(arguments);
}
});
The above should load urls1 into the store correctly, however, the data type is array. So the data is in the store but it is only not displayed in the grid as dataIndex points to that array.
You can create another model for urls and associate it with the master model.
I was not able to show <div>{lat}, {lon}, {ele}</div> on a sencha touch usingEXT.dataview.List ItemTpl with data from a Json File:
Json:
{
"data": {
"trackData":
[
{
"lon": 9.979255199432373,
"lat": 53.56595538391044,
"ele": 19
},
{
"lon": 9.973998069763184,
"lat": 53.56923037464335,
"ele": 15
}
]
}
}
Model:
Ext.define('Fahrradtour.model.Location', { extend: 'Ext.data.Model',
config: {
fields: [
{
name: 'lat',
type: 'float'
},
{
name: 'lon',
type: 'float'
},
{
name: 'ele',
type: 'float'
}
]
}
});
Store:
Ext.define('Fahrradtour.store.LocationStore', { extend: 'Ext.data.Store',
requires: [
'Fahrradtour.model.Location'
],
config: {
autoLoad: true,
model: 'Fahrradtour.model.Location',
storeId: 'LocationStore',
proxy: {
type: 'ajax',
url: './data/json-track.json',
reader: {
type: 'json',
rootProperty: 'data',
record: 'trackData'
}
}
}
});
the Store loads his data in Architect well, but the List shows nothing.
anybody has an Idea what is wrong?
thanks.
I have a model like this:
Ext.define('Policy', {
extend: 'Ext.data.Model',
fields: [
{
name: 'id',
type: 'sting',
phantom: true,
convert: function(value, record) {
return record.get('a') + '#' +
record.get('b');
}
},
{name: 'a', type: 'string'},
{name: 'b', type: 'string'}]
});
Where the PK of each record is a and b. The store looks like this:
Ext.define('Store', {
extend: 'Ext.data.Store',
model: 'Policy',
autoLoad: true,
proxy: {
type: 'rest',
simpleSortMode: true,
batchActions: true,
reader: {
type: 'json',
root: 'data',
idProperty: 'id'
},
writer: {
nameProperty: 'mapping'
},
api: {
create:'/batch',
read: '/policies',
update: '/batch',
destroy: '/batch'
}
}
});
How can I configure the store so that when it POSTS to /batch when calling store.sync(), the payload looks like this and only consists of dirty records:
{
"policies": [{
"a": "AA",
"b": "BB",
}, {
"a": "AAA",
"b": "BBB"
},...]
}
where there is a policies property and under it is an array of dirty policies.
You can create whatever structure you want by making a manual Ext.Ajax() call. You have to submit only the dirty records yourself.