ExtJS Grid Delete Row - Getting Selected Row - extjs

I am getting the following error when trying to get the selected row:
Uncaught TypeError: Object #<HTMLDivElement> has no method 'getView'
How do get the current selected row when I can't get the View and hence the SelectionModel?
My View Code:
Ext.define('MyLodge.view.content.MemberGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.membergrid',
initComponent: function(){
var rowEditing = Ext.create('Ext.grid.plugin.RowEditing');
var store = Ext.create('MyLodge.store.Members');
Ext.apply(this, {
height: this.height,
plugins: [rowEditing],
store: store,
stripeRows: true,
columnLines: true,
columns: [{
id :'id',
text: 'ID',
width: 40,
sortable: true,
dataIndex: 'id'
},{
text : 'Name',
flex: 1,
sortable : true,
dataIndex: 'name',
field: {
xtype: 'textfield'
}
},{
text : 'E-Mail',
width : 150,
sortable : true,
dataIndex: 'email',
field: {
xtype: 'textfield'
}
},{
text : 'Href',
width : 200,
editable: false,
sortable : true,
dataIndex: 'href'
}],
dockedItems: [{
xtype: 'toolbar',
items: [{
text: 'Add',
iconCls: 'icon-add',
handler: function(){
// empty record
store.insert(0, new MyLodge.model.Member());
rowEditing.startEdit(0, 0);
}
}, {
text: 'Delete',
iconCls: 'icon-delete',
handler: function(){
var selection = grid.getView().getSelectionModel().getSelection()[0];
if (selection) {
store.remove(selection);
}
}
},'-',{
text: 'Save',
iconCls: 'icon-save',
handler: function(){
store.sync({
success: function(response){
store.load()
}
});
}
},{
text: 'Refresh',
handler: function(){
store.load();
}
}]
}]
});
this.callParent(arguments);
}
});

One option would be adding the scope to the closure as a variable:
initComponent: function () {
var me = this;
.
.
So in your handler you can use me to refer to the grid:
{
text: 'Delete',
iconCls: 'icon - delete ',
handler: function () {
var selection = me.getView().getSelectionModel().getSelection()[0];
if (selection) {
store.remove(selection);
}
}
}
Working example: http://jsfiddle.net/Sn4fC/
A second option can be setting a click listener instead of the handler and specifying the scope:
{
text: 'Delete',
iconCls: 'icon - delete ',
listeners: {
click: {
scope: this,
fn: function () {
var selection = this.getView().getSelectionModel().getSelection()[0];
if (selection) {
store.remove(selection);
}
}
}
}
}
Working example: http://jsfiddle.net/XyBbF/

The issue is that 'grid' is not available in the handler function scope or it is not the one what you actually expected it to be.
handler: function(){
//.... keep the debug point here in browser developer tool and verify the value of grid in console. It is definitely not an instance of the grid u expected hence it wont have getView() method.
var selection = grid.getView().getSelectionModel().getSelection()[0];
}
Try getting the reference of grid and use it in handler as shown below:
Ext.define('MyLodge.view.content.MemberGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.membergrid',
id: 'membergrid',
......
handler: function(){
var grid = Ext.getCmp('membergrid'); // where 'membergrid' is the id defined in grid config
var selection = grid.getView()......

Related

ExtJS: Issue with scope in class

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

extjs proper way to replace main center panel

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

Record is undefined Extjs4 to get the data out of the form

I have window with button enter and few fields i need to get the data out of the form and there is method on button :
enter: function (button) {
var win = button.up('window'),
form = win.down('form'),
record = form.getRecord(),
values = form.getValues();
record.set(values);
win.close();
this.getUsersStore().sync();
Here record is undefined. What i do wrong?
////////////////////////////////////////////////////////////////////
Here the form:
Ext.define('ExtMVC.view.portlet.Login', {
extend: 'Ext.window.Window',
alias: 'widget.login',
layout: 'fit',
title: 'LogIn',
width: 300,
height: 150,
autoShow: true,
store: 'LoginModels',
initComponent: function () {
this.items = [
{
xtype: 'form',
items: [
{
xtype: 'textfield',
name: 'Name',
fieldLabel: 'Name',
style: { 'margin': '10px' },
},
{
xtype: 'textfield',
name: 'Password',
fieldLabel: 'Password',
style: { 'margin': '10px' },
}
]
}
];
this.buttons = [
{
text: 'Enter',
action: 'enter',
//handler: this.enter
},
{
text: 'Cancel',
scope: this,
handler: this.close
},
{
text: 'Sing in',
scope: this,
handler: this.close
}
];
this.callParent(arguments);
}
});
try to replace with this code
values=form.getForm().getValues();
Please go through the ext doc as it clearly says:
getRecord( ) : Ext.data.Model :
Returns the currently loaded Ext.data.Model instance if one was loaded via loadRecord.
And in case of your example I dont see any code that loads your form panel using loadRecord().
enter: function (button) {
var win = button.up('window'),
form = win.down('form'),
//record = form.getRecord(), /*not required here*/
record = this.getUsersStore().findRecord('id', 1) /*if you know id or some thing which field is know*/
values = form.getValues();
record.set(values);
win.close();
this.getUsersStore().sync();
You have to load form using form.loadRecord() before fetching it through form.getRecord(), otherwise form.getRecord() returns undefined.

how to call an addRow view method from an ExtJS4 controller

I have a controller and a view and want to push a line from a controller when item is selected.
Where it says onItemSelect: that's where I need to make a call, and don't know how...
Thank you.
controller is this:
Ext.define('Application.controller.ItemController', {
// Extend basic controller object
extend: 'Ext.app.Controller',
// Attach store classes to this controller
stores: ['Items'],
// Attach model classes to this controller
models: ['Item'],
// ..and last but not least - the view classes
views: ['item.List', 'item.Show'],
// Refs parameter defines references to certain
// instances of components pointed by selector
refs: [
{
// Ref determines the name of the automagic
// this.get[ref-goes-here] method that returns
// instance of certain component
ref : 'itemShowDesc',
// Select #item-description component in
// item.Show view
selector: 'itemShow > #item-description'
}
],
// when including the controllers in your application,
// the framework will automatically load the controller
// and call the init method on it
init: function() {
this.control({
'itemList' : {
// Action to be performed on select
select: this.onItemSelect
}
});
},
onItemSelect: function (selModel, selection) {
// Executed only when selection is a leaf
(selection.data.leaf) ? this.getItemShowDesc().addRow(selection.raw.description,'','','','','','') : null;
}
});
and the view is this:
Ext.define('Application.view.item.Show', {
extend: 'Ext.grid.Panel',
alias : 'widget.itemShow',
requires: [
'Ext.selection.CellModel',
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.form.*',
'Application.model.Item'
],
xtype: 'cell-editing',
title: 'Favorite Books',
frame: true,
initComponent: function() {
this.cellEditing = new Ext.grid.plugin.CellEditing({
clicksToEdit: 1
});
Ext.apply(this, {
width: 680,
height: 350,
plugins: [this.cellEditing],
store: new Ext.data.Store({
// destroy the store if the grid is destroyed
autoDestroy: true,
model: Application.model.Item,
proxy: {
type: 'ajax',
// load remote data using HTTP
url: 'resources/data/grid/books.xml',
// specify a XmlReader (coincides with the XML format of the returned data)
reader: {
type: 'xml',
// records will have a 'plant' tag
record: 'book'
}
},
sorters: [{
property: 'common',
direction:'ASC'
}]
}),
columns: [{
header: 'Book Id',
dataIndex: 'item_id',
width: 100
}, {
header: 'Author',
dataIndex: 'author',
width: 100
}, {
header: 'Title',
dataIndex: 'title',
width: 250
},{
header: 'Description',
dataIndex: 'description',
width: 495
},{
header: 'Price',
dataIndex: 'price',
width: 70,
align: 'right',
renderer: 'usMoney'
},{
xtype: 'actioncolumn',
width: 30,
sortable: false,
menuDisabled: true,
items: [{
icon: 'resources/images/icons/delete.gif',
tooltip: 'Delete Plant',
scope: this,
handler: this.onRemoveClick
}]
}],
selModel: {
selType: 'cellmodel'
}
});
this.callParent();
this.on('afterlayout', this.loadStore, this, {
delay: 1,
single: true
})
},
addRow: function(inItemID,inDisplay,inSex,inAuthor,inTitle,inDescription,inPrice){
// Create a record instance through the ModelManager
var r = Ext.ModelManager.create({
item_id: inItemID,
display: inDisplay,
sex: inSex,
author: inAuthor,
title: inTitle,
description: inDescription,
price: inPrice
}, 'Item');
store.insert(0, r);
cellEditing.startEditByPosition({row: 0, column: 0});
}
,
loadStore: function() {
this.getStore().load({
// store loading is asynchronous, use a load listener or callback to handle results
callback: this.onStoreLoad
});
},
onStoreLoad: function(){
Ext.Msg.show({
title: 'Store Load Callback',
msg: 'Favorites were loaded, data available for processing',
icon: Ext.Msg.INFO,
buttons: Ext.Msg.OK
});
},
onRemoveClick: function(grid, rowIndex){
this.getStore().removeAt(rowIndex);
}
})
Your ref for itemShowDesc is selecting a child component of itemShow. So when you do this.getItemShowDesc().addRow(), you're calling a method on whatever #item-description is, not on the Application.view.item.Show class.

Sencha ExtJs Grid refresh after saving store

I have an ExtJS grid with a toolbar button to save the date. The save works and the data is stored. But the grid is not refreshed. How do I reload the grid data after the save?
Ext.define('MyLodge.view.content.MemberGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.membergrid',
initComponent: function(){
var rowEditing = Ext.create('Ext.grid.plugin.RowEditing');
var store = Ext.create('MyLodge.store.Members');
Ext.apply(this, {
height: this.height,
plugins: [rowEditing],
store: store,
stripeRows: true,
columnLines: true,
columns: [{
id :'id',
text: 'ID',
width: 40,
sortable: true,
dataIndex: 'id'
},{
text : 'Name',
flex: 1,
sortable : true,
dataIndex: 'name',
field: {
xtype: 'textfield'
}
},{
text : 'E-Mail',
width : 150,
sortable : true,
dataIndex: 'email',
field: {
xtype: 'textfield'
}
},{
text : 'Href',
width : 200,
sortable : true,
dataIndex: 'href',
field: {
xtype: 'textfield'
}
}],
dockedItems: [{
xtype: 'toolbar',
items: [{
text: 'Add',
iconCls: 'icon-add',
handler: function(){
// empty record
store.insert(0, new MyLodge.model.Member());
rowEditing.startEdit(0, 0);
}
}, {
text: 'Delete',
iconCls: 'icon-delete',
handler: function(){
var selection = grid.getView().getSelectionModel().getSelection()[0];
if (selection) {
store.remove(selection);
}
}
},'-',{
text: 'Save',
iconCls: 'icon-save',
handler: function(){
store.sync();
}
}]
}]
});
this.callParent(arguments);
}
});
You can load store in callback of sync
store.sync({
success: function( response ) {
store.load();
}
});
You will probably want to call store.reload() in a callback from store.save() (what is store.save() anyway? it is not part of Ext.data.Store interface)

Resources