I am having trouble with what i think comes basically for free with knockout.
I have a foreach loop, done in knock out, which creates table rows.
Outside of this loop i have the table header, and i want to make the column headers trigger a client side sort.
I have seen the observable array function sort() but i cant seem to get it firing. Following up, is it hard to do ascending / descending sorts?
I was able to implement it with this post. The fiddle had just what I needed, it is a good example of the bindings needed.
Knockoutjs - Sorting a large observablearray
I extended it by including a sort direction variable in my model that i toggle when sorting.
Related
I'm currently trying to optimize our application that uses KnockoutJS for view binding and rendering. We discovered a huge bottleneck with a growing dataset size in the following scenario:
The dataset (observableArray) is displayed in an html table.
50 rows are displayed at the same time.
Each field in the row-model is an observable as the data is inline editable (input, select, ...)
Per row exist 8 selects that are initialized with the Select2 Widget (http://ivaynberg.github.io/select2) and a jQuery datepicker.
I already implemented these KnockoutJS performance tips, which I found on different sites:
The observable array is published with the full dataset (call of the observable) and not with multiple push() calls.
I'm using the template-binding in conjunction with the foreach option, as advised on multiple sites, and not both split up as separate binds.
Datepicker and Select2 are implemented as custom knockout bindingHandlers.
ko.applyBindings is invoked directly with the table-element as second parameter, so that not the whole DOM is bound by knockout.
But the main bottleneck in my opinion seems to be the initialization of the additional widgets. I measured the creation of a Select2 widget, which takes ~15ms. Of course that cummulates quickly with 50 rows and 8 columns. So, a single call on the observable array to load the full dataset takes up to 10 seconds! During this time, the Browser is under heavy load and becomes unresponsive, which is a no-go usability wise.
This leads up to my questions:
Has someone experienced a similar scenario and how was it handled?
Is there a better way to initialize third-party widgets with knockout?
Are there alternative ways (using KnockoutJS) to solve this problem?
Has someone experienced a similar scenario and how was it handled?
I have an interactive table on my page, which I display using the HandsOnTable plugin. The table has about 15 columns and I need to display up to 250 rows.
I bind it to an observableArray, and, at first, the observableArray contained only observables.
I was not satisfied with the speed of it in old versions of IE I am required to maintain (IE8/9, worked ok with IE11/recent Chrome), and made the decision to remove all observables inside the observableArray.
It is not really in the spirit of knockout and I am not so proud of this solution, but it does work much faster.
Handsontable lets you handle some events, in which I update the observableArray just like a regular array and then run the valueHasMutated function to notify the changes of the array.
Likewise, my custom binding handler watches changes on the whole observableArray and updates the table as needed.
I think the other difference with your solution is that Handsontable turns into edit mode only when needed, thus the plugins (like datepicker) load only then.
Is there a better way to initialize third-party widgets with knockout?
Maybe you can enter edit mode only when the line/cell is selected. You could then use an if binding to init and display your widgets only then.
I am looking for a way to sort columns programmatically.
Please bare in mind, I do not mean to sort the grid as you normally would with sortGrid() or whatnot. I mean to arrange the row order from left to right programmatically, after the grid has been rendered.
So, I am aware that with:
$("#myGrid").jqGrid({sortable: true});
I am able to sort the columns by dragging and dropping them in order. The idea is to allow users to sort their column, and to have a callback save the order in the database, so each user can arrange their own columns however they want.
I am doing something similar with showing and hiding columns, but have been unable to reorder the columns programmatically without actually dragging and dropping them.
Any help would be highly appreciated.
You can use remapColumns method to reorder the column programmatically without usage drag & drop.
In the answer you will find the code which shows how to save user specific choice of the column order in localStorage. I personally prefer the way as the saving of the same information on the server side in the database. Nevertheless you can implement saving of the same information in the database instead of localStorage. To do this you need just change the implementation of saveObjectInLocalStorage and getObjectFromLocalStorage functions and include the ajax call instead of usage window.localStorage.
I am trying to implement one sorting functionality in my code in php. The functionality will be like, when we click on the header of a column then that particular column's record will be sorted by ascending order and again click on the same column means the column's record will be sorted by descending order.
Please help me how to proceed with some example.
JQuery has many plugins that do this sort of thing. I have used Tablesorter with great results in my own projects.
I too recommend jQuery Tablesorter, it's an excellent little plugin.
You really want to avoid doing the sorting backend, as this will put strain on your server, but if you wanted to it would be as simple as appending an ORDER BY instruction to your query depending on what column the user clicked. Again, I do not recomment this method, I think you should do it in the frontend with a plugin such as Tablesorter.
I have a a jqGrid that shows as list of rows ... several thousand.
When the grid loads, it will pull down all the data with their previous selections already checked.
My questions is, how do I set the sort order to always show the selected items at the top?
Thanks in advance!!
You question seems be very close to another one which I answered recently (see here). If you has several thousand or event thousand rows you should use paging of date to improve performance of the grid. The solution which I suggested is very simple and it supports saving of selected state over the paging.
One more remark. If you have jqGrid with local data you can implement custom sorting of data. To do this you just need define sorttype as function. If the data need be sorted by a column jqGrid will compare items. The function sorttype should just return any string or number which should be used instead of the cell value. In the case you can easy place for example selected items at the top of grid. You can find examples of custom formatting here, here and here.
Even in this ajax example
which I really like the look of, when ever the top level grid is sorted the "state" of what you were doing "disappears"
For example,
Open the first person's row (Nancy Davolio) so you can see the Sales grid
Sort by Order Total in the Sales grid
Sort by Birth Date in the top level grid
Nancy Davoilo should now be second. Open her row.
The sales grid is no longer sorted by Order Total
This may seem trivial, or that i'm being picky; However:
If I have some text box(or some other type of method of accepting user input) on the sales grid, I would assume that this would get destroyed when sorting the top level grid.
I would also think that even if I had this input on the top level grid, that sorting the top level grid (or filtering if there were filters) would destroy this input.
It seems that even paging destroys this.
The desired behavior would be for sorting and paging not just "appear" to be done client side because it's using an ajax request, but to ACTUALLY be done client side. Meaning that the actual rows of the grid are literally sorted(filtered, paged, etc.) client side so that any client side changes such as adding text to a text box, adding a css class to an object, [or in a more complex example adding a reference to a javascript object to an object via Jquery: $("#div1").data("object",someObject) would persist after sorting, paging and filtering.
Is there a way to make this happen?
Am I making what i'm looking to do clear? If not i'm happy to clarify.
Additional Notes: I would think the client side performance hit would be minimal to do something like this as long as there were not a very large number of rows. In fact there would be a lot less work on the server in recreating all of the records, repeated calls to the server/database and as in my example at the top the subPages would only need to be created once rather than twice.
Take a look at the HierarchyLoadMode property of the MasterTableView. The demo you reference is using HierarchyLoadMode.ServerOnDemand which, according to Telerik's documentation, means that ViewState only maintains the state of the visible items. Therefore, when a details grid is collapsed you will lose its state (e.g. a sort order, page number, etc).
There are other modes. You can choose HierarchyLoadMode.ServerBind which maintains ViewState for all detail tables but requires a PostBack to expand a detail table. The HierarchyLoadMode.Client renders the MasterTableView and all DetailTables and items are expanded/collapsed on the client - no PostBack required. Either of those modes should also maintain the sort order and other state related to the detail tables.
I hope that helps answer your question.
I recently got a reply from the Telerik support that their AJAX grid supports client binding out-of-the-box with sorting, paging and filtering with flat structure only (as in this demo).
For your case you may have two options:
extend the example with grid settings persister - http://demos.telerik.com/aspnet-ajax/grid/examples/programming/savinggridsettingsonperuserbasis/defaultcs.aspx
implement custom solution to simulate hierarchy with client binding as presented in this blog post.