Pageable treeview using Kendo? - kendo-ui

Let's say I have hierarchical data that I display in a treeview. It's possible that a particular node might have 1000 children and I don't want to display them all, so I'm toying with the idea of paging the nodes in a tree. I would show 10 children and if there are more, the user needs to click on the next/previous buttons to see them. I've got sql paging working but I can't get the treeview to do what I want.
If I do this, my controller gets the proper node id and page id and it returns the correct page of results back. But then the treeview shows only the 1 page of children I just requested; the rest of the hierarchy (all the parents) is lost:
$("#btnNextPage")
.click(function () {
var selectedNode = treeview.select();
var selectedNodeID = treeview.dataItem(selectedNode).id;
ds.read({
LoopID: selectedNodeID,
page: ds.page() + 1
});
If I do this, I can keep the hierarchy and my controller gets called, but I can't figure out how to pass in the page that I'm requesting.
$("#btnNextPage")
.click(function () {
var selectedNode = treeview.select();
var testnode = treeview.dataItem(selectedNode);
testnode.loaded(false);
testnode.load();
});
I've been using ASP.NET webforms and this is my first foray into jquery and kendo. Any ideas?

When you change pages the Kendo DataSource replaces its records in memory with the new page retrieved from the server.
You would need to retain all the previously loaded pages in a separate observable array and bind your treeview to that instead.

With a pointer from the folks at Telerik, I got this working. The trick was to use the children property which is the datasource for the children of the selected node. So when the next page button is clicked I do this:
parentNodeDataItem.children.read({
LoopID: parentNodeID,
page: currentPage
});
This produced the behavior I wanted, which was for the children to be refreshed without losing the ancestor hierarchy.

Related

Get all business recommended fields in subgrid

How do I check if a particular field or column of a subgrid is business recommend or not? I want to do this using a web resource. Also due to some requirements, I will have to use the execution context of the form where the subgrid is present and not of the subgrid itself.
It is a little tricky because at the time that the form loads, the subgrid does not have data. So you have to use the Form's load event to attach a load event to the subgrid.
This is described in this MS Docs Page. You can do this like
function attachGridEvent(executionContext)
{
var formContext = executionContext.getFormContext();
var gridContext = formContext.getControl("gridCategories");
// We have the grid, now add a "load" event handler
gridContext.addOnLoad(MyGridLoadedEvent);
}
Now you've got a 'load' event for your grid so you can iterate through its rows and examine its data
I haven't been able to get this to work for subgrids that don't contain data
I get the first row in the sub grid. Once I have that we can loop through each of the row's attributes. Each attribute has the following methods:
getName Returns the logical name of the attribute of a selected grid
row.
getRequiredLevel Returns a string value indicating whether a
value for the attribute is required or recommended.
setRequiredLevel Sets whether data is required or recommended for the
attribute of a selected grid row before the record can be saved.
getValue Retrieves the data value for an attribute.
setValue Sets the
data value for an attribute.
MS Docs Page
I'm using some modern browser features (map, =>) but this code should work for you
function MyGridLoadedEvent(evt)
{
var gridContext = evt.getEventSource();
var rows = gridContext.getGrid().getRows();
if (rows.getLength() > 0)
{
let rowAttributes = rows.getByIndex(0).getAttribute();
let mappedResults = rowAttributes.map(x => x.getName() + " : " + x.getRequiredLevel());
alert(mappedResults);
}
}

Nativescript Get Current Page

How can I get the current screen I'm working on? For example, I have a slidedrawer containing buttons to navigate to another page. When I'm on a certain page(About Page) and when I tap the button to navigate to the About Page, I want to just close the slidedrawer if it is on the same page.
My idea is that to get the current page and just compare it but I dont know how.
Note: The slidedrawer content menu is a custom component.
There are several ways to solve this problem. The easiest is to install the nativescript-dom plugin and then you can do this really simply:
// This will return an array of elements that are SlideDrawer's.
var slideDrawers = getElementsByTagName('SlideDrawer');
or even better is if you have assigned your SlideDrawer an id, you can do
<!-- Declarative XML -->
<SlideDrawer id="myId">...</SlideDrawer>
// JS: Will return a single element that matching the id.
var mySlideDrawer = getElementById('myId');
However, if you just want to not use any helpers and you want to get direct access to the currentPage the method is to do:
var frame = require('ui/frame');
var myPage = frame.topmost().currentPage;
Please note; the currentPage will reflect the old page while navigation is taking effect until the navigatedTo event is fired, at that point the currentPage is actually updated to be the currentPage. However, if you are looking for the current page during any of the navigation events (NavigatingTo, NavigatedTo, Loaded, Unloaded) each of those events are transferred a parameter with the current page as part of the object.
exports.onNavigatedTo = function(args) {
var page = args.object;
// do what you want with the current page variable
}

Unable to deselect the selected node in KendoUI tree view

I have a tree-like structure using Kendo UI tree view. Each node is displayed as a hyperlink and on clicking each one, a new kendotabstrip will be opened. My problem is if I select one node, the results are displayed fine in a new tab but if I close the newly opened tab and then select the same node then no new tab is opened since the node has already been selected. If I have to choose the same node, then I have to access another node and then come back to node.
I tried to deselect the selected item once the new tab is opened using the following snippet:
var treeview=$(#grpTree).data("KendoTreeView");
var selNode=treeview.select();
selNode.find("span.k-state-selected").removeClass("k-state-selected")
but the node is not getting deselected. Is there any other way to do it or have I missed out anything?
I know this post is a bit dated, but as Telerik is continually upgrading its components, I thought I'd put this here so that people can be aware of this change moving forward.
You can deselect all selected nodes with the following syntax:
var treeView = $("#treeView").data("kendoTreeView");
treeView.select($());
Source: Kendo UI Treeview Documentation for Select
Yes this is by design. If you want to attach a click handler which will be triggered each time (no matter if the node is already selected). You can attach a delegate event like the following:
$('#treeviewName').on('click','.k-item',function(e){
var clickedNode = $(this);
var treeViewClientObject = $(e.delegateTarget).data().kendoTreeView;
})
My code:
var treeview=$(#grpTree).data("KendoTreeView");
treeview.select(null);
This calls the change function always, so this can be another solution:
$("#favorite_tree").kendoTreeView({
change: function () {
if (this.dataItem(this.select())) {
var treeView = $("#calendar_tree").data("kendoTreeView");
treeView.select($());
}
}
}).data('kendoTreeView');
$("#calendar_tree").kendoTreeView({
change: function () {
if (this.dataItem(this.select())) {
var treeView = $("#favorite_tree").data("kendoTreeView");
treeView.select($());
}
}
}).data('kendoTreeView');

Navigate to last page on mvc telerik grid

How can you navigate to the last page of a telerik grid using javascript. My scenario is that I want to go to the last page of the grid in which the new record was added. I know I can use the 'pageTo' method in the Telerik Client API but I am not able to figure out how to count the number of pages a grid has. I was looking up if somebody was doing the same thing that I want to do and stumbled across this piece of code
var lastPage = ticketsGrid.totalPages(ticketsGrid.total);
But the value of the variable lastPage is infinity which is not possible as I only have 1 page in that grid.
Any suggestions anyone?
You can use the OnDataBound event.
You need to use a boolean flag which checks if this is the first load.
var firstTimeLoad = true;
function onDataBound(e) {
if (firstTimeLoad) {
firstTimeLoad = false;
var grid = $('#Grid').data('tGrid');
grid.pageTo(grid.totalPages());
}
}

How to change WebGrid action for getting data (.NET MVC3)

I have a Partial View that renders WebGrid. My controller looks like
public ActionResult Index()
{
return View();
}
public ActionResult GetUserList(int? page, string sort, string sortdir)
{
var model = UserModel.getList(page,sort,sortdir);
return PartialView("_UserList",model);
}
Index.cshtml :
....
#Html.Action("GetUserList")
The problem is that every time I click on grid navigation or sort links it calls Index method. How can I make Webgrid to execute a different action (GetUserList in this case)? I'm sure I can prepend GetUserList to all links in grid using jquery, but I believe it should be a better way.
It's also possible that what I'm doing is completely wrong, so thanks for your suggestions.
After lot of monkeying around and digging (and even fiddling with Reflector with WebGrid's source code), I came to the conclusion that with WebGrid, you cannot control/change the Header link action.
To create the header link URL, the path is taken from HttpContext.Request.Path, so there is no way to customize it to point to a different route.
One very ugly hack would be to tap into to jQuery Ajax's events (since the header link uses jQuery.load to sort) and overwrite the URL:
Album Id
Better solution would be to use:
Telerik Grid which lets you specify custom routes and also offers much more flexibility in rendering your layout
or MvcContrib Grid (not sure if this lets you modify header links but definitely offers more flexibility than WebGrid)
#MrChief had the idea above about the ugly hack...I put that together. Here is the main code that I used to do this. It does, indeed, hijack the ajax call before it is put on the wire. The key is to modify the URL that is getting sent because the grid will grab that URL from HttpContext.Request.Path. and plug it into the onclick for the anchor element.
I put this into my main common.js and will simply attach a function to capture the ajaxSend event which happens just before the data is sent.
// Used to hijack the sending of all AJAX calls. Before it sends the call to the server, it checks to see if the
// active element (the element that prompted the call) is marked with a given class. If so, then it will perform
// the given operation.
$(document).ajaxSend(function (event, jqXHR, ajaxOptions) {
var activeElement = document.activeElement;
if ($(activeElement).attr('redosorturl') != null) {
// If this is a sort anchor link from a grid that needs to have the sort link redone, do it here.
// the code is in the eipGrip.js file.
if ($(activeElement).attr('redosorturl').toString() == 'redoSortURL') {
var newURL = RedoGridSortURL(activeElement, ajaxOptions.url.toString());
ajaxOptions.url = newURL.toString();
}
}
return false;
});
When rendering the page, I have marked the tag in column header that contains the incorrect URL with a class named "redosorturl', so I know when I hijack the ajax call, the operation has to be done on this element. I then call a custom function that gives me the correct URL, then the ajaxOptions.url is then rewritten with that new URL.
I have to pass the activeElement to that rewrite function so I can traverse up the DOM to get the grid information, where I have put data like the controller and action method that is used along with and IDs and other info that I use for the URL. Likewise, I pass in the current url string because the grid will inject a token at the end of the url that I parse off and put on the new url.
Your conclusion isn't right. You just need to wrap your webgrid in a Get form:
using (Html.BeginForm("GetUserList", "ThingaMaBob", System.Web.Mvc.FormMethod.Get))
{
var grid = new WebGrid(
...
));
Html.Hidden(grid.SortFieldName, grid.SortColumn);
Html.Hidden(grid.SortDirectionFieldName, grid.SortDirection == SortDirection.Ascending ? "ASC" : "DESC");
}
The hiddens are so that the sort dir and sort field end up in parseable form in the querystring. You end up with urls like localhost/ThingaMaBob/GetUserList?someotherfields=whatever=&sort=city&sortdir=ASC
If you remove [HttpPost] attribute and let the route come to the same function. you'll find the Request["page"] value in your method. this will allow you to put a check on Request["Page"] value.

Resources