ExtJS: How to access Ajax request's value from any other proxy? - javascript

I'm getting some specific data from a web-service and need to transfer this data to another web-service's extraParams. How can I achieve to it?
I've created a singleton class which handles information and after fetching those data; another store proxy will use those data.
This is singleton class;
Ext.define('MyApp.MyInfo', {
requires: [] ,
singleton: true,
getMyId: function () {
var me = this;
var request = Ext.Ajax.request({
url: myUrl() + '/info', //Here is web-service url
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
var myId = obj.data[0].id; // Successfully gets required ID
console.log(myId); // Successfully prints ID value
// callback(userGid); //Not sure if callback method will handle ID value to fetch on any other class..
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
}
});
and here is other proxy which needs myId value from Ajax.request above;
stores: {
myFooStore: {
model: 'MyApp.Model',
autoLoad: true,
session: true,
proxy: {
url: myUrl() + '/the/other/service',
type: 'ajax',
extraParams: {
id: // HERE! I need to get myId value on here. And couldn't get it.
},
reader: {
type: 'json',
rootProperty: 'data'
}
}
},

Instead of store auto load you need to call store.load() method to load your particular store. And you can pass your params using store.getProxy() like below example:
//you can set using get proxy
store.getProxy().setExtraParams({
id: id
});
store.load()
//or you can direcly pass inside of store.load method like this
store.load({
params: {
id: 'value' //whatever your extraparms you can pass like this
}
});
In this Fiddle, I have created a demo based on your requirement.
Code snippet:
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.define('MyInfo', {
alternateClassName: "myinfo",
singleton: true,
getMyId: function (callback) {
var me = this;
Ext.Ajax.request({
url: 'id.json', //Here is web-service url
success: function (response, opts) {
var obj = Ext.decode(response.responseText),
myId = obj.data[0].id; // Successfully gets required ID
console.log(myId); // Successfully prints ID value
callback(myId);
},
failure: function (response, opts) {
callback('');
console.log('server-side failure with status code ' + response.status);
}
});
}
});
Ext.define('MyViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.myview',
onLoadButtonTap: function () {
var view = this.getView(),
myFooStore = this.getViewModel().getStore('myFooStore');
view.mask('Please wait..');
myinfo.getMyId(function (id) {
view.unmask();
if (id) {
myFooStore.getProxy().setExtraParams({
id: id
});
myFooStore.load();
/*
You can also do like this
myFooStore.load({
url:'',//If you want to change url dynamically
params:{
id:'value'//whatever your extraparms you can pass like this
}
});
*/
}
});
}
});
Ext.define("ViewportViewModel", {
extend: "Ext.app.ViewModel",
alias: 'viewmodel.myvm',
stores: {
myFooStore: {
fields: ['name', 'email', 'phone'],
proxy: {
type: 'ajax',
url: 'data1.json',
reader: {
type: 'json',
rootProperty: ''
}
}
}
}
});
//creating panel with GRID and FORM
Ext.create({
xtype: 'panel',
controller: 'myview',
title: 'Demo with singletone class',
renderTo: Ext.getBody(),
viewModel: {
type: 'myvm'
},
layout: 'vbox',
items: [{
xtype: 'grid',
flex: 1,
width: '100%',
bind: '{myFooStore}',
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Email',
dataIndex: 'email',
flex: 1
}, {
text: 'Phone',
dataIndex: 'phone'
}]
}],
tbar: [{
text: 'Load Data',
handler: 'onLoadButtonTap'
}]
});
}
});

Related

How to wait until all stores are Sync in ExtJs?

I have a list of grids that can change their data in form by end-user.
Finally, I want to sync all the grids by clicking the button, then an operation is performed.
I wrote the code below:
$.when.apply(
Ext.ComponentQuery.query('grid')
.forEach(function(item) {
if (item.getXType() == "grid") {
if (item.store.getNewRecords().length > 0 || item.store.getUpdatedRecords().length > 0 || item.store.getRemovedRecords().length > 0) {
item.store.sync();
}
}
})).then(function (results) {
//do something
});
Problem is here that store.sync() not waiting for callback.
What is the recommended way of doing this?
I do it with Promise like this:
// Sync grid data if exist dirty data
Promise.all(
Ext.ComponentQuery.query('grid')
.map(grid => grid.getStore())
.filter(s => (s.getNewRecords().length + s.getUpdatedRecords().length + s.getRemovedRecords().length) > 0)
.map(s => new Promise((resolve, reject) => {
s.sync({
success: () => { resolve(); },
failure: () => { reject(); }
});
}))
).then(() => {
//do something
});
You could use callback for your store.sync() method.
The callback function to be called upon completion of the sync. The callback is called regardless of success or failure and is passed the following parameters: (batch, options).
You could achieve your requirement like this
Take a blank array name before loop. like this var gridIds=[].
In side of loop before store.sync() push grid id in above array.
Now in callback function remove that grid id from above array and check condition array is blank then your all store sync response has came.
You can check here with working Fiddle
Note I have used dummy api. Please use your actual api.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.define('MyStore', {
extend: 'Ext.data.Store',
alias: 'store.mystore',
fields: ['name'],
autoLoad: true,
pageSize: 25,
remoteSort: true,
proxy: {
type: 'ajax',
method: 'POST',
api: {
read: 'data.json',
update: 'your_update_api',
create: 'your_create_api',
destroy: 'your_delete_api'
},
reader: {
type: 'json'
},
writer: {
type: 'json',
encode: true,
root: 'data'
}
},
});
Ext.define('MyGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.mygrid',
store: {
type: 'mystore'
},
height: 200,
border: true,
tools: [{
xtype: 'button',
iconCls: 'fa fa-plus-circle',
tooltip: 'Add New Record',
handler: function () {
let grid = this.up('grid'),
store = grid.getStore();
store.insert(0, {
name: 'Test ' + (store.getCount() + 1)
});
}
}],
columns: [{
text: 'Name',
dataIndex: 'name',
flex: 1
}]
});
Ext.create({
xtype: 'panel',
// title: 'Store sync example',
items: [{
xtype: 'mygrid',
title: 'Grid 1'
}, {
xtype: 'mygrid',
title: 'Grid 2'
}, {
xtype: 'mygrid',
title: 'Grid 3'
}, {
xtype: 'mygrid',
title: 'Grid 4'
}],
bbar: ['->', {
text: 'Submit Changes',
handler: function (btn) {
var panel = btn.up('panel'),
grids = panel.query('grid'),
gtidIds = [],
lenthCheck = function (arr) {
return arr.length > 0;
};
grids.forEach(function (grid) {
let store = grid.getStore();
if (lenthCheck(store.getNewRecords()) || lenthCheck(store.getUpdatedRecords()) || lenthCheck(store.getRemovedRecords())) {
panel.mask('Please wait...');
gtidIds.push(grid.getId());
store.sync({
callback: function () {
Ext.Array.remove(gtidIds, grid.getId());
if (gtidIds.length == 0) {
panel.unmask();
Ext.Msg.alert('Info', 'All grid store sync success.');
}
}
}, grid);
}
});
}
}],
renderTo: Ext.getBody(),
})
}
});

Creating dependent extjs grids

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"?

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'))
}
}]
});
}
});

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.

Sencha Touch: load store for List using Rest Proxy

I'm new to sencha so I'm sure I'm just missing something simple here. I have a rest service and I need to be able to load my store for my list view.
Here's my model with the proxy:
Ext.define('UserModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'UserId', type: 'int' },
{ name: 'FullName', type: 'string' }
],
proxy: {
type: 'rest',
url: '/rest/user',
reader: {
type: 'json',
root: 'user'
}
}
}
});
And this code works fine for a GET request. So I know that I'm able to talk with my rest service.
var User = Ext.ModelMgr.getModel('UserModel');
User.load(10058, {
success: function (user) {
console.log("Loaded user: " + user.get('UserId') + ", FullName: " + user.get('FullName'));
}
});
My problem is that I'm unable to load data into my list view when adding the proxy code to the store. How do I pass in a parameter to the rest service and load the store?
Ext.define('UserStore', {
extend: 'Ext.data.Store',
config: {
model: 'UserModel',
proxy: {
type: 'rest',
url: '/rest/user',
reader: {
type: 'json',
root: 'user'
},
autoLoad: true
},
sorters: 'FullName',
grouper: function(record) {
return record.get('FullName')[0];
}
}
});
And here's my list view:
Ext.define('UserView', {
extend: 'Ext.List',
xtype: 'userView',
config: {
scrollable: 'vertical',
loadingText: "Loading your social connections . . .",
indexBar: true,
singleSelect: true,
grouped: true,
cls: 'customGroupListHeader',
itemTpl: '{FullName}',
store: 'UserStore',
onItemDisclosure: true
}
});
Haha! I knew it was something simple. The "autoLoad: true" in the store's proxy needs to be outside of the proxy's brackets.
Ext.define('UserStore', {
extend: 'Ext.data.Store',
config: {
model: 'UserModel',
autoLoad: true,

Categories

Resources