What is the way to catch anytime a view is rendered?
Not only when switching views, but also when clicking today / prev / next?
I need to clear an array of unique event titles after (or before) each render is complete.
So, similar to eventAllRender which was removed starting v4.
Currently using .click event for all buttons, which does the trick, but I was hoping there was something really linked to the actual rendering.
calendar.render();
$('.fc-button').click( () => {
console.log("do something")
})
https://fullcalendar.io/docs/datesSet
Called after the calendar’s date range has been initially set or
changed in some way and the DOM has been updated.
datesSet: function(info) {
// ...
}
I’m using Kendo UI v2016.3.1118 for my web application.
I use the editing capabilities (mode: “incell”) in the Kendo UI grid. I have created a grid with editing textbox, date, and numeric values and it works fine.
What I want to do now is to apply editing for columns with dropdown values.
I’ve integrated a custom dropdownprovider like described in Telerik sample (https://demos.telerik.com/kendo-ui/grid/editing-custom, demo: https://dojo.telerik.com/UjAGU).
That works so far quite well. However, after I change a value in the DropDown and the cell loses focus, the display switches back to the view mode. It only appears a little red indicator in the upper left of the cell, indicating the value has been changed (cell is “dirty”). Except of the red indicator the cell is empty (no value is shown in cell).
In my case I’ve only numeric (foreign key) values for the columns of type dropdown foreign in my datasource.
My datasource looks similar to this:
{
Product ID: 1,
ProductName: "Chai",
Category: 1
}
Datasource in sample provided by Telerik:
{
Product ID: 1,
ProductName: "Chai",
Category: {
CategoryID: 1,
CategoryName: "Beverages",
Description: "Soft drinks, coffees, teas, berries, and ales"
}
}
I've tried to set the cell value to the selected text in the Select-Event of the dropdown. Nevertheless there is still no text shown for the dropdown in view-mode. Unfortunately, I cannot find a suitable event. The event closeCell is never thrown in my constellation.
Any ideas out there?
Regards
Stefan
I think your issue probably stems from the difference between what is returned by your dropDownList when you make a selection (i.e. an entire object, complete with text and value), and what your grid model object requires (just the value).
Assuming you have a function to create the editor like the one in the sample you referenced, can you please try altering it to set the valuePrimitive property to true?
function categoryDropDownEditor(container, options) {
$('<input required name="' + options.field + '"/>')
.appendTo(container)
.kendoDropDownList({
valuePrimitive: true,
autoBind: false,
dataTextField: "CategoryName",
dataValueField: "CategoryID",
dataSource: {
type: "odata",
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Categories"
}
}
});
}
According to the documentation:
If set to true, the View-Model field will be updated with the selected item value field. If set to false, the View-Model field will be updated with the selected item.
Hopefully that will resolve your issue.
I have a grid I created in Gridx which lists a bunch of users. Upon clicking a ROW in the grid (any part of that row), a dialog pops up and shows additional information about that user and actions that can be done for that user (disable user, ignore user, etc.) - when one of these options is selected from the pop up, I want to DISABLE that row. The logic for getting the row, etc. I can take care of, but I can't figure out how to make a grid row actually "appear" disabled and how to make that row no longer clickable.
Is there a simple way to do this? If you aren't familiar with gridx, solutions that apply to EnhancedGrids or other Dojo grids are also appreciated.
Alright now that I have a little more information here is a solution:
Keep a list of all the rows you have disabled so far either inside the Grid widget or in its parent code. Then on the onRowClick listener I would write code like this:
on(grid, "onRowClick", function(e) {
if(disabledRows[rowIndex]) {
return;
}
// Do whatever pop up stuff you want and after
// a user selects the value, you can "disable"
// your row afterwards by adding it to the disabled
// list so that it can no longer be clicked on.
var rowIndex = e.rowIndex;
disabledRows[rowIndex] = true;
// This is just some random class I made up but
// you can use css to stylize the row however you want
var rowNode = e.rowNode;
domClass.add(rowNode, "disabled");
});
Note that domClass is what I named "dojo/dom-class". Hope this helps!
This is perhaps not exactly what you are seaching for:
If you want to hide one or more rows by your own filterfunction you could just add to these rows in the DOM your own class for nodisplay. Here I show you a function for display only those rows which have in a choiceable field/column a value inside your filterlist.
function hideRowFilter(gridId, fieldName, filterList)
{
var store = gridId.store;
var rowId;
store.query(function(object){
rowId = gridId.row(object.id,true).node();
if (filterList.indexOf(object[fieldName]) == -1)
domClass.add(rowId, "noDisplay"); // anzeigen
else
domClass.remove(rowId, "noDisplay"); // verstecken
});
}
CSS:
.noDisplay { display: none; }
So I can for example display only the entries with a myState of 3 or 4 with this call:
hideRowFilter(gridId, 'myState', [3, 4]);
Note that domClass is what I named "dojo/dom-class"
As is typical for grids in a "dashboard" application that monitors dynamically changing data, my (Telerik) Kendo UI grid is refreshed with fresh data periodically, every 60 seconds:
grid.dataSource.data(freshData);
grid.refresh(); // have been informed this refresh may not be necessary
The schema does not change, but some new rows might show up in the dataset and some might have been removed.
Although the grid.refresh() leaves the groupings intact, and the sort state is also preserved, any collapsed groups get expanded.
QUESTION: How to preserve (or restore) the expanded/collapsed state of the groups (so a user focusing on a particular expanded group with the other groups collapsed is not inconvenienced/frustrated by the periodic updates in which every group gets re-expanded by default)?
EDIT: Some Winforms grids provide a way to "take a snapshot" of the group expand/collapse state before refreshing data, and then to reapply that state after the datasource refresh. If the group header rows in the Kendo UI grid had UIDs (that survived a refresh) it could be done. But see the suggested approach below that does not involve persistent UIDs.
USE CASE:
Here is a typical if somewhat dramatic use case for this feature. Center for Disease Control is monitoring real-time outbreaks of a particular strain of flu, by city. Every 15 seconds the dataset is being refreshed. They happen to be focusing at the moment on Los Angeles and have that city expanded, and the other cities collapsed. If every 15 seconds the entire grid expands, it pisses off the doctors at the CDC and they go in and strangle the programmer and then they go home to play golf, and everyone in Los Angeles succumbs. Does Kendo really want to be responsible for that disaster?
POSSIBLE FEATURE ENHANCEMENT SUGGESTION:
Ignore my suggestion about a UID above. Here's a better way.
The grid has
<div class="k-group-indicator" data-field="{groupedByDataFieldName}">
...
</div>
Now, if that k-group-indicator div could contain a list of the distinct values of data-field with each key's associated data being the expanded/collapsed state of the corresponding section, it would then be possible to save that list to a buffer before making a call to the dataSource.data( someNewData) method, and then in the eventhandler listening for dataBound event, those expand states could be reapplied. To find the corresponding grouping section for the grouping value, it would be very helpful if the k-grouping-row could have a property called group-data-value which held the grouping value of the particular grouping section, e.g. "Sales" or "Marketing" if one were grouping by a data-field called Department.
<div class="k-group-indicator" data-field="dept" data-title="Dept" data-dir="asc">
...
<div class="k-group-distinct-values">
<div group-data-value="Sales" aria-expanded="false" />
<div group-data-value="Events Planning" aria-expanded="true" />
</div>
</div>
and then in the k-grouping-row: <tr class="k-grouping-row" group-data-value="Sales">
It is understandable that this isn't a built-in feature. It is pretty complicated because if you have nested groupings, you would have to remember each collapsed group in the hierarchy that it existed in. Since items will be moving in and out of the DataSource, this would be a pain to track.
That said, here is a very hackish way to accomplish what you want, as long as you don't get too complicated. It just uses the groupHeaderTemplate property to add a UID to each grouping row. I am just using the column name + value as the UID, which is technically wrong if you get into multiple groupings, but it is good enough for an example.
From there, before you refresh you can find the collapsed groups from the ARIA attribute that Kendo has now (side-note, you have to be using 2012 Q3 for this to work). Then drill down and get the UID that was added by the template.
After the refresh, you can find the rows with a matching UID and pass them to the grid's .collapseGroup() function to re-collapse it.
Here is a working jsFiddle that demonstrates this.
And the code from the jsFiddle copy/pasted in (please note that I only set the template on the City column, so only the City column will preserve grouping collapse in this example!):
HTML:
<button id="refresh">Refresh</button>
<div id="grid" style="height: 380px"></div>
JavaScript:
var _getCollapsedUids = function () {
var collapsedUids = [];
$("#grid .k-grouping-row span[data-uid]")
.each(function(idx, item) {
if($(item)
.closest(".k-grouping-row")
.children("td:first")
.attr("aria-expanded") === "false") {
collapsedUids.push($(item).data("uid"));
}
}
);
return collapsedUids;
};
var _collapseUids = function (grid, collapsedUids) {
$("#grid .k-grouping-row span[data-uid]")
.each(function(idx, item) {
if($.inArray($(item).data("uid"), collapsedUids) >= 0) {
console.log("collapse: " + $(item).data("uid"))
grid.collapseGroup($(item).closest("tr"));
}
}
);
};
var refresh = function () {
var collapsedUids = _getCollapsedUids();
var grid = $("#grid").data().kendoGrid;
grid.dataSource.data(createRandomData(50));
_collapseUids(grid, collapsedUids);
};
$("#refresh").click(refresh);
$("#grid").kendoGrid({
dataSource: {
data: createRandomData(50),
pageSize: 10
},
groupable: true,
sortable: true,
pageable: {
refresh: true,
pageSizes: true
},
columns: [ {
field: "FirstName",
width: 90,
title: "First Name"
} , {
field: "LastName",
width: 90,
title: "Last Name"
} , {
width: 100,
field: "City",
groupHeaderTemplate: '<span data-uid="City-#=value#">#= value #</span>'
} , {
field: "Title"
} , {
field: "BirthDate",
title: "Birth Date",
template: '#= kendo.toString(BirthDate,"dd MMMM yyyy") #'
} , {
width: 50,
field: "Age"
}
]
});
Personally I don't really like this solution at all. It is way too hacky and way too much DOM traversal. However without re-implementing the grid widget I can't think of a better way to do it. Maybe it will be good enough for what you are trying to accomplish or give you a better idea.
One last note; I checked the Kendo UI source code and it does not appear to track which groupings are expanded/collapsed. They do something similar to what I did with the aria attribute, but instead check the class that drives the icon state:
if(element.hasClass('k-i-collapse')) {
that.collapseGroup(group);
} else {
that.expandGroup(group);
}
If you are not using Kendo 2012 Q3 and can't use the aria-expanded attribute, you could change the code to check the icon class instead.
I've started a robust group state preservation grid extension that is designed to work with both Kendo Grid and ASP.Net RadGrid (control-specific implementations that utilize common functionality).
This extension makes significant improvements to Telerik's group state preservation example and enhances RadGrid, for which nothing else available even comes close to the Kendo UI example. You can see the list of improvements here, and you can check out the code here.
I'd like to know what you think.
"Answering" my own question just to get the better legibility of the code-formatting in the answer-editor. This is an extension of the discussion.
I agree that nested groupings are more complicated. If each k-grouping-row had a property containing a JSON-representation of the array of distinct data values on which the grouping is based, it would be possible for developers to extract the distinct combinations of data-values from each collapsed k-grouping-row. (It would help if the k-grouping-row directly indicated whether it was expanded or collapsed but that info can be obtained from the cell it contains, right?)
With this set of distinct-values for collapsed groups in hand, one could construct ones own map to the collapsed groups. The distinct data values could act as the key to the objects in this map; each distinct-data combination being unique and associated with only one grouping section in the grid, no matter how many levels of nesting are involved.
For example, for a two-tiered nesting by Department by ProductType we would see something like this:
<tr class="k-grouping-row" data-distinct-values="['Sales','Toys, Games and Videos']">.
The Department value is "Sales" and the ProductType value is "Toys, Games and Videos". The JSON handles commas in the data value.
For a three-tiered grouping by state, city, zipcode we would have:
... data-distinct-values="['California','Beverly Hills','90210']"
These data values are known when the group is created so they are available to be injected into the k-grouping-row as a unique handle to it.
Although the distinct-values are a unique handle, they do not eliminate the need to traverse the DOM, visiting each and every k-grouping-row when one wants to reapply the collapsed state. Yet the Kendo grid would not have to implement the restoration of the collapsed state by default, if it was felt that this was too expensive an operation. But you would be giving developers a simple way to accomplish it using data-distinct-values=[...], and the developers could decide for themselves whether the performance hit, if any, was justified by the requirements of the application.
This is not supported out of the box, but it can be achieved by maintaining an array of the expanded groups (or collapsed clusters).
At a high level - you use a marker to find if a group is collapsed or expanded. Then maintain a list of groups that expanded and only expand those when you refresh your grid.
In my case, I use the default kendo icon that is different for expanded groups (.k-i-collapse) versus collapsed groups (.k-i-expand).
var expandedGroups = [];
The expandedGroups is available globally to me. Modify this as per your need.
Then on save or discard changes of the kendo grid, I call the below method, that is - call it BEFORE your code is doing the grid.refresh() orgrid.dataSource.read() that is triggering the grouping states to be lost.
function updateExpandedGroupsList() {
expandedGroups = []; // reset state
// find the list of group labels adjacent to expanded group icons
var listOfExpandedGroupsLabels = $("#gridId .k-icon.k-i-collapse~span");
for (i = 0; i < listOfExpandedGroupsLabels .length; i++) {
expandedGroups.push(listOfExpandedGroupsLabels [i].innerHTML);
}
}
So what I'm doing in the above method is finding all the instances of the little expand arrow that is pointing downwards, then finding the sibling spans which have the names of the groups, that we need to store on our expandedGroups array for later use.
Now that we have that, your action that is resetting the grid will happen and likely the dataBound or another event will be fired after. In that piece of the code, you have something that is (let's say) collapsing all the groups by default. There, you need to do the reverse process: Find the span and the group name from the iterating group control and check if it is in the list of expandedGroups. If it is, then don't collapse it (or expand it).
collapseGroups(expandedGroups);
After calling the collapse groups and passing the array:
// method collapse groups, excluded groups will not be touched
function collapseGroups(listOfExcludedGroups) {
var grid = $("#gridId").data("kendoGrid");
if (!listOfExcludedGroups) {
listOfExcludedGroups = [];
}
$(".k-grouping-row").each(function () {
var groupName = $(this).find("span")[0].innerHTML;
if (groupName && listOfExcludedGroups.indexOf(groupName) > -1) {
return; // continue
}
grid.collapseGroup(this);
});
}
First of all you rarely need to call refresh from your code. The grid (and all data-bound Kendo widgets) are listening for changes of the data source and will refresh accordingly.
By design the expand/collapse state of the groups is not preserved. Changing the data source will cause all groups to get expanded (which is their default state).
Scenario: I have an .aspx page containing multiple collapsible panels. Each panel represents a different report. To run a report, you click a panel and the report's user controls will appear. The date range control I created could be contained "within" more than one panel.
The code below does not work in the multiple panels instance. It sets all of the "to date" text boxes equal to the start date instead of just the active panel's "to date" text box.
How do I only work with the text boxes in the panel I have expanded?
Thanks for your help!
<script type="text/javascript">
$(document).ready(function(){
$('#dFrom').datepicker();
$('#dTo').datepicker();
$('#dTo').click(function(){
try{
var from = $('#dFrom').datepicker("getDate");
$('#dTo').datepicker("setDate",from);
}
catch(Error)
{
alert(Error);
}
});
});
Firstly, you shouldn't be using IDs for any html element that exists more than once, use classes to identify repeating elements instead.
To answer your question, you need to use $(this) to point at the specific element the click event is coming from. You can then simply query the date picker the event is called from by asking for its sibling.
$(document).ready(function(){
$('.dTo').click(function(){
var from = $(this).siblings('.dFrom').datepicker("getDate");
$(this).datepicker("setDate",from);
});
});
I don't know your actual HTML structure so you may have to alter how the siblings are discovered, but hopefully you get the idea.
You need to get a little more relative with your selector syntax. I see you're using the id of each field -- is this shortened from the ASP.Net UniqueID? Because that's definitely not how it would look.
Rather than manually lookup the id, let ASP.Net make of it what it will and find them the jQuery way:
$(Function() {
$('input[id$=dFrom]').datepicker();
$('input[id$=dTo]').datepicker();
$('.panel').each(function() { //replace with appropriate selector syntax for your panels
$(this).click(function() {
var from = $('input[id$=dFrom]',this).datepicker("getDate");
$('input[id$=dTo]',this).datepicker("setDate",from);
});
});
});