Related
Well considering a grid I create in my application:
{
xtype: 'ordergrid',
itemId: 'ordergrid',
titleBar: {
shadow: false,
items: [{
align: 'right',
xtype: 'button',
text: 'Update status',
stretchMenu: true,
menu: {
itemId: 'status_menu',
defaults: {
handler: 'updateStatus'
},
indented: false,
items: [{
text: 'test1',
value: 'test1'
}, {
text: 'test2',
value: 'test2'
}, {
text: 'test3',
value: 'test4'
}]
}
}]
},
With ordergrid being defined with:
extend: 'Ext.grid.Grid',
xtype: 'ordergrid',
I wish to modify the items of the menu dynamically. I've first tried doing this through a store:
menu: {
itemId: 'status_menu',
defaults: {
handler: 'updateStatus'
},
indented: false,
store: { type: 'status' }
Though this doesn't seem to work. Then I tried accessing this menu through a component query, during the init function of some controller:
Ext.define('BinkPortalFrontend.view.main.OrderController', {
extend: 'Ext.app.ViewController',
alias: 'controller.order',
init: function () {
console.log('..... initializing ......');
const menus = Ext.ComponentQuery.query('ordergrid #status_menu');
const menu = menus[0];
menu.setItems([{
text: 'some',
value: 'some'
}, {
text: 'new',
value: 'mew'
}]);
},
};
However this returns an error: "Cannot read property 'setItems' of undefined"
Debugging shows the obvious problem: it doesn't find any menu.
What's more, even a "catch all" query like
Ext.ComponentQuery.query('menu');
or
Ext.ComponentQuery.query('#status_menu');
Shows an empty array: so what's going on? (I most definitely see the menu from its initial load).
There is one reason your menu is not created. Menu will created whenever button will tap or whenever getMenu() method get called.
If you want to get your menu using Ext.ComponentQuery.query(), so for this you need to do use initialize event of button and forcefully create menu using getMenu() method like below :-
{
xtype: 'button',
text: 'Update status',
stretchMenu: true,
menu: {
itemId: 'status_menu',
indented: false,
items: [{
text: 'test1',
value: 'test1'
}, {
text: 'test2',
value: 'test2'
}, {
text: 'test3',
value: 'test4'
}]
},
listeners: {
initialize: function(btn) {
Ext.defer(function() {
// This will print undefined because menu have not created
console.log(Ext.ComponentQuery.query('#status_menu')[0]);
//When we use getMenu method it will create menu item
btn.getMenu().hide();
// This will print menu component
console.log(Ext.ComponentQuery.query('#status_menu')[0]);
}, 10)
}
}
}
Another way you can use getMenu() method of button. It will return the menu component.
In this FIDDLE, I have created a demo using grid, button and menu. I hope this will help/guide you to achieve your requirement.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
var store = Ext.create('Ext.data.Store', {
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": "home#simpsons.com",
"phone": "555-222-1244"
}, {
'name': 'Marge',
"email": "marge#simpsons.com",
"phone": "555-222-1254"
}]
});
Ext.create('Ext.grid.Grid', {
title: 'Change menu items dynamically',
titleBar: {
shadow: false,
items: [{
align: 'right',
xtype: 'button',
text: 'Update status',
stretchMenu: true,
itemId: 'statusbtn',
menu: {
itemId: 'status_menu',
defaults: {
// handler: 'updateStatus'
},
indented: false,
items: [{
text: 'test1',
value: 'test1'
}, {
text: 'test2',
value: 'test2'
}, {
text: 'test3',
value: 'test4'
}]
},
listeners: {
initialize: function (btn) {
Ext.defer(function () {
// This will undefined because menu has not been created
console.log(Ext.ComponentQuery.query('#status_menu')[0]);
//When we use getMenu method it will create menu item
btn.getMenu().hide();
// This will menu component
console.log(Ext.ComponentQuery.query('#status_menu')[0]);
}, 10)
}
}
}, {
xtype: 'button',
align: 'right',
text: 'Change Items',
handler: function (btn) {
var newItems = [];
store.each(rec => {
newItems.push({
text: rec.get('name'),
value: rec.get('name')
})
});
/*
* You can also get menu using button
* btn.up('titlebar').down('#statusbtn').getMenu().setItems(newItems);
*/
Ext.ComponentQuery.query('#status_menu')[0].setItems(newItems);
Ext.toast('Menu items has been change. Please check', 2000);
}
}]
},
store: store,
columns: [{
text: 'Name',
dataIndex: 'name',
width: 200
}, {
text: 'Email',
dataIndex: 'email',
width: 250
}, {
text: 'Phone',
dataIndex: 'phone',
width: 120
}],
height: 200,
layout: 'fit',
fullscreen: true
});
}
});
For more details about component you can also see this ComponentManager
I am working on extjs Grid panel which has 3 columns user, email, password .
On rowclick event, I want to decrypt the password. I am trying this by setting a type to 'text' in config of password field column.
But I am not able to see the decrypted password.
Please suggest me the solution.
Thanks in advance.
Ext.create('Ext.data.Store', {
storeId: 'simpsonsStore',
fields: ['name', 'email', 'phone'],
data: [{
"name": "Lisa",
"email": "lisa#simpsons.com",
"pass": "555-111-1224"
}, {
"name": "Bart",
"email": "bart#simpsons.com",
"pass": "555--1234"
}, {
"name": "Homer",
"email": "homer#simpsons.com",
"pass": "-222-1244"
}, {
"name": "Marge",
"email": "marge#simpsons.com",
"pass": "111-1254"
}]
});
Ext.create('Ext.grid.Panel', {
title: 'Simpsons',
store: Ext.data.StoreManager.lookup('simpsonsStore'),
listeners: {
rowclick: function (grid, record, e) {
var _this = this;
showPass('text');
function showPass(val) {
_this.getEl().component.columns[2].setConfig('type', "text");
}
}
},
columns: [{
header: 'Name',
dataIndex: 'name',
editor: 'textfield'
}, {
header: 'Email',
dataIndex: 'email',
flex: 1
}, {
header: "Password",
dataIndex: 'pass',
inputType: 'password',
renderer: function(val) {
var toReturn = "";
for (var x = 0; x < val.length; x++) {
toReturn += "●";
}
return toReturn;
}
}],
selType: 'rowmodel',
height: 200,
width: 400,
renderTo: Ext.getBody()
});
In ExtJs grid you can use widgetcolumn it provide config to add xtype inside widgetcolumn. You can refer ExtJs widgetcolumn docs
I have create small demo to show you, how it work. Sencha fiddle example
Hope it will help you.
Ext.create('Ext.data.Store', {
storeId: 'simpsonsStore',
fields: ['name', 'email', 'phone'],
data: [{
"name": "Lisa",
"email": "lisa#simpsons.com",
"pass": "555-111-1224"
}, {
"name": "Bart",
"email": "bart#simpsons.com",
"pass": "555--1234"
}, {
"name": "Homer",
"email": "homer#simpsons.com",
"pass": "-222-1244"
}, {
"name": "Marge",
"email": "marge#simpsons.com",
"pass": "111-1254"
}]
});
Ext.create('Ext.grid.Panel', {
title: 'Simpsons',
store: Ext.data.StoreManager.lookup('simpsonsStore'),
listeners: {
select: function (grid, record, index) {
this.doChangeInputType(this.query('#password')[index]);
},
deselect: function (grid, record, index) {
this.doChangeInputType(this.query('#password')[index]);
},
rowclick: function (grid, record, element, rowIndex, e, eOpts) {
this.getSelectionModel().select(record)
}
},
columns: [{
header: 'Name',
dataIndex: 'name',
editor: 'textfield'
}, {
header: 'Email',
dataIndex: 'email',
flex: 1
}, {
header: "Password",
flex: 1,
dataIndex: 'pass',
xtype: 'widgetcolumn',
widget: {
xtype: 'textfield',
itemId: 'password',
inputType: 'password',
readOnly: true
}
}],
selType: 'rowmodel',
height: 300,
width: '100%',
renderTo: Ext.getBody(),
doChangeInputType: function (passwordField) {
var inputDom = Ext.get(passwordField.getInputId()).dom,
type = inputDom.type;
inputDom.type = type == "text" ? 'password' : 'text';
}
});
Having a background in security I cannot think of a situation where it's valid to have decrypted passwords displayed in a GUI to end users.
I'm creating an app that simply shows customers information on a table, and if a user is being clicked then a pop-up window shows up showing user's information in a form (name and email). Within this PopUp I want to be able to update customers name and email and then when clicking on Update button I want the new information to show up on the table right away. As of right now I'm able to populate the table with customers' information as well as binding their information with the Pop-up window. But since I'm still kind of new to ExtJS I'm not really sure how to make the update to show right away on the table after clicking on update button. I would really appreciate any help!. Thanks a lot.
Here's my code that works just fine.
index.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css"
href="https://cdnjs.cat.net/ajax/libs/extjs/6.0.0/classic/theme-triton/resources/theme-triton-all-debug_1.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/extjs/6.0.0/ext-all.js"></script>
<script type="text/javascript">
Ext.define('UserModal', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'name', type: 'string'},
{name: 'email', type: 'string'}
]
});
Ext.onReady(function () {
// Ajax call
var usersFromAJAX = Ext.create('Ext.data.Store', {
storeId: 'user',
model: 'UserModal',
autoLoad: 'true',
proxy: {
type: 'ajax',
url: 'example.json',
reader: {
type: 'json',
root: 'customers'
}
}
});
// Setting up the Grid
Ext.create('Ext.grid.Panel', {
store: usersFromAJAX,
id: 'user',
title: 'Employees',
iconCls: 'x-fa fa-users',
listeners: {
itemclick: function (view, index, item, record) {
var window = Ext.create('Ext.window.Window', {
xtype: 'formpanel',
title: 'Update Record',
width: 300,
height: 200,
floating: true,
centered: true,
modal: true,
record: record,
viewModel: {
data: {
employee: index.data// employee's name
}
},
items: [{
xtype: 'textfield',
id: 'firstname',
name: 'firstname',
fieldLabel: 'First Name',
bind: '{employee.name}' // biding employee's name
},
{
xtype: 'textfield',
name: 'firstname',
fieldLabel: 'Email',
bind: '{employee.email}' // biding employee's name
},
{
xtype: 'toolbar',
docked: 'bottom',
style:{
background: "#ACCCE8",
padding:'20px'
},
items: ['->', {
xtype: 'button',
text: 'Update',
iconCls: 'x-fa fa-check',
handler: function () {
console.log("Updating name...");
// Need to add something in here
this.up('window').close();
}
}, {
xtype: 'button',
text: 'Cancel',
iconCls: 'x-fa fa-close',
handler: function () {
// this.up('formpanel').destroy();
this.up('window').close();
//this.up('window').destroy();
}
}]
}]
})
window.show();
}
},
columns: [{
header: 'ID',
dataIndex: 'id',
sortable: false,
hideable: true
}, {
header: 'NAME',
dataIndex: 'name',
}, {
header: 'Email',
dataIndex: 'email',
flex: 1 // will take the whole table
}],
height: 300,
width: 400,
renderTo: Ext.getElementById("myTable")
});
});
</script>
</head>
<body>
<div id="myTable"></div>
</body>
</html>
Here's the JSON that populates my table.
{
"customers": [{
"id": 1,
"name": "Henry Watson",
"email": "henry#email.com"
},
{
"id": 2,
"name": "Lucy",
"email": "lucy#email.com"
},
{
"id": 3,
"name": "Mike Brow",
"email": "Mike#email.com"
},
{
"id": 4,
"name": "Mary Tempa",
"email": "mary#email.com"
},
{
"id": 5,
"name": "Beto Carlx",
"email": "beto#email.com"
}
]
}
Binding is for "live" data, so that means it will update the grid as you type. If you want to defer the changes until you hit a button, you can use methods on the form to do so:
Fiddle
Ext.define('UserModal', {
extend: 'Ext.data.Model',
fields: ['id', 'name', 'email']
});
Ext.onReady(function () {
// Setting up the Grid
Ext.create('Ext.grid.Panel', {
store: {
model: 'UserModal',
autoLoad: 'true',
proxy: {
type: 'ajax',
url: 'data1.json',
reader: {
type: 'json',
rootProperty: 'customers'
}
}
},
listeners: {
itemclick: function (view, record) {
var f = Ext.create('Ext.form.Panel', {
xtype: 'formpanel',
title: 'Update Record',
width: 300,
height: 200,
floating: true,
centered: true,
modal: true,
buttons: [{
text: 'Update',
iconCls: 'x-fa fa-check',
handler: function () {
f.updateRecord(record);
f.close();
}
}, {
text: 'Cancel',
iconCls: 'x-fa fa-close',
handler: function () {
f.close();
}
}],
items: [{
xtype: 'textfield',
id: 'firstname',
name: 'name',
fieldLabel: 'First Name'
}, {
xtype: 'textfield',
name: 'email',
fieldLabel: 'Email'
}]
})
f.show();
f.loadRecord(record);
}
},
columns: [{
header: 'ID',
dataIndex: 'id',
sortable: false,
hideable: true
}, {
header: 'NAME',
dataIndex: 'name',
}, {
header: 'Email',
dataIndex: 'email',
flex: 1 // will take the whole table
}],
height: 300,
width: 400,
renderTo: document.body
});
});
I'm a new in ext.js and I'm trying to figure why this example I borrowed from tutorial on http://docs.sencha.com/extjs/6.5.1/guides/quick_start/handling_events.html
doesn't work for me.
I added two listeners to code: itemmouseenter - it's work correctly, and itemtap - it's not working.
Ext.create('Ext.tab.Panel', {
renderTo: Ext.getBody(),
xtype: 'tabpanel',
items: [{
title: 'Employee Directory',
xtype: 'grid',
iconCls: 'x-fa fa-users',
listeners: {
itemmouseenter: function() {
console.log( 'Mouse Enter');
},
itemtap: function(view, index, item, e) {
console.log("item tap")
}
},
store: {
data: [{
"firstName": "Jean",
"lastName": "Grey",
"officeLocation": "Lawrence, KS",
"phoneNumber": "(372) 792-6728"
}, {
"firstName": "Phillip",
"lastName": "Fry",
"officeLocation": "Lawrence, KS",
"phoneNumber": "(318) 224-8644"
}, {
"firstName": "Peter",
"lastName": "Quill",
"officeLocation": "Redwood City, CA",
"phoneNumber": "(718) 480-8560"
}]
},
columns: [{
text: 'First Name',
dataIndex: 'firstName',
flex: 1
}, {
text: 'Last Name',
dataIndex: 'lastName',
flex: 1
}, {
text: 'Phone Number',
dataIndex: 'phoneNumber',
flex: 1
}]
}, {
title: 'About Sencha',
iconCls: 'x-fa fa-info-circle'
}]
});
In classic the event is itemclick. The sample you're looking at is for modern.
As I have checked in sencha fiddle itemtap is working fine for modern but for Classic you have to user itemlick. I am using your same code in my fiddle you can check by given below link:-
EXTJS GRID ITEM TAP
Ext.application({
name : 'Fiddle',
launch : function() {
var panel = Ext.create('Ext.window.Window', {
width:'100%',
height:'100%',
layout:'fit',
items:[{
xtype: 'tabpanel',
items: [{
title: 'Employee Directory',
xtype: 'grid',
layout:'fit',
iconCls: 'x-fa fa-users',
listeners: {
itemmouseenter: function() {
console.log('Mouse Enter');
},
itemclick: function(grid, record, item, index, e, eOpts) {
Ext.Msg.alert('Info',`You have tapped on ${index+1} item`);
}
},
store: {
data: [{
"firstName": "Jean",
"lastName": "Grey",
"officeLocation": "Lawrence, KS",
"phoneNumber": "(372) 792-6728"
}, {
"firstName": "Phillip",
"lastName": "Fry",
"officeLocation": "Lawrence, KS",
"phoneNumber": "(318) 224-8644"
}, {
"firstName": "Peter",
"lastName": "Quill",
"officeLocation": "Redwood City, CA",
"phoneNumber": "(718) 480-8560"
}]
},
columns: [{
text: 'First Name',
dataIndex: 'firstName',
flex: 1
}, {
text: 'Last Name',
dataIndex: 'lastName',
flex: 1
}, {
text: 'Phone Number',
dataIndex: 'phoneNumber',
flex: 1
}]
}, {
title: 'About Sencha',
iconCls: 'x-fa fa-info-circle'
}]
}]
});
panel.show()
}
});
I want to group the values in grid panel
Below is the code:
var store = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: [
{ text: "School Friends", expanded: true, children: [
{ text: "Mike", leaf: true, name: "Mike", email: "mike#stackoverflow.com", phone: "345-2222"},
{ text: "Laura", leaf: true, name: "Laura", email: "laura#stackoverflow.com", phone: "345-3333"}
] },
{ text: "Facebook Friend", expanded: true, children: [
{ text: "Steve", leaf: true, name: "Steve", email: "steve#stackoverflow.com", phone: "345-2222"},
{ text: "Lisa", leaf: true, name: "Lisa", email: "lisa#stackoverflow.com", phone: "345-3333"}
] },
]
}});
Ext.create('Ext.tree.Panel', {
title: 'All My Friends',
width: 200,
height: 150,
store: store,
rootVisible: false,
renderTo: Ext.getBody(),
listeners : {
itemdblclick : function(tree, record, index){
Ext.getStore('simpsonsStore').loadRawData([record.raw], true);
}
}});
Ext.create('Ext.data.Store', {
storeId:'simpsonsStore',
fields:['name', 'email', 'phone'],
data:{'items':[
{ 'name': 'Bart', "email":"bart#simpsons.com", "phone":"555-222-1234" },
{ 'name': 'Homer', "email":"home#simpsons.com", "phone":"555-222-1244" },
{ 'name': 'Marge', "email":"marge#simpsons.com", "phone":"555-222-1254" }
]},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'items'
}
}});
Ext.create('Ext.grid.Panel', {
title: 'Best Friends',
store: Ext.data.StoreManager.lookup('simpsonsStore'),
columns: [
{ text: 'Name', dataIndex: 'name' },
{ text: 'Email', dataIndex: 'email', flex: 1 },
{ text: 'Phone', dataIndex: 'phone' }
],
height: 200,
width: 400,
renderTo: Ext.getBody()});
From the above code I am able to get the values from treepanel to grid panel by double clicking.
I want an extra column to group values if we double click the same leaf in the treepanel.
For example if we double click Bart 6 times
Name email phonenumber groupby(number of times)
Bart bart#simpsons.com 555-222-1234 6
It should not append same value in the grid panel.
Could any one please help me.
Regards,
sreekanth
You'll need to add a count field to your store's fields. Then, you'll need to add the field to your grid. When you double-click the tree, you'll need to check the store to see if the record already exists. If it does, change the value in the count field; otherwise, add a new row.
itemdblclick: function (tree, record, index) {
var s = Ext.getStore('simpsonsStore'),
existingRecIdx = s.findBy(function (r) {
return r.get('email') === record.raw['email'];
});
if (existingRecIdx === -1) { //row not found
record.raw.clickCt = 1;
s.loadRawData([record.raw], true);
} else {
var r = s.getAt(existingRecIdx);
r.data.clickCt++;
grid.getView().refresh(); //once the data has changed
//refresh the grid
}
}
See http://jsfiddle.net/Kk7gL/