Creating dependent extjs grids - javascript

I just started to study extjs 6.
How it is possible to implement dependent grids when the main displays data from the table, when clicked on, in the second grid, the dependent entries from the second table are displayed.
What I realized at the moment:
I created a grid, I get the records from the "Operation" table, I call it using the CRUD. In the "Operation" table, all entries are associated with the second table (numoperation) in the code field.
It is required to me that at pressing on record of the main grid which is already created, to receive dependent records from the table numoperation in the second grid.
How can this be implemented in general?
I would be glad if you share useful links, tips or examples.
Thank you in advance.
Below is the code for the client part of the application:
Ext.onReady(function () {
Ext.define('Operation', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [
{ name: 'id', type: 'int' },
'date_op',
'code',
'status',
'type'
]
});
var urlRoot = 'data?model=Operation&method=';
var registrStore = Ext.create('Ext.data.Store', {
model: 'Operation',
pageSize: 10,
proxy: {
type: 'jsonp',
noCache: false,
api: {
create: urlRoot + 'Create',
read: urlRoot + 'Read',
update: urlRoot + 'Update',
destroy: urlRoot + 'Destroy'
},
reader: {
type: 'json',
metaProperty: 'meta',
root: 'data',
idProperty: 'id',
totalProperty: 'meta.total',
successProperty: 'meta.success'
},
writer: {
type: 'json',
encode: true,
writeAllFields: true,
root: 'data',
allowSingle: false,
}
}
});
var rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToEdit: 2,
autoCancel: false,
listeners: {
edit: function (editor, context) {
var emp = registrStore.getProxy();
var con = context.record;
emp.setExtraParam("id", con.data['id']);
emp.setExtraParam("date_operation", con.data['date_operation']);
emp.setExtraParam("code", con.data['code']);
emp.setExtraParam("status", con.data['status']);
emp.setExtraParam("type", con.data['type']);
}
}
});
var textField = {
xtype: 'textfield'
};
// Определение столбцов
var columns = [
{
header: 'ID',
dataIndex: 'id',
sortable: true,
width: 35
},
{
header: 'Дата',
dataIndex: 'date_op',
sortable: true,
editor: textField
},
{
header: 'Код',
dataIndex: 'code',
sortable: true,
editor: textField
},
{
header: 'Статус',
dataIndex: 'status',
sortable: true,
editor: textField
},
{
header: 'Тип',
dataIndex: 'type',
sortable: true,
editor: textField
}
];
var pagingToolbar = {
xtype: 'pagingtoolbar',
store: registrStore,
displayInfo: true,
items: [
'-',
{
text: 'Save Changes',
handler: function () {
registrStore.sync();
}
},
'-',
{
text: 'Reject Changes',
handler: function () {
// Отмена изменений в stoe
registrStore.rejectChanges();
}
},
'-'
]
};
var onDelete = function () {
var selected = grid.selModel.getSelection();
Ext.MessageBox.confirm(
'Confirm delete',
'Are you sure?',
function (btn) {
if (btn == 'yes') {
var nn = selected[0].get('id')
var emp = registrStore.getProxy();
emp.setExtraParam("id", nn)
grid.store.remove(selected);
grid.store.sync();
}
}
);
};
var onInsertRecord = function () {
var selected = grid.selModel.getSelection();
rowEditing.cancelEdit();
var newEmployee = Ext.create("Operation");
registrStore.insert(selected[0].index, newEmployee);
rowEditing.startEdit(selected[0].index, 0);
};
var doRowCtxMenu = function (view, record, item, index, e) {
e.stopEvent();
if (!grid.rowCtxMenu) {
grid.rowCtxMenu = new Ext.menu.Menu({
items: [
{
text: 'Insert Operation',
handler: onInsertRecord
},
{
text: 'Delete Operation',
handler: onDelete
}
]
});
}
grid.selModel.select(record);
grid.rowCtxMenu.showAt(e.getXY());
};
var grid = Ext.create('Ext.grid.Panel', {
title: 'Таблица операций',
items: grid,
columns: columns,
store: registrStore,
loadMask: true,
bbar: pagingToolbar,
plugins: [rowEditing],
stripeRows: true,
selType: 'rowmodel',
viewConfig: {
forceFit: true
},
listeners: {
itemcontextmenu: doRowCtxMenu,
destroy: function (thisGrid) {
if (thisGrid.rowCtxMenu) {
thisGrid.rowCtxMenu.destroy();
}
}
},
renderTo: Ext.getBody()
});
registrStore.load();
});

What you probably want to do is to add a listener on the main grid that listens for the event: select.
https://docs.sencha.com/extjs/6.5.3/modern/Ext.grid.Grid.html#event-select
listeners: {
select: "onSelectMainGrid",
},
then you want to have a function called onSelectMainGrid or something similar
var onSelectMainGrid : function(grid, selectedItem) {
. . .
}
and in this function, you want to get the store from the dependent grids and you want to call the .load() function on them. For your dependent grid's store's proxy, use the config extraParams: {}
https://docs.sencha.com/extjs/6.5.3/modern/Ext.data.Connection.html#cfg-extraParams and bind the selection from the main grid to the extraParams of the dependent grids. Then call the method .load() on the dependent grid's store. The store of your dependent grid will look something like
var dependentGridStore = Ext.create('Ext.data.Store', {
model: 'OperationDependent',
pageSize: 10,
proxy: {
type: 'jsonp',
noCache: false,
extraParams: { // <==THIS IS NEW
valueFromMainGrid: '{selectedValueFromMainGrid}'
}
api: {
create: urlRoot + 'Create',
read: urlRoot + 'Read',
update: urlRoot + 'Update',
destroy: urlRoot + 'Destroy'
},
reader: {
type: 'json',
. . .
. . .
});
I noticed that you have all the code in the same file. It is strongly advised that you separate your code into views, viewModels, and viewControllers.
One last thing, If you don't make use of a viewModel for databinding, alternatively in the onSelectMainGrid function, since you are passing the selectedItem parameter, you can just get the dependent grid, then get its store, then get its proxy, and then set the extraParams to the selectedItem passed as parameter to the function.
Let me know if you need any clarification.

I did so (shortened the code for better perception):
Ext.define('Operation', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [
{ name: 'id', type: 'int' },
'date_operation',
'code',
'status',
'type',
'mesto_hraneniya',
'contragent',
'sum_operation',
'rezerv',
'cnt_doc',
'stellag'
]
});
var urlRoot = 'data?model=Operation&method=';
// Хранилище для данных таблицы Registr
var registrStore = Ext.create('Ext.data.Store', {
model: 'Operation',
pageSize: 10,
proxy: {
type: 'jsonp',
noCache: false,
api: {
create: urlRoot + 'Create',
read: urlRoot + 'Read',
update: urlRoot + 'Update',
destroy: urlRoot + 'Destroy'
},
reader: {
type: 'json',
metaProperty: 'meta',
root: 'data',
idProperty: 'id',
totalProperty: 'meta.total',
successProperty: 'meta.success'
},
writer: {
type: 'json',
encode: true,
writeAllFields: true,
root: 'data',
allowSingle: false,
}
}
});
Ext.define('Tovary', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [
{ name: 'id', type: 'int' },
'name',
'code',
'prise',
'unit'
]
});
var urlRootTv = 'data?model=Tovary&method=';
var TovaryGridStore = Ext.create('Ext.data.Store', {
model: 'Tovary',
pageSize: 10,
proxy: {
type: 'jsonp',
noCache: false,
extraParams: {
inclProps: '{code_tv}'
},
api: {
create: urlRootTv + 'Create',
read: urlRootTv + 'Read',
update: urlRootTv + 'Update',
destroy: urlRootTv + 'Destroy'
},
reader: {
type: 'json',
metaProperty: 'meta',
root: 'data',
idProperty: 'id',
totalProperty: 'meta.total',
successProperty: 'meta.success'
},
writer: {
type: 'json',
encode: true,
writeAllFields: true,
root: 'data',
allowSingle: false,
}
}
});
......
// Grid панель
var grid = Ext.create('Ext.grid.Panel', {
title: 'Таблица операций',
items: grid,
columns: columns,
store: registrStore,
loadMask: true,
bbar: pagingToolbar,
plugins: [rowEditing],
stripeRows: true,
selType: 'rowmodel',
viewConfig: {
forceFit: true
},
listeners: {
itemcontextmenu: doRowCtxMenu,
destroy: function (thisGrid) {
if (thisGrid.rowCtxMenu) {
thisGrid.rowCtxMenu.destroy();
}
},
select: function(grid, selectedItem) {
TovaryGridStore.proxy.extraParams = {'code_tv' : selectedItem.id.code};
TovaryGridStore.load();
}
},
renderTo: Ext.getBody()
});
registrStore.load();
When I click on a row in the grid, the browser console displays an error:
GET http://127.0.0.1:8000/hello_extjs/data?model=Tovary&method=Read&code_tv=&page=1&start=0&limit=10&callback=Ext.data.JsonP.callback2 500 (Internal Server Error)
What is the cause of this error? Whether correctly I understand that now I need to deduce the second Ext.grid.Panel what to display in it the data of model "Tovary"?

Related

ExtJS: Is possible to state if else condition for bind in grid panel?

Inside the ViewModel I've defined 2 stores and I'm using a gridpanel as view. Is there any chance to state if else condition for bind property inside gridpanel?
ViewModel:
stores: {
dataStore: {
model: 'MyApp.first.Model',
autoLoad: true,
session: true
},
listStore: {
model: 'MyApp.second.Model',
autoLoad: true,
session: true,
},
and on grid panel I want to do this condition;
Ext.define('MyApp.base.Grid', {
extend: 'Ext.grid.Panel',
// Currently binds directly to listStore
bind: '{listStore}',
// but I'm trying to implement a proper adjustment such as this;
// bind: function () {
// var username = localStorage.getItem('username');
// if (username === 'sample#adress.com') {'{dataStore}';} else {'{listStore}'}
// },
You can't use conditional expressions with bind, however, you can use ViewModel's formulas to select which store to use with grid. Here is example of such formula:
conditionalStore: function (get) {
var param = get('param');
if (param === 1) {
return get('simpsonsStore');
}
return get('griffinsStore');
}
And here is working fiddle, which you can play with: https://fiddle.sencha.com/#view/editor&fiddle/2eq2
You can use bindStore method of grid.
In this FIDDLE, I have created a demo using grid. I hope this will help/guide you to achieve your requirement.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
//defining store 1
Ext.define('Store1', {
extend: 'Ext.data.Store',
alias: 'store.store1',
autoLoad: true,
fields: ['name', 'email', 'phone'],
proxy: {
type: 'ajax',
url: 'data1.json',
reader: {
type: 'json',
rootProperty: ''
}
}
});
//defining store 2
Ext.define('Store2', {
extend: 'Ext.data.Store',
alias: 'store.store2',
autoLoad: true,
fields: ['name', 'email', 'phone'],
proxy: {
type: 'ajax',
url: 'data2.json',
reader: {
type: 'json',
rootProperty: ''
}
}
});
//defining view model
Ext.define('MyViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.myvm',
stores: {
gridStore1: {
type: 'store1'
},
gridStore2: {
type: 'store2'
}
}
});
//creating grid
Ext.create({
xtype: 'grid',
title: 'Example of bind the store',
renderTo: Ext.getBody(),
viewModel: {
type: 'myvm'
},
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Email',
dataIndex: 'email',
flex: 1
}, {
text: 'Phone',
dataIndex: 'phone'
}],
tbar: [{
text: 'Load Store1',
handler: function (btn) {
var grid = this.up('grid');
grid.bindStore(grid.getViewModel().getStore('gridStore1'))
}
}, {
text: 'Load Store2',
handler: function (btn) {
var grid = this.up('grid');
grid.bindStore(grid.getViewModel().getStore('gridStore2'))
}
}]
});
}
});

ext js 6 pass dynamic id from grid panel to model

How to passing id from gridpanel to model ?
here my grid panel code:
{
text : 'Tindakan',
xtype: 'actioncolumn',
minWidth: 130,
sortable: false,
menuDisabled: true,
items: [{
icon: 'images/view.png', // Use a URL in the icon config
tooltip: 'Lihat',
handler : function(grid, rowIndex, colIndex) {
var rec = grid.getStore().getAt(rowIndex);
alert("Lihat - " + rec.get('id'));
}]
}
Here is my model code:
Ext.define('Kds.model.ProfilView', {
extend: 'Ext.data.Store',
alias: 'model.profilView',
fields: [
'name',
'ic_no',
'address',
],
pageSize : 20,
proxy: {
type: 'rest',
url : 'http://localhost/kds-rest/web/index.php/people/view/'+id,
useDefaultXhrHeader : false,
withCredentials: false,
reader: {
type: 'json',
rootProperty: 'data',
//totalProperty: 'totalItems'
}
},
autoLoad: 'true',
});
How do you use that model? If you create or use that each time, you can try this:
handler : function(grid, rowIndex, colIndex) {
var rec = grid.getStore().getAt(rowIndex);
//Create or get model to use
var model = Ext.create('Kds.model.ProfilView', {
// then give the record id to model
recordId: rec.get('id') // edited
});
}
// to use in model
Ext.define('Kds.model.ProfilView', {
extend: 'Ext.data.Store',
alias: 'model.profilView',
fields: [
'name',
'ic_no',
'address'
],
pageSize : 20,
autoLoad: 'true',
initComponent: function() {
var me = this;
me.proxy = {
type: 'rest',
url : 'http://localhost/kdsrest/web/index.php/people/view/'+me.recordId, // or this.up().recordId,
................
} // iniComponent
me.callParent();
Edit: How to load model dynamically: fiddle: https://fiddle.sencha.com/#fiddle/11g9
Ext.define('model.instance', {
extend: 'Ext.data.Model',
fields: ['name', 'city', 'country'],
proxy: {
type: 'ajax',
url: 'info',
reader: {
type: 'json',
rootProperty: 'records'
}
}
});
var fn = function getSelectedRow(gridView, rowIndex, colIndex, column, e,direction) {
var me = this;
var store = gridView.getStore();
var record = store.getAt(rowIndex);
var inst = Ext.create('model.instance', {
name: record.get('name')
});
inst.load({
scope: this,
success: function(rec) {
console.log(rec);
}
});
}
var store1 = Ext.create('Ext.data.Store', {
fields: ['name', 'surname'],
data: [{
name: 'Rick',
surname: 'Donohoe'
}, {
name: 'Jane',
surname: 'Cat'
}]
});
var grid = Ext.create('Ext.grid.Panel', {
columns: [{
dataIndex: 'name'
}, {
dataIndex: 'surname'
}, {
xtype: 'actioncolumn',
text: 'Select',
icon: '/image',
handler: Ext.bind(fn, this)
}],
store: store1,
renderTo: Ext.getBody()
});

ExtJS Record with auto id Property

i have following problem with my ExtJS 5.1.0 Store.
When i want to create a new empty model with var m = new (store.model)(); and set Values with record.set(values); ( Which come from a Ext.form.Panel) the record has next to the normal Id, a second id. The Second one looks like that: "AM.namespace.model.ServiceContract-2".
Is it able to prevent a auto generated id?
To Create I use:
onAddServiceContract: function (item) {
this.__form = item.up('form');
var values = this.__form.getValues();
var store = this.getStore('ServiceContract');
var record = new (store.model)();
record.set('Id', 0000);
record.set(values);
record.phantom = true;
var rec = store.add(record);
}
The Store is defined as:
Ext.define('AM.####.store.ServiceContract',{
extend: 'AM.####.data.Store',
requires: ['Ext.data.proxy.Direct'],
model: 'AM.####.model.ServiceContract',
remoteGroup: true,
autoLoad: true,
//buffered: true,
pageSize: 1000,
leadingBufferZone: 500,
trailingBufferZone: 500,
autoSync: true,
constructor: function (config) {
config = Ext.apply({}, config);
if (!config.proxy) {
var proxy = {
type: 'direct',
reader: {
idProperty: 'Id',
rootProperty: 'data',
type: 'json'
},
writer: {
allowSingle: true,
writeAllFields: false // Note: Changed in ExtJS 5 to be default false
},
api: {
read: AM.####.ServiceContract.List,
create: AM.####.ServiceContract.Create,
update: AM.####.ServiceContract.BulkUpdate,
destroy: AM.####.ServiceContract.BulkDelete
}
};
config.proxy = proxy;
}
this.callParent([config]);
this.proxy.on('exception', this.onProxyException, this);
}
});
Thanks for your help!
You can mod the idProperty of the model to some other name.
For instance:
Ext.define('App.model.rssSoaFeed_m', {
extend: 'Ext.data.Model',
idProperty:'extIdProperty',//renaming the extjs id property
fields: [
{ name: 'title', type: 'auto' },
{ name: 'id', type: 'auto' }, //my custom id property
],
proxy:
{
type: 'ajax',
url: '/someurl.service',
extraParams: {
},
reader: {
type: 'json',
root: 'query.results.item'
}
}
});
And here is more info in sencha docs
Also, please note from the docs
the idProperty may be configured as null which will mean that no identifying field will be generated.

loading data to store but no data visible in grid

So I load json to the store but no data visible in grid. What am I doing wrong? Here is the grid:
{
xtype: 'gridpanel',
title: 'Clients List',
store: Ext.create('Ext.data.Store', {
model: 'app.model.modelClients',
proxy: Ext.create('Ext.data.HttpProxy', {
type: 'ajax',
headers: { 'Accept': 'application/json' },
url: 'client.php',
noCache: false,
startParam: undefined,
filterParam: undefined,
limitParam: undefined,
pageParam: undefined
}),
reader: new Ext.data.JsonReader({
root: 'records',
id: 'id',
fields: ['first_name', 'last_name', 'phone']
}),
listeners: {
load: function (self, records, successful, eOpts) {
var fields = records[0].fields;
console.log(fields.getAt(0));
}
},
autoLoad: true
}),
flex: '1',
columns: [
{ text: 'Name', dataIndex: 'first_name' },
{ text: 'Last Name', dataIndex: 'last_name' },
{ text: 'Phone', dataIndex: 'phone' }
]
}
ah. you have the reader at the wrong level. It is part of the proxy
proxy: {
type: "ajax",
url: "...",
reader: {

Extjs Grid doesn't show any data

I created the following grid component:
MyApp.grids.RelationshipMemberGrid = Ext.extend(Ext.grid.GridPanel, {
autoHeight: true,
iconCls: 'icon-grid',
title: 'Relationship Members',
frame: true,
viewConfig: { forceFit: true },
relationshipId: null,
documentId: null,
initComponent: function () {
if (this.verifyParameters()) {
// Initiate functionality
this.columns = this.buildColumns();
this.view = this.buildView();
this.store = this.buildStore();
this.store.load();
}
MyApp.grids.RelationshipMemberGrid.superclass.initComponent.call(this);
},
verifyParameters: function () {
// Verification code
},
buildColumns: function () {
return [{
header: 'Id',
dataIndex: 'Id',
sortable: true,
width: 10
}, {
header: 'Type',
dataIndex: 'ObjType',
sortable: true,
width: 10
}, {
header: 'Name',
dataIndex: 'Name',
sortable: true
}];
},
buildView: function () {
return new Ext.grid.GroupingView({
forceFit: true,
groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Members" : "Member"]})'
});
},
buildStore: function () {
return new Ext.data.GroupingStore({
url: MyAppUrls.ListRelationshipMembers,
baseParams: { relationshipId: this.relationshipId },
root: 'data',
fields: ['Id', 'ObjType', 'Name'],
sortInfo: { field: 'Name', direction: 'ASC' },
groupField: 'ObjType'
});
}
});
The grid renders correctly, and the URL that is mapped to MyAppUrls.ListRelationshipMembers is correct. The data is being retrieved, and the ListRelationshipMembers URL is returning the following JSON:
{"data":[{"Id":1,"ObjType":"topic","Name":"Test2"}]}
Yet, even though the grid is rendered (columns, borders, etc..) no data is showing in the actual grid though. Since this is my first time using a data store, I am unsure of what I am doing wrong. Any help would be appreciative.
Edit:
I tried updating the store to have a reader via the following code:
return new Ext.data.GroupingStore({
url: MyAppUrls.ListRelationshipMembers,
baseParams: { relationshipId: this.relationshipId },
fields: ['Id', 'ObjType', 'Name'],
sortInfo: { field: 'Name', direction: 'ASC' },
reader: new Ext.data.JsonReader({
root: 'data'
}),
groupField: 'ObjType'
});
No change, the datagrid is not being filled with the records
Evan is correct. Your biggest problem is a lack of a reader. That and the validation stub you left in there needed to return true. If you can't just drop this code in and have it work you have some other problem.
MyApp.grids.RelationshipMemberGrid = Ext.extend(Ext.grid.GridPanel, {
autoHeight: true,
iconCls: 'icon-grid',
title: 'Relationship Members',
frame: true,
viewConfig: { forceFit: true },
relationshipId: null,
documentId: null,
initComponent: function () {
if (this.verifyParameters()) {
// Initiate functionality
this.columns = this.buildColumns();
this.view = this.buildView();
this.store = this.buildStore();
this.store.load();
}
MyApp.grids.RelationshipMemberGrid.superclass.initComponent.call(this);
},
verifyParameters: function () {
// Verification code
return true;
},
buildColumns: function () {
return [{
header: 'Id',
dataIndex: 'Id',
sortable: true,
width: 10
}, {
header: 'Type',
dataIndex: 'ObjType',
sortable: true,
width: 10
}, {
header: 'Name',
dataIndex: 'Name',
sortable: true
}];
},
buildView: function () {
return new Ext.grid.GroupingView({
forceFit: true,
groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Members" : "Member"]})'
});
},
buildStore: function () {
return new Ext.data.GroupingStore({
url: MyAppUrls.ListRelationshipMembers,
baseParams: { relationshipId: this.relationshipId },
reader: new Ext.data.JsonReader({
root: 'data',
fields: ['Id', 'ObjType', 'Name'],
sortInfo: { field: 'Name', direction: 'ASC' },
groupField: 'ObjType'
})
});
}
});
Think you need to do a couple of things here: firstly, as mentioned by Evan, you need to add a reader to your store, like this:
buildStore: function () {
return new Ext.data.Store({
url: MyAppUrls.ListRelationshipMembers,
baseParams: { relationshipId: this.relationshipId },
fields: ['Id', 'ObjType', 'Name'],
sortInfo: { field: 'Name', direction: 'ASC' },
reader: new Ext.data.JsonReader({
root: 'data'
})
});
}
I've changed the store type here to something simpler - was there a particular reason you were using GroupingStore? Note that the root is specified in the reader, not the store itself.
Then, in your columns, I'd tend to add a renderer to explicitly determine what each column will display, such as:
buildColumns: function () {
return [{
header: 'Id',
dataIndex: 'Id',
sortable: true,
width: 10,
renderer: function (value, metaData, record) {
return record.data.Id
}
} ... ];
}
I've got into the habit of using renderers, since I modify the content of my column cells quite heavily in my grids. Notice here the arguments being passed to the renderer function; there are a few more you can pass in - see the ExtJS API if you need more info on what you can actually access. On that note, the API documentation is pretty good - it can take some digging into but definitely worth your time if you're working with ExtJS a lot.
You haven't specified a reader on your store, you need to specify the root in the JsonReader.

Categories

Resources