Make first kendo grid filter control lose auto focus - kendo-ui

Inside my kendo grid, some column is filtered with a kendo multiselect control. The control has a placeholder.
columns.Bound(p => p.ModuleName).Title("Module").Filterable(filterable => filterable.UI("moduleFilter"));
function moduleFilter(element) {
element.kendoMultiSelect({
placeholder: "Select Module",
dataSource: {
transport: {
read: {
url: "#Url.Page("Module", "ReadAll")",
data: function() {
return kendo.antiForgeryTokens();
}
}
}
}
});
}
In this filter, I have removed some default filter elements for better appearance.
function filterMenuInit(e) {
if(e.field == 'ModuleName') {
e.container.find('[title="Operator"]').remove(); //gives focus to multiselect
e.container.find('.k-filter-help-text').remove();
}
}
The problem is by doing this, the multiselect gets the focus, losing the initial placeholder. Is it possible to make the multiselect lose focus or trick the filter to give the focus to another control? I tried various ideas without success.

Related

kendo-datasource autoSync causes navigation placeholder to return to upper left corner of the grid

I'm using kendo-ui with angularJS 1.5 and I have a simple kendo-grid bound to a datasource with transport configured using functions as follows:
private buildDataSource() {
this.dataSource = new kendo.data.DataSource({
autoSync: true,
change: this.dataSourceChangeHandler.bind(this),
error: this.dataSourceErrorHandler.bind(this),
transport: {
read: this.dataSourceRead.bind(this),
create: this.dataSourceCreate.bind(this),
update: this.dataSourceUpdate.bind(this),
destroy: this.dataSourceDestroy.bind(this)
},
[...]
});
}
private dataSourceUpdate(e: kendo.data.DataSourceTransportUpdate) {
var updatedItem: KendoCosto = e.data;
[...]
e.success(updatedItem, undefined, undefined);
}
The grid options looks like this:
this.gridOptions = {
dataSource: this.dataSource,
change: this.gridChangeHandler.bind(this),
editable: {
mode: "incell",
confirmation: false
},
navigatable: true,
selectable: "multiple, cell",
allowCopy: true,
toolbar: [
"create"
],
[...]
The grid works fine and the read, create, update, destroy behave as expected.
My problem is that whenever I change a value in a grid's cell and hit enter, I would like to have keyboard navigation "placeholder" (the grid has navigatable: true) to remain on the edited cell, but it happens to be moved to the upper left corner cell.
This behavior happens only when dataSource's autoSync is set to true.
I've also tried to "set" the current cell via the ".current" method of the grid's api but it doesn't seem to work:
// this is bound to the grid's change event and it is supposed to
// store the currently selected cell in a property of the class
// that builds both the datasource and the grid
private gridChangeHandler(e: kendo.ui.GridNavigateEvent)
{
this.thisGrid = this.thisGrid || e.sender;
this.currentCell = e.sender.current();
}
// Then on the change event of the datasource I do
private dataSourceChangeHandler(event: kendo.data.DataSourceChangeEvent)
{
if (this.currentCell && this.thisGrid) {
this.thisGrid.select(this.currentCell);
this.currentCell = undefined;
}
}
any suggestions ?
Thanks in advance !
--- edit ---
The code I posted/pasted in the comment is absolutely unreadable so I'm repeating the code here:
To have your solution work, I had to modify my dataBound handler this way.
private gridDataBoundHandler(e: kendo.ui.GridDataBoundEvent) {
if (this.thisGrid && this.currentCell) {
setTimeout((() => {
// this.thisGrid.editCell(this.currentCell);
this.thisGrid.current(this.currentCell);
}).bind(this)
, 10);
}
}
without the timeout, the navigation placeholde was still resetting back to the upper left corner.
First, I think the grid change event is the wrong event to attach to as it only fires when the user selects a row/cell with the mouse...it will not fire on tab events.
So, I would use the grid save event, which fires after you make an edit and "commit" the change through enter, tab, mouse off, etc.
Second, the e.sender.current() includes the current identifying information like "grid_active_cell" and "k-state-focused" and "k-dirty-cell", etc. By the time you get to the dataSource change event, the cell has actually lost all that decoration and your this.currentCell is essentially pointing at a non-existent selector. So, you need to grab a more "permanent" identifier.
So, using the grid save event:
save: function (e) {
var row = $(e.sender.current()).closest("tr");
var colIdx = $("td", row).index(e.sender.current());
var model = e.sender.dataItem(row);
currentCell = "tr[data-uid='" + model.uid + "'] td:eq(" + colIdx + ")";
}
And then in the grid DATABOUND event(as the dataSource change event is still followed by events that change the cell focus to the top-left, but grid.dataBound is further in the chain and seems to work better):
dataBound: function (e) {
if (currentCell) {
grid.editCell(currentCell);
grid.current(currentCell);
}
}
Demo(with variable changes as I do not have your whole class, based on a kendo grid demo): http://dojo.telerik.com/#Stephen/OjAsU
Note that this solution(not my implementation, but your technique in general) will break tabbing from cell to cell, i.e. tabbing will commit the edit but the dataSource change event will always put the focus back on the just-edited cell instead of moving to the tabbed-to cell. This breaks user expectation of what tab does. So, you should consider trying to capture the enter key press only instead of relying on the grid events(which fire regardless of tab or enter).

Kendo Grid - Add New Item after sorting issues

I am using Kendo UI v2014.1.528
Binding data in Kendo Grid like below
$("#list485").kendoGrid({
dataSource: dataSource,
sortable: true,
columns: [
//Column List
]
);
It gives me a grid with "Sort" and "Add New Record" feature.
If i click on "Add New Record" button, it adds an empty record in the first row of the grid. This is fine.
But if i sort the grid on any column and then click on "Add New Record" button, the empty row for new record gets added somewhere in between the existing rows.
Can someone help me understand and fix this issue?
You can clear the sorting or filtering from the Kendo grid while clicking on the custom Add button.
I have added the Razor code
Code to add a custom Add button to catch the Javascript
.ToolBar(toolbar =>{ toolbar.Custom().Name("cmdAddRecord")
.Text("Add New Record")
.HtmlAttributes(new { #id = "cmdAddRecord" }); })
Javascript to clear the sorting and filtering.
$("#cmdAddRecord").click(function (e) {
var grid= $("#Grid").data("kendoGrid");
var sorting = grid.dataSource.sort();
var filtering = grid.dataSource.filter();
if (filtering) {
grid.dataSource.filter(null);
}
if (sorting) {
grid.dataSource.sort(null);
}
grid.addRow();
e.preventDefault();
});

Kendo grid with MVVM, binding column visibility

I have a kendo grid using MVVM.
My problem is I can't seem to set column visibility using the hidden attribute and an expression:
data-columns=
"[{'template':'# if (User!=null) { # #=User.Name# # } #',
'title':'User', 'hidden': User==null}
The template works, but the 'hidden' attribute doesn't seem to.
Is there any way to get this to work?
As an alternative, you could bind to the dataBinding or dataBound event to hide the column conditionally:
data-bind="events:{ dataBinding: onDataBinding }"
View model:
var viewModel = kendo.observable({
User: null,
showHideUserColumn: function (e) {
var grid = e.sender;
if (this.User) {
grid.showColumn("User");
} else {
grid.hideColumn("User");
}
},
onDataBinding: function (e) {
this.showHideUserColumn(e);
// if you want to track changes, (re)bind change tracking
this.unbind("change", this.showHideUserColumn);
this.bind("change", this.showHideUserColumn);
}
});
Only the properties specified via the data-bind attribute participate in MVVM change tracking. The other data attributes are mapped to widget configuration properties and are not evaluated against the view model.
Currently there is no binding which will allow you to hide and show grid columns.

KendoGrid Validation for a field doesn't get called on grid column sort/filter

Validation used for a field in KendoGrid works fine on currently being edited cell when I try to select other cell.But It doesn't work when I try to sort any column or use filter.
How can I enforce validation as the way normal focusout event works to any HTML element?
Code used in datasource
var mainDataSource={
data :listJson
,type:"json"
,batch:true
,schema: {
model: {
id: "Port_ID"
,fields:{
Port_ID:{type: "string",editable:false,nullable:false}
,Slot1:{type:"number",editable:false}
,Slot2:{type:"number",editable:false}
,Type1:{type: "string",editable:true}
,Type2:{type: "string",editable:false}
,IsHFL:{type:"boolean",editable:false}
Project:{
type:"string"
,editable:true
,validation: {
custom: function(input) {
if(input.val()=="") {//to be added further
input.attr("data-custom-msg", "Message");
return false;
}
else
return true;
}
}
}
,Used_For:{ type: "string",editable:true}
,Start_Date:{type:"date",editable:true}
}
}
}
};
Got feedback from telerik team on it http://www.kendoui.com/forums/framework/validation/validation-call-not-triggered-on-grid-column-sort-filter.aspx
Generally speaking, preventing the binding when there are validation errors is not supported, but can be achieved with some additional code. Basically, you should use the dataSource requestStart event to prevent the binding with the event argument preventDefault method when there are errors e.g.
requestStart: function(e){
var grid = $("#grid").data("kendoGrid");
if(grid.editable && !grid.editable.validatable.validate()){
e.preventDefault();
}
}

Dynamically change a column's editable property with select box

I am using form editing. I would like to disable certain fields in my add and edit forms based on the selection from a drop down box. What event is best to use to trigger this? I have attempted using dataEvents:
{ name:'type_cd',
edittype:'select',
editoptions:{
dataUrl:'functions.php',
dataEvents:[{
type:'change',
fn: function(e){
$(this).setColProp('cntrct_id',{
editoptions:{editable:false}
});
}
}]
}
},
This has no visible effect on my form fields, but I know that it's being reached because I can get an alert message from it if I put one in.
EDIT
If I submit the form, the next time I open it, the column that was set to editable:false will not appear. This is a step in the right direction, BUT I want it to immediately be uneditable. Really, I would like it to be visible, but disabled (i.e. disabled:true)
First of all dataEvents allows you to register callbacks on elements of edit elements. Inside of callbacks this will be initialized to the DOM element which will be bound. So $(this) inside of change handler it will be wrapper on <select> element and not on the grid. The usage of $(this).setColProp will be incorrect.
To disable some input field in Add/Edit form you can use the fact that all input elements get the same id like the value of name property on the corresponding column in colModel. So if you need to disable input of cntrct_id you can set disabled property to true on the element with id="cntrct_id"
{
name: 'type_cd',
edittype: 'select',
editoptions: {
dataUrl: 'functions.php',
dataEvents: [{
type: 'change',
fn: function (e) {
// disable input/select field for column 'cntrct_id'
// in the edit form
$("#cntrct_id").prop("disabled", true);
}
}]
}
}
It's important to understand that editoptions will be used for any existing editing modes (form editing, inline editing and cell editing). If you want to write the code of dataEvents which supports all editing modes you have to detect editing mode and use a little other ids of editing fields. The code (not tested) can be about as below
{
name: 'type_cd',
edittype: 'select',
editoptions: {
dataUrl: 'functions.php',
dataEvents: [{
type: 'change',
fn: function (e) {
var $this = $(e.target), $td, rowid;
// disable input/select field for column 'cntrct_id'
if ($this.hasClass("FormElement")) {
// form editing
$("#cntrct_id").prop("disabled", true);
} else {
$td = $this.closest("td");
if ($td.hasClass("edit-cell") {
// cell editing
// we don't need to disable $("#cntrct_id")
// because ONLY ONE CELL are edited in cell editing mode
} else {
// inline editing
rowid = $td.closest("tr.jqgrow").attr("id");
if (rowid) {
$("#" + $.jgrid.jqID(rowid) + "_cntrct_id")
.prop("disabled", true);
}
}
}
}
}]
}
}
The last remark. If you still use old version of jQuery (before jQuery 1.6) which don't support prop method you have to use attr instead.
#Oleg: This is working(could get the alert messages) but its not disabling the field.
Should the form field require any special values?

Resources