make columns editable by using if condition in w2ui grid - javascript

$('#grid').w2grid({
name: 'grid',
columns: [
{
field: 'code',
caption: 'Code',
size: '120px',
sortable: true,
resizable: true,
editable: {
type: 'text'
}
}
I want to make it edit with if condition like if other fields are empty I don't want to make it editable. How I do this?

You have at least two options:
Either set record.w2ui.editable = false for your specific record (this requires your data source to be dynamic and contain some sort of logic).
- or -
In w2ui 1.5, grid.columns[i].editable can also be a function instead of an object, so you can write your own check function that will determine if the cell will be editable.
Quote from the source files:
col.editable can be a function which will be called with the same args as col.render()
Since the last one isn't well documented, I suggest you take a look at the implementation of getCellEditable() in the w2grid.js sources to get an idea how the two options I mentioned will interact.

Related

ExtJS Grid not refreshing after store update

I have a grid and a store. The store gets populated with some data - country - while the rest is empty. Once I receive more inputs I fill up the store with the inputs.
Assume that I have only 1 country in the store after the initial load.
Store:
feedTheGrid = new Ext.data.JsonStore({
autoDestroy : true,
autoSave : false,
autoLoad : true,
idProperty: 'country',
root: 'root',
totalProperty : 'totalcount',
fields : ['country', 'towns'],
proxy : new Ext.data.HttpProxy(new Ext.data.Connection({
url : "country/searchCountries.action",
method : 'POST',
timeout : 300000
}))
});
So the user inputs towns. I save a town in the array towns using push():
listeners: {
'change': function() {
if (feedTheGrid.getAt(0).towns === undefined) {
feedTheGrid.getAt(0).towns = [];
}
feedTheGrid.getAt(0).towns.push(this.getValue());
gridMonster.getView().refresh();
}
}
I want the grid to update every time a new town is put in.
This is part of the column model I use for gridMonster:
{ header: "Town 1", width: 150, dataIndex: 'towns',
renderer: function(val) {
if (val[0] != undefined) {
return val[0];
}
}, sortable: true},
{ header: "Town 2", width: 150, dataIndex: 'towns',
renderer: function(val) {
if (val[1] != undefined) {
return val[1];
}
}, sortable: true},
{ header: "Town 3", width: 150, dataIndex: 'towns',
renderer: function(val) {
if (val[2] != undefined) {
return val[2];
}
}, sortable: true}
The issue is that after a town is put in the grid never refreshes.
Some things I noticed so far:
The store gets updated with the new value when I check through Firebug. Also it seems the val that is given in renderer is always empty String, even after I push the new value into the array and refresh the grid view.
I am using ExtJS 3.3.1
I know its old so I am open to solutions that would work for 4.0+ and I can try to apply it to 3.3.1.
EDIT: Found the issue
Very subtle problem, spent hours trying to find what is the problem only to find out I was looking in the wrong place. The issue was in this line:
feedTheGrid.getAt(0).towns.push(this.getValue());
This line actually creates a new field towns as part of the record that you get using getAt(0). Using firebug to see if getAt(0).towns[0] is populated actually returns the value you pushed which is misleading.
ExtJS is not aware of this new field and it shouldn't be.
This line should be:
feedTheGrid.getAt(0).data.towns.push(this.getValue());
The trick is to point at the right place: .data. Javascript/ExtJS allows you to add new field without any warning because technically you are not doing anything wrong. Logically it creates a new field that does nothing.
#Lorenz Meyer I am able to display elements of the array using renderer while pointing at towns array in the column model.
There is a major misunderstanding about what a store and a grid are in ExtJs.
Both are just a representation of tabular data. A store is the representation in memory of a table, in order to get fast access to records filtering and more features. A grid is the visual representation of a table in the browser window.
Such a table could look like :
Id | Country | City
-------------------
1 | US | NYC
2 | France | Macon
3 | US | Macon
First of all on one table row, you can only have one city. In tables, you cannot have an array in a single field. If you have more than one city, this is what rows are for.
Then, your idProperty cannot be the country. If it were, this would mean that countries are unique. Obviously, they aren't. There can be more than one city in a country. (cities cannot be the idProperty neither, because there exists more than one city with the same).
Now you certainly begin to understand, that feedTheGrid.getAt(0).towns.push(this.getValue()); makes no sense whatever. The towns column cannot be an array. You insert a new row with feedTheGrid.add({country: 'US', towns: 'LA'}).
At best the towns column can be a comma separated value, in which case, you update the store with
var record = feedTheGrid.getAt(0),
currentTowns = record.get('towns');
record.set('towns', currentTowns + ', ' + value)
The method set of the record does all the magic: It passes the update event to the grid in order to rerender it. Your push in addition to be wrong will not trigger the events necessary to update the view.
About the grid: The columns of your grid should be:
{ header: "Id", width: 150, dataIndex: 'id', sortable: true},
{ header: "Country", width: 150, dataIndex: 'country', sortable: true},
{ header: "Town(s)", width: 150, dataIndex: 'towns', sortable: true}
Notes:
That listeners: looks really strange to me, but maybe it's just because the bigger picture is missing.
feedTheGrid is a strange name for a store. The store does not feed the data. It is tha data.
A renderer alway must return a value, else the cell will remain blank. Therefore your renderers cannot work.
In your renderers the val can not be an array. It's a simple variable. That's why your grid is not refreshing.
Very subtle problem, spent hours trying to find what is the problem only to find out I was looking in the wrong place. The issue was in this line:
feedTheGrid.getAt(0).towns.push(this.getValue());
This line actually creates a new field towns as part of the record that you get using getAt(0). Using firebug to see if getAt(0).towns[0] is populated actually returns the value you pushed which is misleading.
ExtJS is not aware of this new field and it shouldn't be.
This line should be:
feedTheGrid.getAt(0).data.towns.push(this.getValue());
The trick is to point at the right place: .data. Javascript/ExtJS allows you to add new field without any warning because technically you are not doing anything wrong. Logically it creates a new field that does nothing.
#Lorenz Meyer I am able to display elements of the array using renderer while pointing at towns array in the column model.

Extjs 4 grouped columns header dynamic text modification

I have the following grouped headers grid :
var lestore = Ext.create('Ext.data.Store', {
proxy: {
type: 'memory'
},
autoDestroy: true,
data:objstore
});
thegrid = Ext.create('Ext.grid.Panel', {
store: lestore,
columnLines: true,
columns: [{text:'date'},{text:'TV',columns:{text:'400',columns:[{text:'tt1'},{text:'tt2'}]}] ,
title:'my title' ,
selModel: {
selType: 'cellmodel'
},
renderTo: 'gridmpoff',
plugins: [Ext.create('Ext.grid.plugin.CellEditing', {clicksToEdit: 1}
)
],
listeners: {'edit': function(editor,e) {updtitle(editor,e);}
},
viewConfig: {
stripeRows: true
},
});
I need to change the columns texts (tt1,tt2 etc) after the grid creation, without changing the header grouping.
I Tried modifying the columns property, but that doesn't help, only thing that worked so far is a reconfigure which messes with the editor.
Please advice
ExtJS provides setText method fo changing the header text.
Refer http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.grid.column.Column
After so many searches i came up to the idea that ExtJS 4.1 "reconfigure" is buggy and has never been fixed, as it messes with the plugins (the editor in particular), and every fix i found so far targets only a particular use case, mine was just updating the grouped headers labels without touching anything else.
The solution i used is to simply update the dom (while at same time update the columns headers structure for the extjs so that if at some point their bugs are fixed it is simple to switch to reconfigure, settext or whatever), via : thegrid.container.dom.childNodes ....
I hope this helps gettings someone else from this struggle.
This is related : Using Ext.grid.Panel.reconfigure() breaks the grids RowEditing plugin
Try below code:
grid.columns[0].ownerCt.setText('Total Number');
I know this is an old thread but you can use the code Michael posted :
grid.columns[0].ownerCt.setText('Total Number');
and then use the column name in your groupHeaderTpl and have something like this :
{columnName}: {name}
This way it will dynamically change it to the values you want.

pagination not working for KO Grid

I am working with KO-grid and it seems to load all the data fine. Now, I am working on the pagination part and it does not seem to work properly. Yes, I do the pagination control on the bottom but when it comes to be able to decide the page size, it does not seem to work. The page size is driven by two options according to confguration details given on https://github.com/ericmbarnard/KoGrid/wiki/Configuration
1.pageSizes:[5,10, 25] -- seems to show options but when I change my selection from 5 to 10 then it does nto seem to work upon the choices.
2.pagesize ://somenumber -- breaks the code.
I have working model of it on jsfiddle: http://jsfiddle.net/sf4p3/46/
Any suggestions?
Well, it appears that the pagination in KoGrid doesn't work the magic that you were hoping for.
Here's a link to the example from the KoGrid wiki on GitHub:
http://ericmbarnard.github.com/KoGrid/examples/Complex-Server-Side-Paging.html
In viewing source for the HTML page, one will likely see the beginning of the view model declaration without having to scroll (depending on screen resolution, of course). Regardless, this starts around line 30.
Notice that there is an observable named pageSize in the view model, and it is set to 50.
Scrolling down a bit, one should see functions named filter, sort, and getPagedDataAsync for filtering the data, sorting the data, and creating the data set for the current page.
Here's the code for the getPagedDataAsync function:
this.getPagedDataAsync = function (pageSize, page, filterInfo, sortInfo) {
setTimeout(function () {
var data = window.getExampleData();
var filteredData = filter(data(), filterInfo);
var sortedData = sort(filteredData, sortInfo);
var pagedData = sortedData.slice((page - 1) * pageSize, page * pageSize);
self.myObsArray(pagedData);
}, 0);
};
Without seeing the details of the rest of the view model, one should be able to tell from reading the above code that this function starts by retrieving all data to be displayed for this example page, then filters the data and sorts the data.
After that, the data array is sliced to extract the data to be viewed for the current page, and that slice is passed to the myObsArray observable array that is used to display the data in the grid.
Here's the declaration of the grid in this example:
<div id="sandBox" class="example" style="height: 600px; max-width: 700px;"
data-bind="koGrid: {
data: myObsArray,
columnDefs: [
{ field: 'Sku', width: 140 },
{ field: 'Vendor', width: 100 },
{ field: 'SeasonCode', displayName: 'Season Code', width: 150 },
{ field: 'Mfg_Id', displayName: 'Mfg ID', width: 180 },
{ field: 'UPC', width: 170 }
],
autogenerateColumns: false,
isMultiSelect: false,
enablePaging: true,
useExternalFiltering: true,
useExternalSorting: true,
filterInfo: filterInfo,
sortInfo: sortInfo,
pageSize: pageSize,
pageSizes: [25, 50, 75],
currentPage: currentPage,
totalServerItems: totalServerItems,
selectedItem: selectedItem }">
</div>
Hopefully, this helps, and you'll be able to fix your paging issues.
Regardless, please let me know if you have any questions.
UPDATE
#Californicated I'm on vacation, but I had some downtime to take a peek at your latest fiddle.
I forked what you had in your latest fiddle and made the following changes to get the paging to work:
In the declaration of observables, I changed the value of pageSize to 2 and the value of totalServerItems to 7.
In the JS, I changed the declaration of the data var in the
getPagedDataAsync function so it's retrieving the
Prizefillfilmentstatuses observable array.
On the last line of the JS code, I changed the first parameter from 50 to 2.
In the jsFiddle toolbar, I changed the first dropdown from "onLoad" to "no wrap (body)"
In the declaration of the koGrid in the HTML, I added the following options/parameters:
pageSize: pageSize,
currentPage: currentPage,
totalServerItems: totalServerItems,
selectedItem: selectedItem
The page setup was working with the JS changes, alone, but the paging tool (previous, next, etc.) was not active until I added the totalServerItems option in the koGrid declaration.
Again, let me know if you have any questions.

Dojo DataGrid Virtual Scrolling How-To?

I've been digging around for this one quite a bit. I'm using dojox.grid.datagrid and I have an ajax call that brings back 200-300 rows.
The grid renders and scrolls just fine in Chrome but scrolling is excruciatingly slow in IE 7 and 8. I'd like to use virtual scrolling to try and remedy the issue but can't find any sample code.
Here's what my code looks like at present.
function setupAvailableScenes(location) {
var avaiableScenesGridPane = dijit.byId("AvaiableScenesGridPane");
var availableScenesGrid = dijit.byId("AvailableScenesGrid");
if (_isFirstLoad) {
availableScenesGrid = new dojox.grid.DataGrid({
id: 'AvailableScenesGrid',
store: availableScenesStore,
query: { Id: "*" },
sortInfo: "1",
rowsPerPage: 20,
autoHeight:20,
style: "width:315px",
structure: [
{ name: "Available Scenes", field: "Name", width: "85%" },
{ name: " ",
field: "_item",
rowsPerPage: "25",
type: dojox.grid.cells._Widget,
editable: false,
width: "15%",
formatter: function (scene) {
return new dijit.form.Button(
{
label: "+",
onClick: function () {
AddSceneToSelectedScenes(scene);
}
})
}
}
]
});
avaiableScenesGridPane.set('content', availableScenesGrid);
}
var availableScenesStore = new dojo.data.ItemFileWriteStore({
url: _applicationPath + "/Location/" + location.Id + "/Scene.json",
preventUrlCache: true
});
availableScenesGrid.setStore(availableScenesStore);
}
Often one of the biggest things you can do to improve DataGrid performance is to throw away the ItemFileReadStore/WriteStore and use an optimized data store (personally I like QueryReadStore). It would mean needing a server-side servlet of some kind (PHP/JSP/etc) to handle the virtual scrolling/pagination, but I've seen major perf boosts over just using a store backed by a JSON file.
Some other things to consider, which may or may not help:
give your anonymous formatter function a name and try scrolling the table with the Chrome or Firebug profiles turned on to see if it's hogging a lot of cycles (or, like Vijay Agrawal said, you could try replacing the dijit.form.Button with a vanilla html <button> tag)
you shouldn't actually need to specify the dojox.grid.cells._Widget type for that cell; having a custom formatter returning a valid Dijit should be sufficient to make the Grid do the right thing.
Since you specified rowsPerPage=25, it is already doing virtual scrolling (it pulls the new set of rows only when user scrolls down)
Since you mention scrolling is very slow, the performance issue seems to be around rendering the new rows - you may try a couple things to improve performance:
1) remove autoHeight attribute. Instead, specify a fixed height in the style attribute
2) in the formatter function, instead of returning a dijit, try returning a simple html button/anchor styled as button
so remove the type:dojox.grid.cells._Widget attribute and in the format function return the html you want to use

How to show all rows in the jqGrid?

jqGrid exposes a property rowNum where you can set the number of rows to display for each page. How do you set the grid to just display ALL rows?
Right now I'm just setting the rowNum to something really high like <%= int.MaxValue %> but I'm wondering if there is a better way.
In the latest version of jqGrid, you can set rowNum to -1 to instruct the grid to always display all rows:
rowNum: -1
See the latest jqGrid documentation here.
Specifically:
Sets how many records we want to view in the grid. This parameter is passed to the url for use by the server routine retrieving the data. Note that if you set this parameter to 10 (i.e. retrieve 10 records) and your server return 15 then only 10 records will be loaded. Set this parameter to -1 (unlimited) to disable this checking.
Update
Unfortunately this behavior was broken in jqGrid 3.6.3. According to this post from Tony:
Yes, this is true. The reason is the new introduced scroll:1. In the future we will correct this behavior.
So the jqGrid developers are aware of this problem and apparently are planning to fix it in a future release. Unfortunately this post was from over a year ago...
At this time, all I can recommend is that you set rowNum to a very large number to simulate the behavior of -1.
You can also try whatispunk's solution below of using rowNum: ''. However, I tried this on a grid containing local data (loadonce: true). When attemping to sort the rows all of the grid's local data would disappear. So this solution does not seem to work for grids with local data, unless this defect has been fixed in a later version of jqGrid (I tested it on jqGrid 3.8.2). If you have feedback, please post a comment below!
Update - April 16, 2014
According to the jqGrid team this is now fixed:
I have added support to set different display values on pager select box including -1 for all.
I have not had a chance to test to confirm the fix, though. Presumably this change will be in the next release after jqGrid 4.6.0.
jqgrid (3.5 anyway) doesn't seem to have an elegant built in way to do this. The best I have found so far is to add something like the following to your grid options:
rowList:[10,20,30,100000000],
loadComplete: function() {
$("option[value=100000000]").text('All');
},
Where the 100000000 is some arbitrarily higher number than the maximum # of rows you will ever return, and the option[value=] line is so your user interface looks a little nicer. Jenky, but works for me.
if you dont wish to use paging at all then change you server side code to simply return all the rows. dont use the rows parameter at all.
if you want to have the rowlist but also have an option to show all then do something like this in the grid properties
jQuery("#statement_mods").jqGrid({
rowList:['ALL',30,50,100,200]
});
and then in the serverside code make sure that you ignore the rows parameter if GET['rows']='ALL'
This works:
// Step1 - defines the rows
jqGridOptions.rowList =[10, 50, 100, 500, 'All'];
...
...
// Step2 - Change the 'All' to a meaningful value
loadComplete: function (data) {
$(".ui-pg-selbox option[value='All']").val(1000);
}
setting rowNum:-1 did the trick for me
If you have set the pagination on the navbar, you can also access to the total number of rows written on the right-bottom of the grid and then append to the generated RowList option.
Do something like :
// Get the total number of rows and delete space between numbers (Split the content of the div depending of the language (for me french)
var val=jQuery("#pager_right div").text().split('sur')[jQuery("#pager_right div").text().split('sur').length-1].split(' ').join('');
// And do the appending if the option isn't already added
if(!$(".ui-pg-selbox option[value='"+val+"']").length > 0)
jQuery(".ui-pg-selbox").append($('<option></option>').val(val).html(val));
Setting rowNum: '' you get all rows.
Jqgrid.PagerSettings.PageSize = Max Row you want to display;
Jqgrid.ToolBarSettings.ToolBarPosition = ToolBarPosition.Hidden;
I've got this working:
$('#bla').jqGrid({
...
'rowNum' : 0,
'loadOnce' : true,
'loadComplete': function(data) {
$(this).jqGrid('setGridParam', 'rowNum', data.total);
},
...
});
This works with and without the loadOnce option set to true. Note that you have to set the rowNum option to 0 first, if you leave out this option it'll still default to the 20 records to show.
Also, I'm assuming you're returning the total rows from the server in the documented JSON reader format.
resolved it with simple change:
rowNum: inputDataArray.length
where inputDataArray is the array that I am providing to the Grid.
By default the JQ grid show 20 rows Max ,if you are using not using pagination:
// To over come with this problem ,you can just write the bold mark
(rowNum:10000,):
$("#MasterDataDefinationGrid").jqGrid({
url: 'FetchData.aspx/GetDataFromDB',
datatype: 'json',
mtype: 'POST',
height: 300,
autowidth: true,
serializeGridData: function (postData) {
return JSON.stringify(postData);
},
ajaxGridOptions: { contentType: "application/json" },
loadonce: true,
colNames: [Your column names],
colModel: [Your model],
formatter: 'actions',
pager: '#MasterDataDefinationPager', pgbuttons: false,pgtext:false,
multiselect: false,
ignoreCase: true,
**rowNum: 10000,**
loadtext: 'Loading ...',
gridview: true,
hidegrid: false,
jsonReader: {
page: function (obj) { return 1; },
total: function (obj) { return 1; },
records: function (obj) { return obj.d.length; },
root: function (obj) { return obj.d; },
repeatitems: false,
id: "0"
},
caption: 'Data'
});
You can also go into jquery.jqGrid.js and change "rowNum:20" to "rowNum:Some-Really-Large-Number". When you define your jqGrid, don't specify rowNum. Then return your entire dataset back to jqGrid.
Even if it still appears in the doc that you cannot set rowNum to -1 as of jqGrid 4.5.4 it works again (maybe in earlier version too).
loadComplete: function (data) {
//set our "ALL" select option to the actual number of found records
$(".ui-pg-selbox option[value='ALL']").val(data.records);
}
This changes the "ALL" option to the actual number of records in the dataset.
Setting rowNum:-1 works for me like, after that it was showing all records but it still has row number option in grid footer like this:
To remove this I just added a css option display none by getting the sector in jquery. Like this
$('#id_tableCell').css('display', 'none');
Note: This css setting should be done when the grid load is completed.

Categories