dojox.grid.DataGrid - Maintaining row selection when sorting and paging - dojo

I am using a dojox.grid.DataGrid to display data and allow the user to select one or more rows to highlight items to do other actions to.
My problem is that the grid uses indexes to remember the selected rows. If I have turned clientSort on, sorting the rows makes the rows change order but the selection changes to the rows that now occupy the selection indexes before sorting.
To combat this I get the items for the selected rows on each selection change and then when onSort event happens I use getItemIndex(item) on each of the items in my selected items collection to get the new row indexes and I re-select using those indexes.
Now, my problem is that the DataGrid loads data a certain number of rows at a time (it uses the term page to define a set number of rows) to improve performance. When a sort occurs it reloads the data in the new sort order but only up to the rowsPerPage value (defaults at 40). When I try and use getItemIndex for an item whose new row has not been loaded into the grid it returns and index of -1. The getItemIndex() function only returns the index once the user scrolls down and the row is loaded.
I cannot find an event that fires when the page loading occurs to try and restore the selection. I have looked through the 1.3.2 source code and can not find anything. I have tried connecting to a number of private functions but none work.
Has anyone come across this and found a fix?
Thanks in advance.

I found the answer. The dojox.grid.DataGrid has a private event (_onFetchComplete) which fires each time the next page is requesting. I use setTimeout to run my restore function after a duration of 300.
Job done!

Related

vb.net dataview grid won't add record and doesn't update after data is modified independently

I have a dataview grid bound to a datasource at run time. The datasource is filled from an access database via a DataAdapter. The data fills and displays correctly, and updates to existing rows seem to work OK but I have two problems:
When I type something in a new row and then press return or switch to a different row, I want the DataAdapter to add that row then and there to the database so I can retrieve the Autonumber index of the new record from Access and use that to add an associated record in a different table (Entries, a many to many linking table). This isn't happening. In the RowLeave event I have adapter.Update(dsSentences) and then I check for the new row, but the RowCount doesn't reflect its presence even though the newly added data is visible in the grid, and the adapter.Update doesn't seem to have triggered the Insert query that I specified in the DataAdapter. So nothing is added.
(edit: OK, so the new row has not yet been added when this event is fired. Which event should I then use to commit the data and retrieve the Autonumber primary key for my new record? I've tried UserAddedRow but that one fires before you've entered any data into the new row.)
THe second problem is that I need to update the data independently and then have the grid reflect those changes. How do I do that? Is there some call that will force the grid to get the updated data from the DataAdapter via the Dataset? Any help would be much appreciated. I'm almost ready to dtop the whole idea of binding data and do it all through code, Data binfing is supposed to save time but I'm finding it labyrinthine and unpredictable.
FWIW here's the query I'm using to fill the grid:
PARAMETERS nIdCollection Long;
SELECT tblSentences.IdSentence, tblSentences.SentenceText, tblSentences.SentenceParsed, Not IsNull([tblSentences]![SentenceParsed]) AS HasParsed, Entries.IdEntry
FROM tblSentences INNER JOIN Entries ON tblSentences.IdSentence = Entries.IdSentence
WHERE (((Entries.IdCollection)=[nIdCollection]))
ORDER BY Entries.SortValue;
As you can see, it requires a record in Entries. After I've entered a new record in tblSentences, before there are any entries the IdEntry will be null assuming it shows up at all. That's why I need to intercept directly after the Insert, add the record to Entries and requery to keep everything in order. You could do it all in an SQL stored procedure but I have to use Access.
Edit: After a lot of googling I've come to the conclusion that what I'm trying to do = add a record to a table through an additional INSERT query apart from the one handled by the DataAdapter, every time a new row is added - simply can't be done if you are using data binding. I am going to have to delete all my code and start from scratch populating the grid through code (unbound). I think it's the only way to do what I want. I will leave this here as a warning to anyone else not to make my mistake of trying to use Data binding when your data is coming from more than one table. Bad mistake.

Is there any way to select all or some row of records and then hit a command button that will effect the row of records the same way?

I have a continuous form that contains a varying number of records. Typically it doesn't exceed 100 but it can. Below is the form showing a few row of records. I was wondering if its possible to select a few or all of the records and after selecting them, I click a command button that will run its code accordingly with each record selected.
Continous Form Displaying a few rows of records
The most easy way is to add a check box column to the table. However, in a multi-user environment, this can fall apart. But, the idea is you check off the rows, and then hit a button. That button can process all records with "ToProcess = True" and then when done, it un-sets those records. Since the process would be limited to the one sub form dataset, then this can even work quite well in a multi-user environment, since those sub-forms records are un-likely to be open/viewed at the same time by others.
So, just add a true/false column to the sub form table, and display. The user can check box which rows to operation against. You thus limit the query to the sub form records +

Data Adapter does not update all rows updated

So long story short I have a dgv that gets data from a mysql database and I can make changes to the data in the grid and save back to the table, no problem except this: Changes made by the user on the dgv are not done directly (or manually) on the dgv, rather the user clicks plus or minus buttons and I pragmatically increase or decrease the number in a certain field called Quantity which is actually the only field that can be updated.
Now when I update my adapte command (...da.Update(ds, "salesDet")), the row I changed last does not get updated unless I manually leave that row to another row before pressing the update button. So for instance if I have 3 rows in the dgv and I select row 2 which has a quantity of 1, then I press the plus button, the quantity changes to 2. Then if I immediately press my update button while still on row 2, it will not get updated to my database. It will only work if prior to pressing the update button I leave row 2 to say row 1 or 3. Kind of like because I'm changing the numbers programmatically and not manually, I need to leave the edited row for an "after-update" commitment of the new values to fire? Don't know if I'm making sense but I'm really lost
I have tried dgv.EndEdit(), dgv.RefreshEdit(), dgv.Refresh() before updating but none of that works.
Thanks for your help
Sounds like the current row hasn't been validated yet, so your change has not taken effect. A clumsy hacky way of getting round this might be to set dgv.CurrentRow to nothing at the start of your Update method to force validation.

Create DataTable child row without showing it?

I am using datatable (v1.10.2 with jquery 1.9.2) because I like the out-of-the-box features (searching/sorting etc). However, now I want the ability to:
1) use animations (sliding) when showing/hiding a row
2) have the hidden row available in the DOM to change (ie, it would exist but have a display:none).
My current code to create the table looks like the following (where formatChild() returns html for a table):
if (row.child.isShown()){
row.child.hide();
tr.removeClass('shown');
} else {
row = row.child(formatChild());
row.show();
tr.addClass('shown');
}
I am using several services to change data in the child row's table via ajax and want to be able to change that data even when the row is hidden. I know I can create a map in memory and use the information in the stored map when I show the child row, but to me it is much cleaner to change the hidden row immediately.
I was hoping I could do a row()child(), modify the row, then call row()child().show() but the row isn't created in the DOM after the row.child().
Regarding the animation, I found an answer here but it involves changing the datatables code :(
I considered just using jquery to add a row to the datatable and hide it, but I couldn't find a good way to "attach" it to the primary row for sorting.
The plan I am currently leaning towards is to add a div to my primary table row that I will show/hide/update rather than using child rows at all.
What is the best practice for managing these hidden areas in a datatable (and showing them with animation)? ty
In case anyone else has the same question, I ended up using a DIV in the row rather than using DataTables' child row. When I add a new row to the datatable, the div is hidden then I hide and show (slideup/slidedown) on a click event. This gives me the nice animations, keeps the sorting simple, and let's me change information in the hidden row. Interestingly, the DIV contains a table and the text that is in that table when I create the new row is searchable; however, the text in the table that my ajax call adds/modifies is not searchable. I'm looking into how I want that to work (and may keep the div out of the search altogether if possible).

Looping through the rows of a gridview with more than one page

Is it possible to loop through a gridview with more than one page, the gridview I'm looking at has a pageSize of 20, there are say 26 records (over two pages) and I want to be able to loop though all the records.
For Each row As GridViewRow In GridView.Rows
.
.
.
Next row
The count of the above is only 20 as the pageSize is set to 20, I can see that the pagecount is 2 but how do you loop through the next page in a gridview? Or would I have to just iterate through the orginal datasource?
You have two options: 1) use the original data source that has all rows for your grid (a very unoptimized solution!) or 2) have the stored procedure that gets the result set from the database be optimized for paging. If you use option one, then you'll have to rebind your grid with the current page (a common solution would be to use linq and query your data source). If you use option two, you'll have access to the results set from the database. Either way, you'll eventually need to use the ItemDataBound event and and then you can iterate through each item in your grid.
As your questions suggests, you will have to iterate through the original datasource as the GridView.Rows will correspond to the current rows, in this case limited to 20, showing in the GridView.