ExtJS 4 introduced Sencha’s wonderful data model. One aspect of that is Associations which let you define relationships between different models in your application. It’s a powerful feature with only two, minor side effects.
Again, minor issues on an otherwise great feature of the framework. This article covers the latter of the issues.
In my example, I have Documents, to which Components can be assigned. In our Natural Language Processing [NLP] model building application, each document can be used to train different aspect of the model. However, Components can change, be erased from the system, or new ones can be added, so I’m tracking those as a separate object and associating them to the Document object.
/**
* A simple document Model.
*/
Ext.define("BigData.Document", {
extend: "Ext.data.Model",
fields: [
{ name: "id", type: "int" },
{ name: "filetype", type: "string" },
{ name: "filename", type: "string" },
{ name: "size", type: "int" }
],
hasMany: { model: "Component", name: "components" }
});
/**
* Each document has n Components, the number, and value,
* of which can be modified over time, so I'm not hard
* coding those fields directly in the document.
*/
Ext.define("BigData.Component", {
extend: "Ext.data.Model",
fields: [
{name: "id", type: "int"},
{name: "name", type: "string"}
]
});
Now that the models have a relationship, I create a store for the Documents the user wants to manage.
/*
* Create a SimpleDocumentStore
*/
SimpleDocumentStore = Ext.create("Ext.data.Store", {
model: "Document",
proxy: { type: "memory", reader: { type: "json" } }
});
Once the models and stores are set up, you can create a Document object, and assign one, or more, Components to it.
/**
* Create a document
*/
var SimpleDocument = BigData.Document.create({ id: 1, filename: "sample.txt", filetype: "user-defined", size: 10221 });
/**
* Create an instance of the document's components
*/
var DocComponents = SimpleDocument.components();
/**
* Add some components to the document
*/
var TitleComponent = BigData.Component.create({ id: 23, name: "Title" });
var BodyComponent = BigData.Component.create({ id: 23, name: "Body" });
DocComponents.add([TitleComponent, BodyComponent]);
// Add the document to the store
SimpleDocumentStore.add(SimpleDocument);
Now I want to display a grid that is tied to the Document store, but also have columns for each Component and show which components were assigned to each of the Documents. To do this, I define a column for each Component and then define a custom renderer for each one. This renderer function looks for each specific Component in the Document’s associated store and simply marks the cell with an ‘X’.
/**
* Now when you want to render those components in a grid, you need a custom
* render function, because the components aren't direct properties of a Document.
*/
xtype: "grid",
store: SimpleDocumentStore,
columns:[{
header: "Name",
dataIndex: name,
width: 100
},{
header: "Title",
width: 60,
renderer : function (value, cell, doc, idx) {
var components;
if (doc.hasOwnProperty("componentsStore")) {
components = doc.componentsStore;
if (components.findExact("id", "Title") !== -1) {
return "X";
}
}
}
},{
header: "Body",
width: 90,
renderer : function (value, cell, doc, idx) {
var components;
if (doc.hasOwnProperty("componentsStore")) {
components = doc.componentsStore;
if (components.findExact("id", "Body") !== -1) {
return "X";
}
}
}
}]
2 Responses for "ExtJS 4: Render association values in a grid panel"
Hi
var DocComponents = SimpleDocument.components();
on this line i am getting this error
Uncaught TypeError: Object [object Object] has no method ‘components’
Can you please what is the problem because i am simply copy pasting your code. Thanks
Hi
var DocComponents = SimpleDocument.components();
on this line i am getting this error
Uncaught TypeError: Object [object Object] has no method ‘components’
Can you please what is the problem because i am simply copy pasting your code. Thanks
Leave a reply