How to bind dynamic select options for each row in jsGrid? - javascript

i try to bind select option dynamically from database,
for example:
$("#grid").jsGrid({
editing: true,
autoload: true,
paging: false,
pageLoading: true,
data: result,
fields: [
{ name: "Units", type: "select", title: "Units", items: ? },
]
});
but What's the data format to create select with options.
i try "itemTemplate" but didn't work well.

Build your select list before you instantiate the grid. Example:
const units = [ { id: 0, name: "cm"}, { id: 1, name: "inch" } ];
$("#grid").jsGrid({
// ...
fields: [
{ name: "Units", type: "select", title: "Units",
items: units, valueField: "id", textField: "name" },
]
});
Working demo at JSFiddle.
If you are talking about different rows having different drop down lists for the same column, then the built-in select type may not be useful. You have to render the editTemplate yourself. A simple working example is in this JSFiddle.

Related

ExtJS Add filtering in Grid for hasMany association

I have a data model that I want to be able to add a generic amount of filters to. I am specifying a name and a value. How can I add these hasMany associated fields as filters to my grid? I have attempted to write custom filtering option, but I can't have filters show up without an attached dataIndex, which is not available for the hasMany association.
Ext.define('AirGon.model.Project', {
extend: 'Ext.data.Model',
fields: [
{ name: 'Link', type: 'string' },
{ name: 'Title', type: 'string' },
{ name: 'Description', type: 'string' },
{ name: 'MappedMetadata', mapping: 'Metadata'},
{ name: 'XMax', type: 'float' },
{ name: 'XMin', type: 'float' },
{ name: 'YMax', type: 'float' },
{ name: 'YMin', type: 'float' }
],
hasMany: { model: 'Metadata', name: 'Metadata', associationKey: 'Metadata' }
});
Ext.define('Metadata', {
extend: 'Ext.data.Model',
fields: ['Name', 'Value']
});
This is my custom filtering attempt. I am getting the DataStore from the main store and then adding custom rendering, but I can't filter or sort this column because of the lack of a dataIndex.
var column = {
header: 'Meta',
//?????????dataIndex: 'MappedMetadata[0]',?????
sortable: true,
filterable: true,
filter: {
type: 'string'
},
renderer: function (value, meta, record) {
console.log(record.MetadataStore.data.items[index].data)
return record.MetadataStore.data.items[index].data.Value;
}
}
Data. The data is modeled so that a variable amount of metadata can be entered and the 'tag' will not be known by the system.
{
"Link": "link.com",
"Title": "project",
"Description": "descript",
"State": "",
"Metadata": [
{
"Name": "County",
"Value": "32"
},
{
"Name": "Info",
"Value": "info"
},
{
"Name": "State",
"Value": "TN"
}
],
"XMin": "-1",
"XMax": "-1",
"YMin": "1",
"YMax": "1"
}
I was able to solve this by dynamically flattening the data model and adding columns once the store has been loaded. Although this breaks the MVC structure this was the best solution I came up with so it might be able to help you.
var defaultColumns = [];
var store = Ext.getStore('store');
store.on('load', function (store) {
var model = store.model;
var fields = model.getFields();
store.getAt(0).MetadataStore.data.items.forEach(function (item, index) {
var header = item.data.Name;
//isField returns a boolean if the field is already part of the data model
if (!isField(fields, header)) {
//Add a new metadata field to the data model
var field = { name: header, mapping: 'Metadata[' + index + '].Value' }
fields.push(field)
//Add a new metadata column
var column = {
header: header,
dataIndex: header,
sortable: true,
filterable: true,
filter: {
type: 'list'
},
flex: 0.2
}
defaultColumns.push(column);
}
});
model.setFields(fields);
//reload the grid after adding columns
var gridView = Ext.ComponentQuery.query('gridpanel')[0];
gridView.reconfigure(store, defaultColumns);
});
//reload the data after creating new fields
store.load();
I then set the columns of the grid to defaultColumns.
{
xtype: 'grid',
store: 'Projects',
overflowX: 'auto',
autoScroll: true,
features: [filters],
columns: defaultColumns
}

In Extjs grid On options select from combo box, it removes selection of all records from grid

On Combo select from options, it removes selection of all records from grid and even it removes selection of current record also when you finish your editing.
Select all row from table.
click on last column cell, it will show you combo box to edit cell and at same time all other records get deselected this is one issue.
Now select value from combo box and click on any other record or somewhere, you'll notice that edited row also get deselected
I'm using 4.1.* Extjs and i have tried to override celledit plugin as well CheckboxModel.
Is there any way to keep records selected until and unless i'm not specifically deselect it from checkbox column.
Any help will be appreciated and thanks in advance
here is what I have done on the fiddle
https://fiddle.sencha.com/#view/editor&fiddle/1u9i
Hey man I forked your fiddle and made some change that I think solve your problem:
https://fiddle.sencha.com/#view/editor&fiddle/27ua
Basically I added a viewConfig to the grid with a cellclick event listener. The cellclick event fires first; in the event handler we check the value of the cellIndex parameter in order to determine which grid column was clicked to fire the event. We then set the value of our flag variable to the cellIndex value, so we can access that value in the beforedeselect event handler of the selection model. Finally we return false from the beforedeselectif the value of the flag is anything other than 0.
Here's the code:
var store = Ext.create('Ext.data.Store', {
fields: ['name', 'email', 'region'],
data: [{
name: 'xyz',
email: 'xyz#xyz.com',
region: 'Arizona'
}, {
name: 'xyz',
email: 'xyz#xyz.com',
region: 'Alaska'
}, {
name: 'xyz',
email: 'xyz#xyz.com',
region: 'Alaska'
}, {
name: 'xyz',
email: 'xyz#xyz.com',
region: 'Alabama'
}]
});
var states = Ext.create('Ext.data.Store', {
fields: ['abbr', 'name'],
data: [{
"abbr": "AL",
"name": "Alabama"
}, {
"abbr": "AK",
"name": "Alaska"
}, {
"abbr": "AZ",
"name": "Arizona"
}]
});
var targetedCell = -1;
Ext.create('Ext.grid.Panel', {
id: 'theGrid',
viewConfig: {
listeners: {
cellclick: function(view, cell, cellIdx, record, row, rowIdx, eOpts) {
targetedCell = cellIdx;
}
}
},
title: 'data',
store: store,
width: 400,
renderTo: Ext.getBody(),
selModel: new Ext.selection.CheckboxModel({
checkOnly: true,
listeners: {
beforedeselect: function (thisSelModel, record, idx, eOpts) {
if(targetedCell != 0) {
return false;
}
return true;
}
}
}),
columns: [{
text: 'Name',
dataIndex: 'name',
}, {
text: 'Email',
dataIndex: 'email',
flex: 1,
}, {
text: 'State',
dataIndex: 'region',
editor: {
xtype: 'combo',
store: states,
displayField: 'name',
valueField: 'name',
listeners: {}
}
}],
plugins: {
ptype: 'cellediting',
clicksToEdit: 1
}
});

How to display nested objects in a GridPanel in ExtJS (and Sencha architect)?

I've got an incoming array of Offering objects that looks like this:
[{
"id" : 16,
"price" : 500,
"quantity" : 2000,
"denomination" : "case",
"denominationPlural" : "cases",
"product" : {
"id" : 14,
"description" : "This is the text description for product 14."
}
}, {
"id" : 18,
"price" : 500,
"quantity" : 1,
"denomination" : "study",
"denominationPlural" : "studies",
"product" : {
"id" : 17,
"description" : "This is a text description for product 17."
}
}]
An Offering is a Product times a quantity for a price.
Now I want to display these Offerings in a GridPanel, but also include the nested product information in those rows. Here's how I was doing it before:
Ext.define('Offering', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'number'},
{name: 'price', type: 'number'},
{name: 'quantity', type: 'number'},
{name: 'denomination', type: 'string'},
{name: 'denominationPlural', type: 'string'},
{name: 'product.description', type: 'string'},
]
});
var offeringStore = Ext.create('Ext.data.Store', {
autoDestroy: true,
model: 'Offering',
proxy: {
type: 'ajax',
url: '/offerings',
reader: {
type: 'json',
root: 'success'
}
},
autoLoad:true
});
var offeringGrid = Ext.create('Ext.grid.Panel', {
store: offeringStore,
columns: [{
header: 'id',
dataIndex: 'id'
}, {
header: 'price',
dataIndex: 'price'
}, {
header: 'quantity',
dataIndex: 'quantity'
}, {
header: 'denomination',
dataIndex: 'denomination'
}, {
header: 'description',
dataIndex: 'product.description'
},
};
And this worked just fine. Then, somewhere along the way (which included an upgrade to ExtJS 5.1.1 (from ExtJS 4.2.1) and use of Sencha Architect, it broke.
Problem 1: Sencha Architect prevents creating an entry for "product.description" in the Offering Model, complaining about the "." character. But if you create it as "whateveryouwant", you can go into the model field and rename it to "product.description" there.
Problem 2: after working around the "." issue and running the application, the "product.description" column's cells are blank.
Problem 3: the javascript console produces zero errors. The incoming data looks fine.
How should I go about getting this nested data to show up?
The way I do it is quite simple. Just add the mapping attribute to the model this way:
{
name: 'product.description',
type: 'string',
mapping : 'product.description'
}
No need for renderer.
My current workaround, which may help others in the same situation, uses a "renderer" clause to display the information desired.
{
xtype: 'gridpanel',
title: 'Offerings',
bind: {
store: '{OfferingsStore}'
},
columns: [
...
{
xtype: 'gridcolumn',
renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
return record.getData().product.description;
},
text: 'Product Description'
},
...
]
But I'd still like an answer about using "product.description" in the Offering Model definition rather than this rendering trick.

Grief with extJS4 treegrid using custom model and async loading

I just cannot seem to get the tree grid up and running.
I have defined the model, the store and the treegrid (as seen below).
The tree grid shows inside target, the data is loaded async (checked with fiddler, two rows came back) however the treegrid just shows two rows with empty cells.
I tried debugging and the store's root node indeed has two child nodes, the model data is under child's raw property (except some fields such as leaf and iconCls which are also in data property), yet the tree grid shows two empty rows, despite dataIndex pointing to a proper model field.
It's like tree grid cannot find the field defined by the model?!?
Here's the source (I am using sandbox because I am integrating this into salesforce vforce, the salesforce merge fields {!} are also valid and render properly)
Ext4.onReady(function() {
var target = '{!$Component.childBlock.childTreeDiv}';
Ext4.define('ConfigurationItem', {
extend: 'Ext4.data.Model',
fields: [
{
id: 'id',
type: 'string'},
{
id: 'name',
type: 'string'},
{
id: 'recordType',
type: 'string'},
{
id: 'ciName',
type: 'string'},
{
id: 'alias',
type: 'string'},
{
id: 'model',
type: 'string'},
{
id: 'status',
type: 'string'},
{
id: 'description',
type: 'string'},
{
id: 'leaf',
type: 'bool'},
{
id: 'iconCls',
type: 'string'}
]
});
var store = Ext4.create('Ext4.data.TreeStore', {
model: 'ConfigurationItem',
root: {
nodetype: 'async',
id: '{!CI__c.Id}',
expanded: true
},
proxy: {
type: 'ajax',
url: 'json_CIChildren',
reader: {
type: 'json',
root: 'children'
}
}
});
tree = Ext4.create('Ext4.tree.Panel', {
width: document.getElementById(target).offsetWidth,
autoHeight: true,
title: 'Child Configuration Items',
collapsible: true,
titleCollapse: true,
renderTo: target,
rootVisible: false,
store: store,
multiSelect: true,
singleExpand: true,
columns: [
{
type: 'treecolumn',
text: 'CI#',
dataIndex: 'name'},
{
text: 'Type',
dataIndex: 'recordType'}
]
});
});​
The request to json_CIChildren?_dc=1329830854458&node=a0NT0000006tYKzMAM was valid (the parentID in root.id got propagated ok) and came back with valid json:
{ "children" : [
{
"id": "a0NT0000006tswhMAA",
"name": "CI334593834",
"recordType": "Rack",
"ciName": "Empty rack",
"alias": "",
"model": "",
"status": "",
"description": "",
"leaf": "true",
"iconCls": "x4-ciicon-Rack"
},
{
"id": "a0NT0000006tYKuMAM",
"name": "CI2345234",
"recordType": "Service",
"ciName": "Business Connect - Premium",
"alias": "",
"model": "",
"status": "",
"description": "",
"leaf": "true",
"iconCls": "x4-ciicon-Service"
}
]}
What am I doing wrong? Why isn't the treegrid seeing name and recordType fields?
Is this because store only saw NodeInterface-like fields and there is none of my custom data in data property?
I think the problem is your model fields aren't mapped right. The "id" property for each field should be the 'name' property instead.

Displaying values in an ext grid where the values correspond to strings in another table/model

I'm teaching myself ExtJS by building a really simple 'scrum' development tracking application. I'm currently displaying the "Backlog" as a grid panel that displays the properties of the card(user story).
Card.js (Card model)
Ext.define('AM.model.Card', {
extend: 'Ext.data.Model',
fields: [
'id',
'name',
'priority_id',
...
]
});
Priority.js (Priority model)
Ext.define('AM.model.Priority', {
extend: 'Ext.data.Model',
fields: [
'id',
'name',
'short_name'
]
});
So the data for the card will look something like this:
backlogcards.json (data)
{
success: true,
backlogcards: [
{
id: 1,
name: 'ONEs',
priority_id: 2,
...
},
{
id: 2,
name: 'TWOs',
priority_id: 3,
...
}
]
}
And the priorities looks like this:
priorities.json (data)
{
success: true,
priorities: [
{
id : 1,
name : "High",
short_name : "H"
},
{
id : 2,
name : "Medium",
short_name : "M"
},
{
id : 3,
name : "Low",
short_name : "L"
}
]
}
So ideally what I would like to do is have the grid panel display the short_name for the corresponding priority_id. When the item is clicked on to be edited inline, a combo box will be displayed that shows the name property. I'm half way there already.
BacklogList.js (view)
Ext.define('AM.view.card.BacklogList', {
extend: 'Ext.grid.Panel',
alias: 'widget.backlogcardlist',
title: 'Backlog',
store: 'BacklogCards',
selType: 'cellmodel',
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})
],
columns: [
{ header: 'ID', dataIndex: 'id' },
{ header: 'Name', dataIndex: 'name', field: 'textfield' },
{
header: 'Priority',
dataIndex: 'priority_id',
width: 130,
field: {
xtype: 'combobox',
typeAhead: true,
store: 'Priorities',
displayField: 'name',
valueField: 'id',
listClass: 'x-combo-list-small'
}
}
]
});
So I know the 'dataIndex' property is what I need to modify in order to change the display, but I'm not sure how to tie those two stores together.
As you can see above, priority is being displayed as a number instead of the short_name.
Is this a situation where I would need to use associations? (I only know OF them) Sencha Docs
Thank you!
EDIT1: Oh I realize I could 'hard code' a renderer property that does this change, but I would like to avoid that and instead use values from the priorities store.
renderer: function(value){
if (value==3)
{
return "L";
}
else if (value==2)
{
return "M";
}
else
{
return "H";
}
},
EDIT2 for Evan:
Priorities store
Ext.define('AM.store.Priorities', {
extend: 'Ext.data.Store',
model: 'AM.model.Priority',
autoLoad: true,
proxy: {
type: 'ajax',
api: {
read: 'app/data/priorities.json',
update: 'app/data/updateUsers.json'
},
reader: {
type: 'json',
root: 'priorities',
successProperty: 'success'
}
}
});
The store.each refers to this store, right? If so, how do I perform the each operation on it?
I tried changing the declaration line to:
var test = Ext.define('AM.store.Priorities', {
And then tried changing your code to test.each but was unsuccessful.
Thanks again!
You need to use a renderer, however there's nothing stopping you from looping over the values in the priorities store and checking, something like:
renderer: function(value) {
var display = '';
store.each(function(rec){
if (rec.get('id') === value) {
display = rec.get('name');
return false;
}
});
return display;
}

Categories