I am using EXTJS and I want to create my TreePanel with one more icon to the right that will be set to indicate something has changed. I am struggling to do this as I am unsure where I can modify these properties. It would be easy with HTML alone but obviously this framework is useful and I need to integrate these changes into it.
Thanks,
Dan
Yes, there is way to handle it in ExtJS framework with renderer method on column.
Here is how I would achieve it using ExtJS 6.0.x:
Ext.create('Ext.container.Viewport', {
layout: 'fit',
items: [{
xtype: 'container',
scrollable: 'y',
flex: 1,
layout: {
type: 'hbox',
alignt: 'stretchmax'
},
items: [{
xtype: 'treepanel',
rootVisible: false,
flex: 1,
store: {
type: 'tree',
parentIdProperty: 'parentId',
root: {
text: 'Navigation Bar',
expanded: true,
children: [{
text: 'Parts',
children: [{
leaf: true,
itemId: 'addPart',
text: 'Add new part',
changed: true
}, {
leaf: true,
itemId: 'manageParts',
text: 'Manage Parts',
changed: false
}, ]
}, {
leaf: true,
itemId: 'announcements',
text: 'Announcements',
changed: true
}]
}
},
columns: [{
text: 'Code',
dataIndex: 'codigo',
align: 'left'
}, {
xtype: 'treecolumn',
text: 'Description',
dataIndex: 'text',
flex: 1
}, {
text: 'Edited',
iconCls: 'x-fa fa-edit',
align: 'center',
flex: 1,
renderer: function (f, grid, record) {
if(record.get('changed') === true) {
return "Changed Icon here"
}
else {
return "Not changed icon here";
}
}
}]
}]
}]
});
With this you can easily manage the data with store and can easily update the data in store. ExtJS will take care of rendering the given configuration for columns.
You can also use actioncolumn to show icons/buttons and handle events with listeners.
Example Fiddle: https://fiddle.sencha.com/#view/editor&fiddle/28qm
I Have solved the problem. You can embed html into the text field in the store.
Ext.define('MyApp.store.Navigation', {
extend: 'Ext.data.TreeStore',
alias: 'store.navigation',
rootData: {
text: 'Navigation Bar',
expanded: true,
children: [
{
text: 'Parts',
children: [
{ leaf:true, itemId:'addPart', text: 'Add new part' },
{ leaf:true, itemId:'manageParts', text: 'Manage Parts <b>here</b>' },
]
},
{
leaf:true, itemId:'announcements', text: 'Announcements'
}
]
},
constructor: function (config) {
// Since records claim the data object given to them, clone the data
// for each instance.
config = Ext.apply({
root: Ext.clone(this.rootData)
}, config);
this.callParent([config]);
}
});
Probably a poor solution but gets the job done.
Related
I am working on Ext JS 6.5 modern. I have some condition to disable the grid component, user has only rights to view the grid no one else.
I have tried disabled config and disable method but not working. Here is my Fiddle.
Code snippet
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.create('Ext.data.Store', {
storeId: 'gridStore',
fields: ['name'],
data: [{
name: 'Test 1'
}, {
name: 'Test 2'
}, {
name: 'Test 3'
}, {
name: 'Test 4'
}]
});
Ext.create({
xtype: 'grid',
layout: 'fit',
fullscreen: true,
title: 'Baisc grid example',
store: 'gridStore',
//Here I have put {disabled: true} but not working
disabled: true,
columns: [{
text: 'Name',
flex: 1,
dataIndex: 'name'
}],
listeners: {
childtap: function (grid, location, eOpts) {
alert('childtap');
}
},
items: [{
xtype: 'toolbar',
items: {
xtype: 'button',
ui: 'action',
text: 'Disabled grid',
iconCls: 'x-fa fa-ban',
handler: function () {
//IT is also not working
this.up('grid').setDisabled(true);
this.up('grid').disable();
}
}
}]
//renderTo:Ext.getBody()
});
}
});
Somebody please help me with a solution for disabling the grid component.
As a workaround we can use grid.setMasked(true);
Here is the example Fiddle.
Another approach is to set grid's hideMode to opacity and then set it to hidden (this.up('grid').setHidden(true);).
For Example (editing your fiddle)
Ext.create('Ext.data.Store', {
storeId: 'gridStore',
fields: ['name'],
data: [{
name: 'Test 1'
}, {
name: 'Test 2'
}, {
name: 'Test 3'
}, {
name: 'Test 4'
}]
});
Ext.create({
xtype: 'grid',
layout: 'fit',
fullscreen: true,
title: 'Baisc grid example',
store: 'gridStore',
//Here I have put {disabled: true} but not working
//disabled: true,
hideMode: 'opacity',
columns: [{
text: 'Name',
flex: 1,
dataIndex: 'name'
}],
listeners: {
childtap: function (grid, location, eOpts) {
alert('childtap');
}
},
items: [{
xtype: 'toolbar',
items: {
xtype: 'button',
ui: 'action',
text: 'Disabled grid',
iconCls: 'x-fa fa-ban',
handler: function () {
this.up('grid').setHidden(true);
}
}
}]
//renderTo:Ext.getBody()
});
Also you need this css override:
<style>
.x-hidden-opacity {
opacity: 0.2 !important; //default is 0
pointer-events: none;
}
</style>
so I have a view where I display a combobox and a grid that share a 'Roles' store. If you pick an option on the combobox, the grid will be filtered accordingly.
I am looking for a way to add an "All" option to the combobox that is selectable (so placeholder or value attributes don't work for me). I want to do this because I cannot add that option to the store without affecting the grid as well.
This is my code:
Ext.define("MODIFE.view.administration.Roles",{
extend: "Ext.panel.Panel",
xtype: "app-administration-roles",
controller: "administration-roles",
viewModel: {
type: "administration-users"
},
title: "Roles",
items:[
{
title: 'Búsqueda de Roles',
frame: true,
resizable: true,
xtype: 'form',
layout: 'column',
defaults: {
layout: 'form',
xtype: 'container',
defaultType: 'textfield',
style: 'width: 50%'
},
items: [{
items: [{
fieldLabel: 'Rol',
xtype: 'combobox',
store: 'Roles',
displayField: 'Description',
valueField: 'RoleId',
}]
}, {
items: [
{ fieldLabel: 'Estatus', xtype: 'combobox' },
]
}],
buttons: [
{ text: 'Nuevo' },
{ text: 'Buscar' }
]
},
{
layout: 'fit',
items: [{
xtype: 'grid',
id: 'rolesGrid',
title: 'Listado de Roles',
store: 'Roles',
columns: [
{ text: 'Rol', dataIndex: 'Description', flex: 2},
{ text: 'Estatus', dataIndex: 'Status', flex: 2},
]
}]
}]
});
Thanks in advance!
You could clone the store, then any alterations wont be reflected in the original store. (but it's messy, and may have problems with syncing if you have this enabled)
//clone store
var records = [],
me = this;
me.store.each(function(r){
records.push(r.copy());
});
var store2 = new Ext.data.Store({
recordType: me.store.recordType,
model: me.store.model
});
store2.add(records);
//add record
store2.add({ID:"-1", NAME: "-Please select-"});
The Ext.grid.plugin.DragDropView and Ext.tree.plugin.TreeViewDragDropView are great to allow drag'n'drop functionnality over those components but I don't want the store modification thing when I drag and drop an item.
I want custom functions, like, when I drop an item on my grid, I don't want the drag component source store to be modified and I don't want the drop component store to be modified too. I would like a function of mine to be called instead.
How to do this?
Do I need to use DragZone and DropZone instead?
You are on the right path, and looking in the right areas. The plugins that you have mentioned are exactly what you need for this purpose and provide the DragZone and DropZone functionality within.
I have written a simple example of using these plugins together, Fiddle Here.
The thing to watch out for here... If you do not want the default functionality of moving a record between stores you will likely need to run your own logic in the beforeDrop event and call the cancelDrop method, to prevent default behaviour, this is demonstrated in the fiddle and code below.
Make sure that both plugins share the same ddGroup.
Ext.application({
name: 'Fiddle',
launch: function() {
// create a very simple tree view
var treeStore = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: [{
text: "detention",
leaf: true
}, {
text: "homework",
expanded: true,
children: [{
text: "book report",
leaf: true
}, {
text: "algebra",
leaf: true
}]
}, {
text: "buy lottery tickets",
leaf: true
}]
}
});
var gridStore = Ext.create('Ext.data.Store', {
storeId: 'simpsonsStore',
fields: ['name', 'email', 'phone'],
data: {
'items': [{
'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"
}]
},
proxy: {
type: 'memory',
reader: {
type: 'json',
rootProperty: 'items'
}
}
});
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
layout: 'fit',
height: 800,
width: 800,
items: [{
layout: 'border',
title: "DnD",
height: '100%',
items: [{
xtype: 'grid',
region: 'center',
store: gridStore,
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Email',
dataIndex: 'email',
flex: 1
}, {
text: 'Phone',
dataIndex: 'phone'
}],
viewConfig: {
plugins: {
ptype: 'gridviewdragdrop',
enableDrag: false,
enableDrop: true,
ddGroup: 'myDropGroup'
},
listeners: {
beforedrop: function(node, data, overModel, dropPosition, dropHandlers) {
// Defer the handling
dropHandlers.wait = true;
// here you have the record from the treeview and can do anything you like with it.
var record = data.records[0];
Ext.MessageBox.confirm('Drop', 'Your are about to drop ' + record.get('text') + ', Are you sure?', function(btn) {
if (btn === 'yes') {
dropHandlers.processDrop();
} else {
// IMPORTANT - In this case, we want to cancel the drop as the records aren't compatible
dropHandlers.cancelDrop();
}
});
}
}
}
}, {
xtype: 'treepanel',
width: '40%',
region: 'west',
store: treeStore,
rootVisible: false,
viewConfig: {
plugins: {
ptype: 'treeviewdragdrop',
enableDrop: false,
ddGroup: 'myDropGroup'
}
}
}]
}]
});
}
});
I'm pretty new to web development and ExtJS, I've looked around for tutorials on more complex concepts but they are hard to find (Yes I've found the Sencha documentation but the only provide simple concepts)
I'm trying to make a dashboard for my application, in this dashboard I want a chart
that gives a detailed overview of my statistics. In order to accomplish this I am trying to add a custom filter for the chart by making a seperate list with that holds all the instances of the key, when selecting said instances from a list I want the chart to only display those selected instances.
The chart I made:
Ext.define('view.chart.LocationStatisticsPerMonth', {
extend: 'Ext.chart.Chart',
alias: 'widget.LocationStatisticsPerMonthChart',
requires: [
'store.LocationStatisticsStore',
'store.TemplateStore',
'view.TitleToolbar'
],
constructor: function () {
this.store = Ext.create('store.LocationStatisticsStore', {
autoLoad: true, sorters: [{
property: 'YearMonth',
direction: 'ASC'
}]
});
this.store.getProxy().api.read = ServerControllers.Dashboard.LocationStatisticsPerMonth;
this.callParent(arguments);
},
animate: true,
shadow: true,
border: true,
legend: {
position: 'right'
},
axes: [{
type: 'Numeric',
position: 'left',
fields: ['TotalCount'],
title: false,
grid: true,
label: {
renderer: function (v) {
return String(v);
}
}
}, {
type: 'Category',
position: 'bottom',
fields: ['Location_Id'],
title: false,
label: {
rotate: {
degrees: 315
}
}
}],
series: [{
type: 'column',
axis: 'left',
gutter: 80,
xField: ['Location_Id'],
yField: ['TotalCount'],
tips: {
trackMouse: true,
width: 125,
height: 28,
renderer: function(storeItem, item) {
this.setTitle(String('Visitors: '+item.value[1]));
}
}
}]
});
My Store
Ext.define('store.LocationStatisticsStore', {
extend: 'Ext.data.Store',
requires: ['model.LocationStatistics'],
model: 'model.LocationStatistics',
autoLoad: false,
remoteSort: false,
remoteFilter: false,
filterOnLoad: true,
sorters: [{
property: ['YearMonth' , 'Location_Id'],
direction: 'DESC'
}],
proxy: {
type: 'direct',
paramOrder: [],
api: {
read: ServerControllers.Reports.GetLocationStatisticsPerMonth
},
reader: {
type: 'json',
root: 'data',
totalProperty: 'totalRecords',
successProperty: 'success',
messageProperty: 'msg'
}
}
});
My Model:
Ext.define('model.LocationStatistics', {
extend: 'Ext.data.Model',
idProperty: ['Location_Id'],
fields: [
{ name: 'YearMonth', type: 'string' },
{ name: 'Location_Id', type: 'int' },
{ name: 'Year', type: 'int' },
{ name: 'Month', type: 'int' },
{ name: 'TotalCount', type: 'int' },
{ name: 'AverageCountPerDay', type: 'int' }
]
});
Would anyone be so kind as to explain this concept to me, link a tutorial or provide me an example of how to go about doing this?
Help is greatly appreciated.
EDIT: the panel that this is contained in:
Ext.define('view.panel.DashboardStatisticsPanel', {
extend : 'Ext.panel.Panel',
alias : 'widget.DashboardStatisticsPanel',
requires : [
'Ext.layout.container.Column',
'view.chart.LocationStatisticsPerMonth'
],
plain: true,
border: false,
layout: {
type: 'hbox',
padding: '10 10 10 10'
},
items: [{
xtype: 'panel',
layout: 'fit',
border: true,
flex: 1,
items: [{
xtype: 'panel',
layout: 'anchor',
border: true,
overflowX: 'scroll',
height: 400,
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
items: [{
xtype: 'label',
text: 'Select Date',
padding: '0 0 0 10'
},
{
xtype: 'combobox',
displayField: 'YearMonth',
emptyText: 'Select Date ',
queryMode: 'local',
padding: '0 0 0 10',
store: function (btn) {
btn.up('panel').down('LocationStatisticsPerMonthChart').getStore();
},
valueField: 'YearMonth',
}]
}]
/*tbar: [{
text: 'September Only',
handler: function (btn) {
var store = btn.up('panel').down('LocationStatisticsPerMonthChart').getStore();
store.clearFilter();
Ext.defer(function (btn) {
store.filter("Month", 9);
}, 300);
}
}]*/,
items: [{
xtype: 'LocationStatisticsPerMonthChart',
itemId: 'LocationStatisticsPerMonthChart',
anchor: '2000, -10',
//height: 400,
// width: 2000,
}]
}],
dockedItems: [{
xtype: 'TitleToolbar',
dock: 'top',
title: Resources.t('RegistrationsPerUnit'),
items: ['->', {
iconCls: 'iconRefresh',
itemId: 'refresh',
scope: this,
handler: function (btn) {
var store = btn.up('panel').down('LocationStatisticsPerMonthChart').getStore();
//store.removeAll();
store.load();
}
}]
}]
}]
});
The best way is to use a function, I'll give you an example:
We have a store, let's call it StoreA, and another store StoreB
var storeA = something.getStore();
var storeB = somethingElse.getStore();
storeA.filterBy(function(record) {
return storeB.find("name", record.data.name) != -1;
});
So basicly in this example, if the name is in storeB (find returns an index), it will filter it out from storeA's contents.
Unfortunately, you will have to re-do the exact same filter every time a new record is added or updated... so what I do is bind a function that does this to the load, update, delete, etc.. events.
You only need to filter the related data store. To accomplish this use the filter method as follows:
chart.store.filter("Month", 10);
You can always remove the filtering on the store by calling clearFilter store's method,
chart.store.clearFilter();
Take into account that you need to remove previous filters when applying new ones otherwise the each new applied filter will stack with the current ones
You can see a small example based on your code here. Hope it helps you to solve your problem.
I am trying to add Checkboxes for a Rally Report version 2.00p2.
I defined severals place holders for the filter (releaseFilter and stateFilter)
and Adding the checkboxes at the body of the onReady function at the end.
However, Instead of 5 different checkbox I get 1 and on top of the Release filter.
Sorry But I couldn't add an Image.
Rally.onReady(function() {
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
autoScroll: 'true',
items: [
{
xtype: 'container',
itemId: 'releaseFilter',
style: {
margin: '5px'
}
},
{
xtype: 'container',
itemId: 'stateFilter',
style: {
margin: '5px'
}
},
{
xtype: 'container',
itemId: 'grid',
style: {
margin: '10px',
}
},
// SOME CODE
],
launch: function() {
Rally.data.ModelFactory.getModel({
type: 'UserStory',
success: function(model) {
this.grid = this.add({
xtype: 'rallygrid',
model: model,
columnCfgs: [
'FormattedID',
'Release',
'Iteration',
'PlanEstimate',
'PlanDevEstDays',
'PlanQAEstDays'
],
storeConfig: {
filters: [
{
property: 'ScheduleState',
operator: '=',
value: 'Accepted'
}
]
}
});
this.down('#releaseFilter').add(
{
xtype: 'rallyreleasecombobox'
}
);
this.down('#stateFilter').add([{
xtype: 'menucheckitem',
text: 'Backlog',
floating: 'false'
},{
xtype: 'menucheckitem',
text: 'Defined'
},{
xtype: 'menucheckitem',
text: 'In-Progress'
},{
xtype: 'menucheckitem',
text: 'Completed'
},{
xtype: 'menucheckitem',
text: 'Accepted'
}]
);
},
scope: this
});
}
});
Rally.launchApp('CustomApp', {
name: 'Grid Example'
});
});
The original Entry in your javadoc is:
Ext.create('Ext.menu.Menu', {
width: 100,
height: 110,
floating: false, // usually you want this set to True (default)
renderTo: Ext.getBody(), // usually rendered by it's containing component
items: [{
xtype: 'menucheckitem',
text: 'select all'
},{
xtype: 'menucheckitem',
text: 'select specific',
},{
iconCls: 'add16',
text: 'icon item'
},{
text: 'regular item'
}]
});
What did I do wrong ?
Instead of using menucheckitem, use a standard Ext checkbox. Like this:
this.down('#stateFilter').add([{
xtype: 'checkbox',
fieldLabel: 'Backlog'
},
...
]);
Be sure change it from text to fieldLabel