Extjs 5, data model association & load nested data - javascript

trying to make this work....
I want to load nested data on two object model
Ext.application({
name : 'MyApp',
launch : function() {
Ext.define('MyApp.model.Address', {
extend: 'Ext.data.Model',
entityName: 'Address',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'addressLine',
type: 'string'
},
{
name: 'city',
type: 'string'
},
{
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}
]
});
Ext.define('MyApp.model.User', {
extend: 'Ext.data.Model',
entityName: 'User',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'address',
reference: 'Address'
},
{
name: 'name',
type: 'string'
},
{
name: 'lastname',
type: 'string'
},
{
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}
]
});
var user = new MyApp.model.User({
"id": 1,
"name": "Pedro",
"lastname": "Carbonell",
"address": {
"id": 1,
"addressLine": "Bailen 22",
"city": "Barcelona",
"created": 1420668866000
},
"created": 1420668866000
});
console.info(user);
console.info(user.getAddress());
}});
It's result on no error when created the user, but when I access to associated data via user.getAddress() it returned an exception:
Uncaught Error: The model ID configured in data ("[object Object]") has been rejected by the int field converter for the id fieldext-all-debug.js
Try to define proxy like memory or localstorage on model definitions, but the result it is the same.
Ext fiddle: https://fiddle.sencha.com/#fiddle/h2d
Any help will be appreciated!

Solved, but only find this solution: when use loadRawData...
var store = new Ext.data.Store({
model: MyApp.model.User
});
store.loadRawData({
"id": 1,
"name": "Pedro",
"lastname": "Carbonell",
"address": {
"id": 1,
"addressLine": "Bailen 22",
"city": "Barcelona",
"created": 1420668866000
},
"created": 1420668866000
});
console.info(store.first());
console.info(store.first().getAddress());
sample at this new fiddle: https://fiddle.sencha.com/#fiddle/h4e
you'r right, ext is a bit flaky, very....

I've been playing around with the code in your fiddle and not been able to get the association working the official way as of yet.
I simulated the functionality using this code:
Ext.define('MyApp.model.User', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int'
}, {
name: 'name',
type: 'string'
}, {
name: 'lastname',
type: 'string'
}, {
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}],
getAddress: function() {
if ('undefined' === this.data.address) {
return null;
}
return Ext.create('Address', this.data.address);
}
});
Basically I've removed the association and created a custom function to create a model record based off of the raw data passed in, You could also return a new, empty model if the address data does not exist instead of null, I used null as it's easier to determine whether you have a valid address record or not.
As already mentioned - this is not the official way to do this, I will have another play around with the fiddle and post a better solution once I find it, this may help in the meantime.

Using the original code, I made a few modifications and now it appears to be working.
Ext.application({
name : 'MyApp',
launch : function() {
Ext.define('MyApp.model.Address', {
extend: 'Ext.data.Model',
//entityName: 'Address',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'addressLine',
type: 'string'
},
{
name: 'city',
type: 'string'
},
{
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}
],
hasMany: 'User'
});
Ext.define('MyApp.model.User', {
extend: 'Ext.data.Model',
//entityName: 'User',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'name',
type: 'string'
},
{
name: 'lastname',
type: 'string'
},
{
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}
],
hasMany: { model: 'Address', name: 'Address' }
});
var user = new MyApp.model.User({
"id": 1,
"name": "Pedro",
"lastname": "Carbonell",
"address": {
"id": 1,
"addressLine": "Bailen 22",
"city": "Barcelona",
"created": 1420668866000
},
"created": 1420668866000
});
console.info(user);
console.info(user.data.address);
}
});

Is this the sort of thing you're after? I set Address manually on the User model. Not ideal but it's interpreted correctly as a record then.
Ext.define('MyApp.model.Address', {
extend: 'Ext.data.Model',
entityName: 'Address',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'addressLine',
type: 'string'
},
{
name: 'city',
type: 'string'
},
{
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}
]
});
Ext.define('MyApp.model.User', {
extend: 'Ext.data.Model',
entityName: 'User',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'addressId',
reference: 'Address'
},
{
name: 'name',
type: 'string'
},
{
name: 'lastname',
type: 'string'
},
{
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}
]
});
var user = new MyApp.model.User({
"id": 1,
"name": "Pedro",
"lastname": "Carbonell",
"created": 1420668866000
});
var addr = new MyApp.model.Address({
"id": 1,
"addressLine": "Bailen 22",
"city": "Barcelona",
"created": 1420668866000
});
user.setAddress(addr);
console.info(user);
console.info(user.getAddress());

Related

Sanity.io GROQ - Retrive document by highest reference count in other documents

I have a tag document that looks like
{
name: 'tag',
title: 'Tag',
type: 'document',
fields: [
{
name: 'label',
title: 'Label',
type: 'string',
}
]
}
And page document that looks like
{
name: "page",
title: "Page",
type: "document",
fields: [
{
name: "title",
title: "Title",
type: "string",
},
{
name: "tags",
title: "Tags",
type: "array",
of: [{ type: "reference", to: [{ type: "tag" }] }],
}
]
}
And another article document that looks like
{
name: "article",
title: "Article",
type: "document",
fields: [
{
name: "title",
title: "Title",
type: "string",
},
{
name: "description",
title: "Description",
type: "text",
},
{
name: "tags",
title: "Tags",
type: "array",
of: [{ type: "reference", to: [{ type: "tag" }] }],
}
]
}
I am unable to figure out how to get the tags with the highest reference count used across pages and articles
An extension of this question would be to get the top 10 highest tags used across the site.
I've been struggling for a while now. Any help would be appreciated.
Thank you team.
You can likely accomplish this by constructing a query that first gets all tags, then uses the count function to further filter them. Something like the following:
*[_type == 'tag'] {
...,
'totalReferences': count(*[_type in ['page', 'article'] && references(^._id))
} | order(totalReferences desc) [0...10]
This may not be very performant in very large datasets, though.

How to filter references based on change in another reference?

I have created an object with 3 reference fields - categories, subcategories, and types. I want the subcategories to show subcategories related to the selected category.
{
title: "Product Category",
name: "category",
type: "object",
fields: [
{
name: "categories",
type: "reference",
to: [
{
type: "categories",
},
],
},
{
name: "subcategories",
type: "reference",
to: [
{
type: "subcategories",
},
],
},
{
name: "types",
type: "reference",
to: [
{
type: "types",
},
],
},
],
},
I tried the filter option as mentioned in docs but can't seem to get it working so I removed it.
This is how I defined the categories and subcategories.
// categories.js
export default {
name: "categories",
type: "document",
title: "Categories",
fields: [
{
name: "category",
type: "string",
title: "Category name",
},
{
name: "slug",
title: "Slug",
type: "slug",
description: "URL friendly name",
options: {
source: "category",
maxLength: 96,
},
},
{
title: "Description",
name: "description",
type: "text",
},
],
};
// subcategories.js
export default {
name: "subcategories",
type: "document",
title: "Subcategories",
fields: [
{
name: "subcategory",
type: "string",
title: "Subcategory name",
},
{
name: "slug",
title: "Slug",
type: "slug",
description: "URL friendly name",
options: {
source: "subcategory",
maxLength: 96,
},
},
{
name: "categories",
type: "reference",
to: [
{
type: "categories",
},
],
},
],
};
Any help is appreciated.
Based on your schema, I think this should work:
export default {
title: "Product Category",
name: "category",
type: "object",
fields: [
{
name: "categories",
type: "reference",
to: [
{
type: "categories",
},
],
},
{
name: "subcategories",
type: "reference",
to: [
{
type: "subcategories",
},
],
options: {
filter: 'references($category._id)',
filterParams: {category: 'categories'}
}
},
{
name: "types",
type: "reference",
to: [
{
type: "types",
},
],
},
],
}
This adds the filter and filterParams to the options object on the subcategories field. This should narrow down the items that is selectable in the reference picker.
EDIT:
This should get the job done for you. It will also not yield any results if categories isn't set already:
export default {
title: 'Product Category',
name: 'category',
type: 'object',
fields: [
{
name: 'categories',
type: 'reference',
to: {type: 'categories'}
},
{
name: 'subcategories',
type: 'reference',
to: {type: 'subcategories'},
options: {
filter: ({ document }) => {
console.log(document)
if (!document.category || !document.category.categories) {
return;
}
return {
filter: "categories._ref == $category",
params: {
category: document.category.categories._ref,
}
}
}
}
}
]
}

How to implemented a nested and associated model-json into selectfield in Sencha Touch?

I have a store with associated model and I need to include values of this associated model into selectfield component in Sencha Touch.
Here my parent model:
Ext.define('x.customer.model.CustomerModel', {
extend: 'Ext.data.Model',
requires:[
'x.customer.model.CustomerTemplateModel'
],
config: {
useCache: false,
idProperty: 'id',
fields: [
{
name: 'id',
type: 'string'
},
{
name: 'address',
type: 'string'
},
{
name: 'name',
type: 'string'
},
{
name: 'type',
type: 'int'
}
],
associations: [
{
type: 'hasMany',
associatedModel: 'Survey.customer.model.CustomerTemplateModel',
ownerModel: 'Survey.customer.model.CustomerModel',
associationKey: 'templates',
autoLoad: true,
name: 'templates'
}
]
}
});
and the children model:
Ext.define('x.customer.model.CustomerTemplateModel', {
extend: 'Ext.data.Model',
requires:[],
config: {
useCache: false,
rootProperty: 'templates',
fields: [
{
name: 'text',
type: 'string'
},
{
name: 'value',
type: 'string'
}
]
}
});
store:
requires: ['Survey.customer.model.CustomerModel'],
config: {
model: 'Survey.customer.model.CustomerModel',
proxy: {
type: 'ajax',
reader: {
type: 'json',
rootProperty: 'customers'
}
}
}
Currently the json has this structure:
{
"id": "00000001",
"address": "Antsy Road",
"name": "asfas",
"phone": "55555",
"openSurveys": 7,
"templates": [
{
"text": "123",
"value": "Template 1"
}
],
"type": 1,
"withSurveys": true
},
how to implement data included in the "templates" nested json in a selectfield?
thank you in advance
Once your store loaded and if you have one custommer:
var templatesData = []; // What will be inserted to the ComboBox
for (var i=0; i < custommers[0].get('templates').length; i++) { // Running threw the values and populating templatesData
var templateModel = custommers[0].get('templates')[i];
var templateCombo = {
text: templateModel.data.text,
value: templateModel.data.value
};
templatesData.push(templateCombo);
}
// Setting the values to the combobox
Ext.getCmp('myCombo').setStore(Ext.create("Ext.data.Store", {
model: 'x.customer.model.CustomerTemplateModel',
data :templatesData
}));
This is not a unique solution, you could create a new instance of store as well. Here is more information about how setting the "store" property for a combobox : http://docs.sencha.com/extjs/4.1.3/#!/api/Ext.form.field.ComboBox-cfg-store

How to use ExtJS 5 Ext.data.Model Field reference (in comparison to belongsTo in ExtJS 4)

I use belongsTo in an Ext.data.Model and it works like charm, thread.getCustomer(function(record) {[…]}) loads a customer:
Ext.define('MyApp.model.Thread', {
extend: 'MyApp.model.Base',
requires: [
'MyApp.model.Customer'
],
idProperty: 'thread_id',
fields: [
{name: 'thread_id', type: 'int'},
{name: 'thread_customer_id',type: 'int'},
],
belongsTo: {
model: 'MyApp.model.Customer',
name: 'Customer',
primaryKey: 'customer_id',
foreignKey: 'thread_customer_id'
}
});
However, I get a warning from Ext:
[W] Use of "belongsTo" is obsolete in MyApp.model.Thread
I tried to translate it to a reference in the field definition:
Ext.define('MyApp.model.Thread', {
extend: 'MyApp.model.Base',
requires: [
'MyApp.model.Customer'
],
idProperty: 'thread_id',
fields: [
{name: 'thread_id', type: 'int'},
{
name: 'thread_customer_id',
type: 'int',
reference: 'MyApp.model.Customer'
}
]
});
or
reference: {
type: 'MyApp.model.Customer',
role: 'customer',
association: 'Customer',
inverse: 'thread'
}
or
reference: {
type: 'Customer',
role: 'customer',
association: 'Customer',
inverse: 'thread'
}
does not work.
Nothing helpful found in
http://docs.sencha.com/extjs/5.0/core_concepts/data_package.html
or
http://docs.sencha.com/extjs/5.0/whats_new/5.0/extjs_upgrade_guide.html
Any of you had any luck with it?
I had exactly the same problem, this link helped me:
http://www.sencha.com/forum/showthread.php?285478-Nested-stores-associated-model-doesn%C2%B4t-contain-any-store
It gave me this:
Ext.define('MyApp.model.Base', {
extend: 'Ext.data.Model',
schema: {
namespace: 'MyApp.model'
}
});
Ext.define('MyApp.model.Application', {
extend: 'MyApp.model.Base',
fields: [
{ name: 'id', type: 'int' },
{ name: 'name', type: 'auto' },
{ name: 'desc', type: 'auto' }
]
});
Ext.define('MyApp.model.ApplicationVersion', {
extend: 'MyApp.model.Base',
fields: [
{ name: 'id', type: 'int' },
{
name: 'appid',
type: 'int',
reference: {
type: 'Application',
role: 'application',
inverse: 'versions'
}
},
{ name: 'version', type: 'auto' }
]
});
And now I have a one-to-many association which works:
> a = Ext.create(MyApp.model.Application, {desc: 'My description'})
constructor {data: Object, session: null, internalId: 30, …}
> a.versions().add({version: '2.5'})
[constructor]
> a.versions().first().application.get('desc')
"My description"

ExtJS 3.3 Format.Util.Ext.util.Format.dateRenderer returning NaN

The Store
var timesheet = new Ext.data.JsonStore(
{
root: 'timesheetEntries',
url: 'php/scripts/timecardEntry.script.php',
storeId: 'timesheet',
autoLoad: true,
fields: [
{ name: 'id', type: 'integer' },
{ name: 'user_id', type: 'integer' },
{ name: 'ticket_number', type: 'integer' },
{ name: 'description', type: 'string' },
{ name: 'start_time', type: 'string' },
{ name: 'stop_time', type: 'string' },
{ name: 'client_id', type: 'integer' },
{ name: 'is_billable', type: 'integer' }
]
}
);
A section of my GridPanel code:
columns: [
{
id: 'ticket_number',
header: 'Ticket #',
dataIndex: 'ticket_number'
},
{
id: 'description',
header: 'Description',
dataIndex: 'description'
},
{
id: 'start_time',
header: 'Start',
dataIndex: 'start_time',
renderer: Ext.util.Format.dateRenderer('m/d/Y H:i:s')
}
...
From the server, I receive this JSON string:
{
timesheetEntries:[
{
"id":"1",
"user_id":"1",
"description":null,
"start_time":"2010-11-13 11:30:00",
"stop_time":"2010-11-13 15:50:10",
"client_id":null,
"is_billable":"0"
}
My grid panel renders fine. However, my start and stop time columns read 'NaN/NaN/NaN NaN:NaN:NaN' and I don't know why.
If your data has "2010-11-13 11:30:00" shouldn't your format be 'Y-m-d H:i:s'?
EDIT: Sorry, the grid config should be OK -- I was referring to the dateFormat value in your store's field definition, which should be 'Y-m-d H:i:s' so that your incoming data can be properly mapped to your column model. You should also include type: 'date'. You're not showing your store config, but the problem is likely one of those things being wrong.
Try this
function renderDate(v,params,record)
{
var dt = new Date(v);
if (!isNaN(dt.getDay())) {
return dt.format('d/m/Y');
}
return '-';
}
A very simple way to do it:
return Ext.util.Format.date(val,'m/d/Y');

Categories

Resources