There is a need to dynamically change a view in ExtJS 4 grid panel.
By default grid is displayed as a table, but in my application I need a feature to switch grid from table view to tiles (or cards) view. Below I tried to represent how it should look like.
Normal view: Tiles view:
====================================== ====================================
| Name | Description | | Name | Description |
====================================== ====================================
| Name 1 | First description |^| | ------ ------ ------ |^|
|----------------------------------|X| | | O O | | # # | | > < | |X|
| Name 2 | Second description |X| | | \__/ | | \__/ | | \__/ | |X|
|----------------------------------|X| | ------ ------ ------ |X|
| Name 3 | Third description | | | Name 1 Name 2 Name 3 | |
|----------------------------------| | | | |
| | | | | ------ ------ ------ | |
| ... | ... |v| | | o O | | - - | | * * | |v|
====================================== ====================================
I have found almost perfect implementation of what I need, named Ext.ux.grid.ExplorerView. However, the extension was developed for ExtJS versions 2.x (3.x), and cannot be reused for ExtJS 4.
I use a grid which is created as simple as:
Ext.create("Ext.grid.Panel", {
store: ...,
columns: [{
header: "Name",
dataIndex: "name",
}, {
header: "Description",
dataIndex: "description"
}],
tbar: [ ... ],
bbar: [ ... ],
listeners: { ... },
multiSelect: true,
viewConfig: {
stripeRows: true,
markDirty: false,
listeners: { ... }
}
});
I have tried to update tpl property of the inner view component, but nothing seems to work.
Do you have any idea of how to make the dynamic switch between the views for a single grid panel?
The problem was easily solved with wonderful feature for grid panel named "Tileview" developed by Harald Hanek. The solution was specially developed for ExtJS 4.
The basic usage example is:
var grid = Ext.create("Ext.grid.Panel", {
store: ...,
columns: [{
header: "Name",
dataIndex: "name",
}, {
header: "Description",
dataIndex: "description"
}],
tbar: [ ... ],
bbar: [ ... ],
listeners: { ... },
multiSelect: true,
viewConfig: {
stripeRows: true,
markDirty: false,
listeners: { ... }
},
features: [Ext.create("Ext.ux.grid.feature.Tileview", {
getAdditionalData: function(data, index, record, orig) {
if (this.viewMode) {
return {
name: record.get("name").toLowerCase(),
};
}
return {};
},
viewMode: 'tileIcons', // default view
viewTpls: {
tileIcons: [
'<td class="{cls} ux-tileview-detailed-icon-row">',
'<table class="x-grid-row-table">',
'<tbody>',
'<tr>',
'<td class="x-grid-col x-grid-cell ux-tileview-icon" style="background-image: url("...");">',
'</td>',
'<td class="x-grid-col x-grid-cell">',
'<div class="x-grid-cell-inner">{name}</div>',
'</td>',
'</tr>',
'</tbody>',
'</table>',
'</td>'
].join(""),
mediumIcons: [ ... ].join(""),
largeIcons: [ ... ].join("")
}
})]
});
To change the view we should just use setView() method, i.e.
grid.features[0].setView("tileIcons");
That's how the feature looks like in the real life.
Example of tile view:
Example of image view:
References:
https://github.com/harrydeluxe/extjs-ux/blob/master/ux/grid/feature/Tileview.js -- Tileview sources
https://github.com/harrydeluxe/extjs-ux -- All Harald's extensions with screenshots
http://www.sencha.com/forum/showthread.php?183023-Thumbnails-in-Grid-with-switching-between-views -- Feature discussion node on Sencha forum
http://harrydeluxe.github.com/extjs-ux/example/grid/tileview.html -- Demo
I wouldn't do it like that. Instead, have a grid and a view in a card layout, the view gives you the ability to have pretty much any markup per item, here's a simple example:
Ext.define('Thing', {
extend: 'Ext.data.Model',
fields: ['name']
});
Ext.require('*');
Ext.onReady(function() {
var store = Ext.create('Ext.data.Store', {
model: Thing,
data: [{
name: 'Name 1'
}, {
name: 'Name 2'
}, {
name: 'Name 3'
}]
});
var gridActive = true;
var panel = Ext.create('Ext.panel.Panel', {
renderTo: document.body,
width: 400,
height: 400,
layout: 'card',
tbar: [{
text: 'Switch',
handler: function(){
var item;
if (gridActive) {
item = panel.items.last();
} else {
item = panel.items.first();
}
gridActive = !gridActive;
panel.getLayout().setActiveItem(item);
}
}],
items: [{
border: false,
xtype: 'gridpanel',
columns: [{
text: 'Name',
dataIndex: 'name'
}],
store: store
}, {
xtype: 'dataview',
itemTpl: '<b>{name}</b>',
store: store
}]
});
});
Related
I'm trying to create an Ext.Window and i'm trying to organize it with pannels, I already have them created but I don't know how to give them a good extructure, I want a icon and two sentences, something like this:
-------------------------------
| | TEXT 1
| Icon | -----------------
| | TEXT 2
-------------------------------
I used the following code:
Panel1 = new Ext.Panel({
header: false,
frame: false,
border: false,
collapsible: false,
layout: 'column',
items [{
xtype: 'label',
text: "text 1",
style: 'font-size:12px; margin-left: 20px; margin-top: 30px'
}]
});
Panel2 = new Ext.Panel({
header: false,
frame: false,
border: false,
collapsible: false,
layout: 'column',
items [{
xtype: 'label',
text: "text 2",
style: 'font-size:12px; margin-left: 20px; margin-top: 30px'
}]
});
myNewWindow = nex Ext.Window({
width: 400,
height: 250,
items : [myIcon, Panel1, Panel2]
});
myNewWindow.show()
but it's being showed like this:
-------------
| A |
-------------
| B |
-------------
| C |
-------------
I'm trying to create an application. Where I'm using tinymce as editor. In the file panel, I don;t want to show new document. Corrently it's rendering:
But I just want to render it with thse two options:
Can anyone help me with it?
Here is my related config:
plugins: 'print preview ...',
menubar: 'file edit ...',
thanks.
Per the documentation if you want to control what you see on each discrete menu you have to provide those choices explicitly:
https://www.tiny.cloud/docs/configure/editor-appearance/#menu
The defaults are:
menu: {
file: { title: 'File', items: 'newdocument restoredraft | preview | print ' },
edit: { title: 'Edit', items: 'undo redo | cut copy paste | selectall | searchreplace' },
view: { title: 'View', items: 'code | visualaid visualchars visualblocks | spellchecker | preview fullscreen' },
insert: { title: 'Insert', items: 'image link media template codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor toc | insertdatetime' },
format: { title: 'Format', items: 'bold italic underline strikethrough superscript subscript codeformat | formats blockformats fontformats fontsizes align lineheight | forecolor backcolor | removeformat' },
tools: { title: 'Tools', items: 'spellchecker spellcheckerlanguage | code wordcount' },
table: { title: 'Table', items: 'inserttable | cell row column | tableprops deletetable' },
help: { title: 'Help', items: 'help' }
}
So if you only want 2 items on the file menu you would have to state that explicitly within the broader menu option:
file: { title: 'File', items: 'preview | print ' },
Here is a TinyMCE Fiddle showing this in action: https://fiddle.tiny.cloud/hYhaab
I have the following grid definition:
$(document).ready(function () {
$("#thegrid").jqGrid({
url: "/ajax/questions/get/" + form_id,
datatype: "json",
colNames: ['id', 'grid_id', 'seq', 'type', 'text'],
colModel: [
{name: 'field_id', index: 'id', width: 100, editable: false, search: false},
{name: 'grid_id', index: 'grid_id', width: 50, editable: false, search: false},
{name: 'field_seq', index: 'seq', width: 45, editable: false, search: false},
{name: 'type', index: 'type', width: 125, editable: false, search: false},
{name: 'field_name', index: 'text', width: 585, search: false}
],
autowidth: true,
rowNum: 200,
cmTemplate: {width: 300, autoResizable: true},
iconSet: "fontAwesome",
guiStyle: "bootstrap",
autoResizing: {compact: true, resetWidthOrg: true},
viewrecords: true,
autoencode: true,
sortable: true,
pager: true,
toppager: true,
hoverrows: true,
multiselect: true,
multiPageSelection: false,
rownumbers: true,
loadonce: true,
autoresizeOnLoad: true,
forceClientSorting: true,
ignoreCase: true,
prmNames: {id: "field_id"},
jsonReader: {id: "field_id"},
localReader: {id: "field_id"},
navOptions: {edit: false, add: false, search: false, del: false, refresh: true},
pgbuttons: false,
pginput: false,
caption: "Questions",
height: 100,
editurl: '/ajax/questions/edit',
onSelectRow:
function () {
// ....
},
loadComplete: function () {
// ...
}
})
});
With the code above it's possible to sort the rows by dragging them and dropping at some position at the grid.
In order to keep this changes I have a function in the backend that takes a form_id (I have this stored at sessionStorage) and an array of field_id => field_seq and do some magic at DB level.
Take a look at the following picture which is a grid that has been loaded for first time:
Now let's say I am dragging & dropping the colored row (id: 219110) into the first row position. That will makes the first row (id: 219110) to move one row down (same will happen to all rows after that one) and then the moved row will take the first position. See example below:
before:
+--------+--------+-----+
| id | gri_id | seq |
+--------+--------+-----+
| 219111 | | 1 |
| ... | | ... |
| 219110 | | 4 |
+--------+--------+-----+
after:
+--------+--------+-----+
| id | gri_id | seq |
+--------+--------+-----+
| 219110 | | 1 |
| 219111 | | 2 |
| ... | | ... |
+--------+--------+-----+
I need to build and array with the id as the key and the seq as the value so I can pass this later on to an AJAX backend function which will care about store the new data.
How do I achieve this?
You can use lastSelectedData parameter of jqGrid to get the items, which users sorted and filtered previously. The old answers: this one and another one provides the demos, which demonstrates the usage of lastSelectedData.
In general, jqGrid contains internally some JavaScript methods, which are used for sorting and filtering of local data. I described in the old answer tricky technique, which works on old jqGrid (i version <=4.7). Already in the first version of "free jqGrid" fork I implemented lastSelectedData parameter (see the readme), which makes working with the last sorted and filtered local data very easy.
I want to construct simple register with the grid component with tittle bar and bottom bar constant (I mean title visible always on top and bottom bar visible always on the bottom of the screen):
-------------------------------------
| title bar |
|-----------------------------------|
| |
| pure grid, only rows |
| |
|-----------------------------------|
| bottom bar |
-------------------------------------
simple but I have a problem to set grid parameters. When I set "layout: 'fit'" bottom bar is not visible until I scroll down to the end of the screen. And in this place I can't see title bar.
I want to scroll only rows but app scrolls all the elements.
Be so kind as to prompt me how should I set parameters.
Something like:
Ext.define('MyApp.view.Ranking', {
extend: 'Ext.Panel',
...
requires: [
'Ext.grid.View',
'Ext.grid.column.Number'
],
resizable: true,
initComponent: function() {
var me = this,
upper_tag = {
xtype: 'toolbar',
height: 60,
items: [
{ xtype: 'label', ... }
'->',
{ xtype: 'label', ... }
]
},
lower_tag = {
xtype: 'toolbar',
height: 60,
items: [
{ xtype: 'label', ... }
{ xtype: 'button', ... }
'->',
{ xtype: 'button', ... }
{ xtype: 'button', ... }
]
};
Ext.applyIf(me, {
items: [
upper_tag,
{
xtype: 'gridpanel',
itemId: 'GRD_PW',
layout: 'fit',
height: 750,
store: 'PW_Store',
columns: { ... }
viewConfig: { ... }
},
lower_tag
]
});
me.callParent(arguments);
}
To be clear, this is the better explanation of my need:
1 row
2 row
3 row
4 row
-------------------------------------
| title bar |
|-----------------------------------|
| 5 row ^|
| 6 row ||
| 7 row pure grid, only rows || <-- this is browser screen
| 8 row ||
| 9 row ||
| 10 row v|
|-----------------------------------|
| bottom bar |
-------------------------------------
11 row
12 row
13 row
...
So that's no way to restrict number of rows on the screen and set pagination. It should use full hight of the browser screen. Sometimes 5 sometimee 20 rows.
Is it possible to create a grid with several columns under one header?
+-----------------------+-----------------------+
| Column 1 | Column 2,3,4 |
+-----------------------+-----------------------+
| | | | |
+-----------------------+-----------------------+
| | | | |
+-----------------------+-----------------------+
| | | | |
+-----------------------------------------------+
tried column header grouping but there's no way to hide the sub columns. it'll look something like
+-----------------------+-----------------------+
| Column 1 | Column 2,3,4 |
+ +-----------------------+
| | | | |
+-----------------------+-----------------------+
| | | | |
+-----------------------+-----------------------+
| | | | |
+-----------------------------------------------+
This one requires an override. Here's what your column config should look like:
columns: [
{
text: "Column 1",
// width, other settings
},
{
text: "Columns 2, 3, 4",
// width is computed as sum of child columns
columns: [
{
text: "",
columnName: "Column 2", // custom config
width: // needed
},
{
text: "",
columnName: "Column 3",
width: // needed
},
{
text: "",
columnName: "Column 4",
width: // needed
}
]
}
]
Note the columnName configs that aren't part of the API. That's something I made up for this.
Setting text: "" hides the header for that column. Setting it for all three sub-columns hides the whole row, but leaves you with a thin, 2px tall line where the header would be. Not sure how to remove it. Might be able to CSS it away.
This will give you your desired layout. You can hide the sub-columns via the main column's menu. However, the menu won't look right because there's no text. That's where the columnName comes in.
Find the source for Ext.grid.header.Container#getColumnMenu. You need to create an override for just this function. Here's how it goes:
Ext.override(Ext.grid.header.Container, {
getColumnMenu: function(headerContainer) {
// stuff
for (; i < itemsLn; i++) {
item = items[i];
menuItem = Ext.create("Ext.menu.CheckItem", {
text: item.columnName || item.text // <--- IMPORTANT LINE
// rest of the function is the same
}
});
This will pick up your columnName config if it exists without affecting existing columns that don't use it. Now when you click on the header trigger for your multi-column, you'll get a nested option your sub-columns. If you want to get fancy, you should be able to flatten the hide options through some more overrides, but I'll leave that up to you.
Note: This was all tested on Ext JS 4.0.7. There were some big changes to the header container code in the 4.1 release candidates and I can't guarantee this will work the same way.
Just add style property on your sub-header columns config like this:
columns: [{
header: 'Header',
defaults: {
style: { display: 'none !important' } <--here is the magic
},
items: [{
header: '',
dataIndex: ''
},{
header: '',
dataIndex: ''
}]
}]