i have a grid and scroll in a grid. this is my code for generate the grid
gridMain = Ext.create('Ext.grid.Panel', {
renderTo: Ext.get("sa-grid"),
store: 'pf-store',
height: mainContentHeight - 63,
title: 'Promotion Form',
columns: [{
text: 'No PF',
width: 115,
dataIndex: 'PFID'
},
{
text: 'Title',
flex: 1,
dataIndex: 'Title'
},
{
text: 'Promotion From',
dataIndex: 'PromotionFrom'
},
{
text: 'Promotion To',
dataIndex: 'PromotionTo'
},
{
text: 'Limit Payment Date',
width: 120,
dataIndex: 'LimitPaymentDate'
},
{
text: 'Request Status',
width: 150,
dataIndex: 'RequestDescription'
},
{
text: 'Initiator',
width: 150,
dataIndex: 'CreateByName'
}],
dockedItems: [{
xtype: 'toolbar',
items: [actAddPF, actEditPF, actDeletePF, actExtendPF]
}],
listeners: {
itemdblclick: function (view, record, item, index, e, eOpts) {
isGridClicked = true;
ViewDetails(FormState.VIEW);
}
}
});
function ViewDetails(FormState) {
var data = GetSelectedRecord(gridMain);
var id = data.PFID;
ShowLoading("sa-body", "Please Wait ...");
$.ajax({
type: 'POST',
url: root + "PF/GetDataByID",
data: { PFID: id },
success: function (result) {
try {
DataToArray(result);
DataToControl(result);
CreatePivotPeriode();
CreateMainPivot();
ChangeFormState(FormState);
tabs.setActiveTab('pageDetails');
} catch (err) {
MsgErr(err);
}
},
complete: function () {
try {
HideLoading();
} catch (err) {
MsgErr(err);
}
}
});
}
it works fine, but when i insert or modify data and load again or click search by parameter. the scroll is not working. the content in grid is update based on search parameter, the problem is only the scroll which is not working anymore. then I have to do F5 to refresh it again so the grid can be scroll again.
this is my code for searching in grid
$("#btnSearch").click(function () {
ShowLoading("sa-body", "Please Wait ...");
$.post(root + "PF/Search", { FieldName: $("#cbSearch").val(), Pattern: $("#cbPattern").val(), Condition: $("#txtSearch").val() }, function (data) {
storePF.loadDataViaReader(data);
HideLoading();
});
});
Does someone have a solution about this problem ?
Many thanks
i can do by this
:)
Ext.override(Ext.grid.Scroller, {
onAdded: function() {
this.callParent(arguments);
var me = this;
if (me.scrollEl) {
me.mun(me.scrollEl, 'scroll', me.onElScroll, me);
me.mon(me.scrollEl, 'scroll', me.onElScroll, me);
}
}
});
Related
I am trying to put a grid inside in the all ready available grid's column on the basis of this parent grid data that if there is the data from the API call then my grid should display the data or if there is no data from the API response then it should not display anything in the parent grid column.
I have inserted the grid in the parent grid via the above code
and below is my handler for to display the data in the child grid
I have tried this via the widget column but via this approach it is displaying
displaying the data only from the last response of API
columns:[{
dataIndex: 'JobCode',
text: 'Job Code',
renderer: 'applyCursor',
flex: 1.5,
rowwidget: {
widget: {
xtype: 'grid',
autoLoad: true,
modal: true,
margin: '30 10 10 10',
listeners: {
afterrender: 'loadData',
},
bind: {
store: '{paymentdetailsstore}',
},
columns: [{
text: 'Payment Type',
dataIndex: 'PaymentType_Name',
flex: 0.5
}, {
text: ' Received Date',
dataIndex: 'Received_DateTime',
flex: 0.5
}, {
text: 'Amount($)',
dataIndex: 'Amount',
flex: 0.5
}]
}
}
},{...},{...},{...}],
loadData: function (a, b, c, d, e) {
debugger;
let me = this,
paymenthistorystore = this.getStore('paymenthistorystore'),
paymentdetailsstore = this.getStore('paymentdetailsstore'),
paymenthistorygrid = me.lookupReference('paymenthistory'),
jobId = paymenthistorystore.getData().items,
grid = a,
id;
console.log(jobId);
Ext.each(jobId, function (items) {
id = items.data.JobId;
Ext.Ajax.request({
url: '/api/jobs/GetPaymentHistory',
method: 'GET',
//async: false,
params: {
JobId: id
},
success: function (response, opts) {
debugger;
//var obj = Ext.decode(response.responseText);
paymentdetailsstore = me.getStore('paymentdetailsstore');
try {
data = Ext.decode(response.responseText).data;
} catch (e) {
data = [];
}
paymentdetailsstore.add(data);
console.log(data);
Ext.Msg.alert('Fiddle', 'Store contains ' + paymentdetailsstore.count() + ' records');
},
scope: paymentdetailsstore,
failure: function (response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
});
}
I want that in the child grid the data must be display as per according to the API response.
The way I'd do this, is have the details as a field (of array type) inside the job model/record and use the rowViewModel to map inner data to the widget. The way it works, it creates a separate viewmodel instance per row, and so if you define a store inside that rowViewModel, it's going to be created for each job separately. Also from inside the rowViewModel, you can access the record's fields ('{record.<field>}'), and thus you can simply bind the store's data to it.
Ext.define('MyView', {
viewModel: {
stores: {
outterGrid: {
fields: ['name', 'innerGridData'],
data: [{
name: 'Foo',
innerGridData: [{
innerField: 'Foo_a'
}, {
innerField: 'Foo_b'
}]
}, {
name: 'Bar',
innerGridData: [{
innerField: 'Bar_a'
}, {
innerField: 'Bar_b'
}]
}]
}
}
},
extend: 'Ext.grid.Panel',
xtype: 'MyView',
bind: {
store: '{outterGrid}'
},
columns:[{
dataIndex: 'name',
flex: 1
}, {
xtype: 'widgetcolumn',
flex: 1,
widget: {
xtype: 'grid',
bind: {
store: '{innerStore}'
},
columns: [{
dataIndex: 'innerField',
flex: 1
}]
}
}],
rowViewModel: {
stores: {
innerStore: {
fields: ['innerField'],
data: '{record.innerGridData}'
}
}
}
});
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.create({
xtype: 'MyView',
width: 300,
height: 300,
renderTo: Ext.getBody()
});
}
});
I'm keep facing with a issue to choice exact component with scope. As you'll notice below I've created 2 different functions inside gridpanel. One of those creates a Ext.MessageBox for confirm. And other function creates a Ext.window.Window depends on button click of MessageBox.
The thing here is; It should destroy related component with cancel and no buttons. Both buttons always point to gridpanel because of var me = this state and destroys the gridpanel itself.
How can I point destroy method directly to related component?
Ext.define('MyApp.FooGrid', {
extend: 'Ext.grid.Panel',
reference: 'fooGrid',
getGridMenu: function () {
// Here is the 'Update' function; with right-click user being able to see `contextmenu`
var me = this;
var ret = [
{
text: 'Update',
listeners: {
click: me.onUpdate,
scope: me
}
}
];
return me.callParent().concat(ret);
},
onUpdate: function () {
var me = this,
gridRec = this.getSelectionModel().getSelection(); // Here being able to retrieve row data.
Ext.MessageBox.confirm(translations.confirm, translations.confirmChange, me.change, me);
return gridRec;
},
change: function (button) {
var me = this;
var selectedRec = me.onUpdate();
var selectedRecEmail = selectedRec[0].data.email; //Retrieves selected record's email with right-click action
if (button === "yes") {
return new Ext.window.Window({
alias: 'updateWin',
autoShow: true,
title: translations.update,
modal: true,
width: 350,
height: 200,
items: [
{
xtype: 'container',
height: 10
},
{
xtype: 'textfield',
width: 300,
readOnly: true,
value: selectedRecEmail //Display selected record email
},
{
xtype: 'textfield',
width: 300,
fieldLabel: translations.newPassword
}
],
dockedItems: [
{
xtype: 'toolbar',
dock: 'bottom',
items: [
{
xtype: 'tbfill'
},
{
xtype: 'button',
text: translations.cancel,
listeners: {
click: function () {
me.destroy(); // Here is the bug: When user clicks on this button; should destroy current window but it destroys 'gridpanel' itself
}
}
},
{
xtype: 'button',
text: translations.save,
listeners: {
click: function () {
console.log("I'll save you!");
}
}
}
]
}
]
});
} else {
console.log('this is no!');
me.destroy(); // Another bug raises through here: If user will click on No then 'messagebox' should destroy. This one is destroys the gridpanel as well.
}
}
});
How can I point destroy method directly to related component?
Firstly on confirmation box button's(No) click, you don't need to destroy it will automatically hide the box whenever you click into No.
And for update window instead of using me.destroy() you need to use directly button.up('window').destroy() so it will only destroy your update window not the grid.
And also you don't need to again call me.onUpdate() inside of change function otherwise it will again show the confirmation box. You can directly get selected record on the change function like this me.getSelection().
In this Fiddle, I have created a demo using your code and I have put my efforts to get result.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.create('Ext.data.Store', {
storeId: 'demostore',
fields: ['name', 'email', 'phone'],
data: [{
name: 'Lisa',
email: 'lisa#simpsons.com',
phone: '555-111-1224'
}, {
name: 'Bart',
email: 'bart#simpsons.com',
phone: '555-222-1234'
}, {
name: 'Homer',
email: 'homer#simpsons.com',
phone: '555-222-1244'
}, {
name: 'Marge',
email: 'marge#simpsons.com',
phone: '555-222-1254'
}]
});
Ext.create('Ext.grid.Panel', {
title: 'Demo GRID',
store: 'demostore',
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Email',
dataIndex: 'email',
flex: 1
}, {
text: 'Phone',
dataIndex: 'phone'
}],
height: 200,
listeners: {
itemcontextmenu: function (grid, record, item, index, e, eOpts) {
e.stopEvent();
grid.up('grid').getGridMenu().showAt(e.getXY());
}
},
renderTo: Ext.getBody(),
getGridMenu: function () {
var me = this;
if (!me.contextMenu) {
me.contextMenu = Ext.create('Ext.menu.Menu', {
width: 200,
items: [{
text: 'Update',
handler: me.onUpdate,
scope: me
}]
});
}
return me.contextMenu;
},
onUpdate: function () {
var me = this;
Ext.MessageBox.confirm('Confirmation ', 'Are your sure ?', me.change, me);
},
change: function (button) {
var me = this,
selectedRecEmail = me.getSelection()[0].data.email; //Retrieves selected record's email with right-click action
if (button === "yes") {
return new Ext.window.Window({
autoShow: true,
title: 'Update',
modal: true,
width: 350,
height: 200,
items: [{
xtype: 'tbspacer',
height: 10
}, {
xtype: 'textfield',
width: 300,
readOnly: true,
value: selectedRecEmail //Display selected record email
}, {
xtype: 'textfield',
inputType:'password',
width: 300,
fieldLabel: 'New Password'
}],
dockedItems: [{
xtype: 'toolbar',
dock: 'bottom',
items: [{
xtype: 'tbfill'
}, {
xtype: 'button',
text: 'cancel',
listeners: {
click: function (btn) {
btn.up('window').destroy(); // Here is the bug: When user clicks on this button; should destroy current window but it destroys 'gridpanel' itself
}
}
}, {
xtype: 'button',
text: 'save',
listeners: {
click: function () {
console.log("I'll save you!");
}
}
}]
}]
});
}
}
});
}
});
I have a popup in which I have a dropdown. When I change the value of the dropdown to some other value it shows the orange triangle of the dirty check, but if I change the value of the drop down back to the previous value, the dirty check mark is still shown.
If the value is changed back to the original value in the dropdown, I want the dropdown to not show the dirty check mark.
Sharing my code
columns: {
defaults: {
align: 'left',
flex: 2
},
items: [{
xtype: 'actioncolumn',
localized: {
text: 'commonTranslations.function'
},
items: [{
iconCls: 'iwp-icon-gen_edit',
handler: 'onEditClick',
getTip: function() {
return I18n.get('commonIconTranslations.penReleaseConcepts')
}
}],
align: 'center',
flex: 1
},
{
localized: {
text: 'commonTranslations.description'
},
dataIndex: 'title',
renderer: CommonRendererUtils.htmlEncode
},
{
localized: {
text: 'commonTranslations.fileName'
},
dataIndex: 'filename',
renderer: CommonRendererUtils.htmlEncode
},
{
xtype: 'actioncolumn',
localized: {
text: 'commonTranslations.file'
},
items: [{
getClass: function(v, metadata, r) {
if (!r.get('filename')) {
return 'x-hidden'
} else {
return 'iwp-icon-zeb_folder'
}
},
getTip: function() {
return I18n.get('commonIconTranslations.halfOpenFolder')
},
handler: 'onDownloadClick'
}],
align: 'center',
flex: 1
},
{
localized: {
text: 'commonTranslations.source'
},
dataIndex: 'source',
flex: 1
},
{
localized: {
text: 'details.tabview.scope.contents.release.main.uploadDate'
},
dataIndex: 'changeDate',
xtype: 'dynamicTimestampColumn'
},
{
localized: {
text: 'details.tabview.scope.contents.release.main.uploadBy'
},
dataIndex: 'changeUser',
xtype: 'usercolumn'
},
{
localized: {
text: 'commonTranslations.status'
},
/*-----facing issue for the column*/
dataIndex: 'status',
renderer: function(value) {
return value.germanDescription;
}
},
{
localized: {
text: 'commonTranslations.changeReason'
},
dataIndex: 'changeReason',
renderer: CommonRendererUtils.htmlEncode
},
{
localized: {
text: 'commonTranslations.modulOrg'
},
dataIndex: 'modulOrgs',
renderer: function(value, metaData, record) {
if (record.isModified(metaData.column.dataIndex)) {
console.log("modified 9999999" + record.isModified(metaData.column.dataIndex));
metaData.tdCls += 'x-grid-dirty-cell';
}
var formattedValue = "";
if (value) {
value.forEach(function(modulOrg) {
formattedValue += modulOrg.modulOrg + ", ";
});
}
return formattedValue.substring(0, formattedValue.length - 2);
},
flex: 1
},
{
localized: {
text: 'details.tabview.scope.contents.release.main.historyIndex'
},
dataIndex: 'historyIndex',
flex: 1
}
]
}
I think you have too much code for this. Anyways there is a change event listener that you can add to your dropdown as follows:
listeners:{
change:'combochange'
}
Now you can write this combochange function inside your controller or you can defined this function inside your view only.
combochange:function(field,newValue,oldValue,e){
// Inside this function you will get both the values of the dropdown of
yours where newValue is the value currently selected and oldValue is the
previous value. So inside this function according to your conditions you
can put a check that if the old and newvalue matches then not to show the
orange triangle.
}
Let me know if any issue. Happy Learning :)
In ExtJS, on a menu toolbar button, I am trying to remove the current panel in my center window, then recreate it with the new selection. I do not understand the proper way to do this. So far when I click the menu item, it removes whatever is currently there successfully, then it will add the new panel successfully. The problem is the 2nd time I hit the button I get the following error:
REGISTERING DUPLICATE COMPONENT ID 'mainportalID'.
I realize its telling me I already used this ID, but then what would be the correct way to remove the current panel, and replace with a new one?
Here is my view controller:
selectMenuButton: function (button, e) {
console.log('select menu button section was hit')
console.log(button);
console.log(e);
var optionString = button.text;
var myDetailsPanel = Ext.getCmp('navview');
console.log(myDetailsPanel);
var count = myDetailsPanel.items.items.length;
if (count > 0) {
myDetailsPanel.items.each(function (item, index, len) {
myDetailsPanel.remove(item, false);
});
}
myDetailsPanel.add({
xtype: optionString
});
}
var myStore = Ext.create('ExtApplication1.store.PositionsStore');
var gridSummary = Ext.create('Ext.grid.Panel', {
store: myStore,
width: 600,
title: 'my first grid',
columns: [
{
text: 'AcctNum',
dataIndex: 'AcctNum',
width: 100
},
{
text: 'AcctShortCode',
dataIndex: 'AcctShortCode',
flex: 1
},
{
text: 'Exchange',
dataIndex: 'Exchange',
width: 200
}
]
});
This is my view
Ext.define('ExtApplication1.view.main.MainPortal', {
extend: 'Ext.panel.Panel',
xtype: 'mainportal',
alias: 'widget.mainportal',
id: 'mainportalID',
html: 'user... this is the main portal window',
autoScroll: true,
bodyPadding: 10,
items: [
gridSummary
]
});
adjusted panel
Ext.define('ExtApplication1.view.main.MainPortal', {
extend: 'Ext.panel.Panel',
xtype: 'mainportal',
alias: 'widget.mainportalAlias',
reference: 'gridtextfield',
//id: 'mainportalID',
html: 'user... this is the main portal window',
autoScroll: true,
bodyPadding: 10,
items: [
gridSummary
]
});
adjusted view controller
onComboboxSelect: function (combo, record, eOpts) {
console.log('new listener was hit');
//return selected Item
var selectedValue = record.get('ClientName');
var selectedCID = record.get('ClientID');
//find the grid that was created
var me = this;
console.log(me);
var xxx = this.lookupReference('gridtextfield');
debugger;
//debugger;
var mainPortalView = Ext.getCmp('mainportalID');
var targetGrid = mainPortalView.down('grid');
//find the store associated with that grid
var targetStore = targetGrid.getStore();
//load store
targetStore.load({
params: {
user: 'stephen',
pw: 'forero',
cid: selectedCID
}
//callback: function (records) {
// Ext.each(records, function (record) {
// console.log(record);
// });
// console.log(targetStore);
//}
});
},
added listeners to MainPortal.js
var myStore = Ext.create('ExtApplication1.store.PositionsStore');
var gridSummary = Ext.create('Ext.grid.Panel', {
store: myStore,
width: 600,
title: 'my first grid',
columns: [
{
text: 'AcctNum',
dataIndex: 'AcctNum',
width: 100
},
{
text: 'AcctShortCode',
dataIndex: 'AcctShortCode',
flex: 1
},
{
text: 'Exchange',
dataIndex: 'Exchange',
width: 200
}
],
listeners: {
destroy: function () {
debugger;
}
}
});
Ext.define('ExtApplication1.view.main.MainPortal', {
extend: 'Ext.panel.Panel',
xtype: 'mainportal',
alias: 'widget.mainportalAlias',
//id: 'mainportalID',
itemId: 'mainportalID',
html: 'user... this is the main portal window',
autoScroll: true,
bodyPadding: 10,
items: [
gridSummary
],
listeners: {
destroy: function () {
debugger;
}
}
});
I am new to ExtJs, and i am playing around to build logic to perform "live search" on Grid columns.
From the code below i am able to populate data into the grid but cannot make live search functionality. i am not sure where i am missing the logic.
Ext.define('abc.view.EmployeePanel', {
extend: 'Ext.window.Window',
alias: 'widget.EmployeePanel',
requires: [
'Ext.tab.Panel',
'Ext.form.*'],
constructor: function () {
this.callParent(arguments);
},
this. employeePopUPGridStore = new Ext.data.ArrayStore({
fields: [
{
name: 'empid',
type: 'number'
},
{
name: 'fname',
type: 'string'
},
{
name: 'lname',
type: 'string'
},
],
});
this.employeePopUPGridStore.loadData(localAr, false);
this.down('#addempgrid').bindStore(this.employeePopUPGridStore);
this.down('#addempgrid').getView().refresh();
},
items: [{
xtype:'textfield',
name:'search',
itemId:'search',
emptyText:'Search by First Name / Last Name',
listeners: {
onTextFieldChange: function(field, newValue, oldValue, eOpts){
var grid = field.down('addempgrid');
grid.store.clearFilter();
if (newValue) {
var matcher = new RegExp(Ext.String.escapeRegex(newValue), "i");
grid.store.filter({
filterFn: function(item) {
return matcher.test(item.get('empid')) ||
matcher.test(item.get('fname')) ||
matcher.test(item.get('job'));
}
});
}
}
}
},
{
xtype: 'gridpanel',
itemId: 'addempgrid',
autoHeight: true,
columns: [
{
header: "Employee ID",
flex: 1,
dataIndex: 'empid',
},
{
header: "Full Name",
flex: 3,
dataIndex: 'fname'
},
{
header: "LastName",
flex: 1,
dataIndex: 'lname'
},
]
}
] }
});
Any help around is much appreciated.
Hi Please try this way once..
{
xtype: 'textfield',
itemId: 'searchBar',
cls: 'search-bar',
width: 230,
margin: '0 0 0 10',
listeners: {
buffer: 250,
scope: this,
change: function (field, newVal) {
var grid = field.down('addempgrid');
grid.store.clearFilter();
if (newValue) {
var matcher = new RegExp(Ext.String.escapeRegex(newValue), "i");
grid.store.filter({
filterFn: function(item) {
return matcher.test(item.get('empid')) ||
matcher.test(item.get('fname')) ||
matcher.test(item.get('job'));
}
});
}
}
}
}
Hope it helps you