In our UI for ASP.NET Core R3 2020 (2020.3.915) release, the Column menu message of unsticking a column is "null".
This bug will be resolved in our next official release.
In the meantime, as a workaround, manually set the Unstick Column menu message:
.ColumnMenu(c => c.Messages(m => m.Unstick(
"Unstick Column"
)))
Good afternoon,
Is there a way to populate a second grid based on the outcome of the read action for the first grid?
For example, the read action for grid1 pulls a list of files from the file system in and runs checks against each file. The list generated is returned to load grid1. During the processing a number of errors are generated, creating a second list. Ultimately I'd like grid2 to display that list.
It seems unnecessary to have a separate action for grid2 that is essentially running the same processing, just returning a different list.
With the two grids having AutoBind set to false I assume I can control the order the girds are populated. Could grid2 be populated from a list stored in ViewData?
This article explains how two models can be returned to a single View, but ToDataSourceResult in the Controller can only return one model:
https://www.c-sharpcorner.com/UploadFile/ff2f08/multiple-models-in-single-view-in-mvc/
Kind regards,
Richard
@(
Html.Kendo().Grid<IndexModel.CompanyFinancialVM>()
.Name("gridCompanyFinancial")
.Navigatable()
.Height(590)
.Sortable()
.Editable(e => e.Mode(GridEditMode.InCell))
.Scrollable()
.ToolBar(t => { t.Save(); t.CancelEdit(); })
.Columns(columns =>
{
columns.Bound(f => f.CompanyName).Title("Company").Width(150);
columns.Bound(f => f.PeriodName).Title("Period").Width(120);
columns.Bound(f => f.VariableName).Title("Variable").Width(150);
columns.Bound(f => f.VariableTypeName).Title("Variable Type").Width(120);
columns.Bound(f => f.Val).Title("Val")
.Width(100)
.Format("{0:n}") // Show 4 decimals and thousand separator
.EditorTemplateName("Decimal");
columns.Bound(f => f.ValCurr)
.Title("Currency")
.ClientTemplate("#= getCurrencyName(ValCurr) #")
.EditorTemplateName("Currency")
.Width(120);
columns.Bound(f => f.QuantumFK)
.Title("Quantum")
.ClientTemplate("#= getQuantumName(QuantumFK) #")
.EditorTemplateName("QuantumFK")
.Width(120);
columns.Bound(f => f.Priority).Title("Priority").Width(80);
columns.Bound(f => f.SpecOrder).Title("Spec Order").Width(100);
columns.Bound(f => f.Rem).Title("Remarks").EditorTemplateName("Rem");
})
.DataSource(ds => ds.Ajax()
.Read(r => r.Url(Url.Content("~/CompanyFinancial/Index?handler=Read")).Data("getGridRequestData"))
.Update(u => u.Url(Url.Content("~/CompanyFinancial/Index?handler=Update")).Data("forgeryToken"))
.Batch(true)
.Model(m =>
{
m.Id(f => f.Nr);
m.Field(f => f.CompanyName);
m.Field(f => f.PeriodName);
m.Field(f => f.VariableName);
m.Field(f => f.VariableTypeName);
m.Field(f => f.Priority);
m.Field(f => f.SpecOrder);
m.Field(f => f.Val);
m.Field(f => f.ValCurr);
m.Field(f => f.QuantumFK);
m.Field(f => f.Rem);
})
.Sort(s => s.Add(f => f.SpecOrder).Ascending())
.PageSize(20)
)
.Pageable()
Hi,
I'm using Teleik Core components, latest version in mvc application.
I have defined grid in view with name "gridMara"
In javascript i have code:
var gridMara = $("#gridMara").data("kendoGrid");
I checked in console, $("#gridMara") is initialized.
But when i use statement:
var gridMara = $("#gridMara").data("kendoGrid");
the value of gridMara is undefined.
Please help.
Regards,
Tomaz
Hi all,
Going nuts over this problem. Should be simple, and for other technologies telerik shows solutions, but can not get it to work for razor pages .net core.
What i want is:
I have a grid that opens in a popup when editting. In the editortemplate i have a childgrid showing all possible children that can be added to this record. That is working. However, i want to multiselect in this grid without having my customers to hold down ctrl or use a textbox. Main reason: When using a textbox, you really have to click in the textbox, clicking outsisde of it won't work. So i removed the select column (the checkboxes) and just want people to click somewhere on a row to select it and be able to click on another row without the fiorst one loosing it's selected status. The only hook i can find is the onchange event. This indeed allows me to catch the slection process. However, the previously selected items are not available any more, so i oose them.
Anyone an idea how to do this quite simple trick?
<div style="height: 100%;">
<!-- Parent Grid -->
<div style="width: 60%; height: 100%; float: left;">
<h2>{_ParentItem_}s</h2>
@(Html.Kendo().TreeList<ParentChildModel>()
.Name("ParentGrid")
.Columns(columns =>
{
columns.Add().Field(p => p.Id).Width(80).Hidden(false);
columns.Add().Field(p => p.ItemId).Width(80).Hidden(true);
columns.Add().Field(c => c.Name).Title("Name").Width(140).Template("#= getIndentedName(Name, Id) #");
columns.Add().Field(e => e.AssetCode).Title("{_AssetCode_}").Width(60);
columns.Add().Field(e => e.Weight).Title("Weight").Format("{0:n3}").Width(40).Hidden(false);
columns.Add().Field(e => e.Dimension).Title("Dimension").Width(100).Hidden(false);
columns.Add().Command(c =>
{
c.Edit().Text("Edit").ClassName("k-grid-edit");
c.Destroy().Text("Delete").ClassName("k-grid-delete");
}).Title("Actions").Width(80);
})
.Editable(editable => editable.Move(move => move.Reorderable(true)).Mode(TreeListEditMode.PopUp)
.TemplateName("ParentPopupEditor"))
.Toolbar(toolbar =>
{
toolbar.Create().Text("Add New {_ParentItem_}");
toolbar.Custom().Template(
"<div>" +
"<input id='toolbarComboBox' style='width: 300px;' />" +
"</div>"
);
toolbar.Search();
})
.DataSource(dataSource => dataSource
.Read(read => read.Action("GetParentAndChildItems", "ParentChild").Data("parentSearchData"))
.Create(update => update.Action("AddNewRecord", "ParentChild").Type(HttpVerbs.Post))
.Update(u => u.Action("UpdateRecord", "ParentChild").Type(HttpVerbs.Post)) //.Data("saveFormData"))
.Destroy(update => update.Action("DeleteRecord", "ParentChild"))
.ServerOperation(false)
.PageSize(20)
.Model(m =>
{
m.Id(f => f.Id);
m.ParentId(f => f.ParentId);
m.Expanded(true);
m.Field(f => f.ItemId);
m.Field(f => f.AssetName);
m.Field(f => f.AssetCode);
m.Field(f => f.Weight);
m.Field(f => f.Dimension);
})
)
.Pageable(x => x.PageSizes(new int[] { 20, 50, 100, 200, 500 }).Refresh(true).Input(true))
.Sortable()
.Selectable()
.Events(e => e.DataBound("dataBound").Save("onEditorDataSave").DragEnd("onDragEnd"))//.DragStart("onDragStart").DragEnd("onDragEnd")
)
</div>
<!-- Assignable Assets -->
<div style="width: 40%; height: 100%; float: right;">
<h2>Assignable {_Asset_}s</h2>
@(Html.Kendo().Grid<ItemDto>()
.Name("AssetGrid")
.HtmlAttributes(new { style = "height:100%; width:100%;" })
.Columns(columns =>
{
//columns.Template(@<text> </text>).Draggable(true).Width(30);
columns.Template("").Draggable(true);
columns.Bound(a => a.Id).Title("Id").Width(60).HtmlAttributes(new { @class = "idColStyle" });
columns.Bound(a => a.Title).Title("{_AssetName_}").Width(150);
columns.Bound(a => a.ItemTypeName).Title("{_AssetType_}").Width(100);
columns.Bound(a => a.LocationName).Title("Destination {_Location_}").Width(110);
})
.ToolBar(toolbar =>
{
toolbar.Custom().ClientTemplate(Html.Kendo().Template().AddComponent(c => c
.TextBox().Name("toolbarTextBox")
.Placeholder("Filter by {_AssetName_}/{_AssetType_}...")
.HtmlAttributes(new { style = "float: right; width: 300px;" })
.Events(ev => ev.Change("toolbarTextBoxChanged"))
));
toolbar.Search();
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.ServerOperation(false)
.Model(m => m.Id("Id")) //Ensure that the Model identifier ("Id") is defined.
.Read(read => read.Action("GetAssignableAssets", "ParentChild").Data("childrenSearchData"))
)
.Pageable()
.Sortable()
.Selectable()
)
</div>
</div>
$(document).ready(function () {
var treeList = $("#ParentGrid").data("kendoTreeList");
if (treeList) {
treeList.dataSource.bind("requestEnd", function (e) {
if (e.response) {
if (e.type === "create") {
console.log("call requestEnd type: create");
treeList.dataSource.read(); // Refresh immediately
} else if (e.type === "update") {
console.log("call requestEnd type: update");
setTimeout(function () {
treeList.dataSource.read(); // Refresh after 1 second
}, 200); // 1000 milliseconds = 1 second
}
}
});
}
});
function onDragEnd(e) {
var draggedItem = e.source; // The dragged item
var newParent = e.destination; // The new parent (if changed)
var newOrder = e.position; // The new order in the parent
// Prepare data for backend
var updateData = {
sourceId: draggedItem.id,
destId: newParent ? newParent.id : null,
destParentId: newParent ? newParent.id : null,
//sourceItemId = draggedItem.ItemId,
//destItemId = newParent ? newParent.ItemId : null,
order: newOrder
};
// Make an AJAX call to update the hierarchy/order in the backend
$.ajax({
url: "/ParentChild/Reorder", //"/ParentChild/Reorder",
type: "POST",
data: { //{destId: updateData.destId, sourceId: updateData.sourceId, order: updateData.order},
destId: e.destination.Id,
sourceId: e.source.Id,
destParentItemId: e.destination.ParentItemId,
order: e.position
},
//contentType: "application/json",
success: function () {
// Optionally refresh the TreeList
$("#ParentGrid").data("kendoTreeList").dataSource.read();
},
error: function () {
$("#ParentGrid").data("kendoTreeList").dataSource.read();
alert("Reorder failed (Can't make child asset as parent)");
}
});
console.log("Drag operation ended!", e);
}
// Initialize ParentGrid rows as drop targets
window.initializeDropTargets = function () {
var draggedItem = null;
// Make Rows Draggable
$("#AssetGrid").on("mousedown", "tr", function () {
var grid = $("#AssetGrid").data("kendoGrid");
var dataItem = grid.dataItem($(this));
draggedItem = dataItem; // Track the dragged item's data
console.log("AssetGrid -> mousedown", draggedItem);
});
// Track dragged item from ParentGrid
$("#ParentGrid").on("mousedown", "tr", function () {
var parentGrid = $("#ParentGrid").data("kendoTreeList");
draggedItem = parentGrid.dataItem($(this));
console.log("ParentGrid -> mousedown", draggedItem);
});
$("#ParentGrid").kendoDropTargetArea({
filter: "tbody tr",
group: "assetGroup", // Match the draggable group
drop: function (e) {
var parentGrid = $("#ParentGrid").data("kendoTreeList"); // Get the Kendo Grid instance
var dropTargetRow = $(e.dropTarget); //.closest("#ParentGrid tr.k-table-row.k-master-row"); // The row where the item was dropped
var targetItem = parentGrid.dataItem(dropTargetRow); // Target row data
console.log("Dragged Item:", draggedItem.Id);
console.log("Drop Target:", e.dropTarget);
console.log("Drop Target Row:", dropTargetRow);
console.log("Target Item:", targetItem.Id);
if (targetItem && draggedItem) {
//alert("Item '" + draggedItem.Title + "' dropped on Parent '" + targetItem.Name + "'");
// Add AJAX call here to save assignment in the database
$.ajax({
url: "/ParentChild/AssignAsset",
method: "POST",
data: { parentId: targetItem.Id, itemId: draggedItem.Id, parentItemId: targetItem.ParentItemId },
success: function (response) {
parentGrid.dataSource.read();
$("#AssetGrid").data("kendoGrid").dataSource.read();
console.log("AssignAsset ended from kendoDropTargetArea -> drop");
//parentGrid.refresh();
//alert("Assignment successful!");
},
error: function () {
alert("Error while assigning asset (Can't assign children to child asset).");
}
});
}
},
dragend: function (e) {
var draggedItem = e.source; // The dragged item
var newParent = e.destination; // The new parent (if changed)
var newOrder = e.destinationIndex; // The new order in the parent
// Prepare data for backend
var updateData = {
id: draggedItem.id,
parentId: newParent ? newParent.id : null,
order: newOrder
};
// Make an AJAX call to update the hierarchy/order in the backend
$.ajax({
url: "/ParentChild/Reorder",
type: "POST",
data: JSON.stringify(updateData),
contentType: "application/json",
success: function () {
// Optionally refresh the TreeList
$("#TreeList").data("kendoTreeList").dataSource.read();
console.log("AssignAsset ended from kendoDropTargetArea -> dragend -> Reorder");
},
error: function () {
alert("Reorder failed");
}
});
}
});
$("#AssetGrid").kendoDropTarget({
filter: "tbody tr",
group: "gridGroup", // Match the draggable group
drop: function (e) {
var parentGrid = $("#ParentGrid").data("kendoTreeList"); // Get the Kendo Grid instance
var dropTargetRow = $(e.dropTarget); //.closest("#ParentGrid tr.k-table-row.k-master-row"); // The row where the item was dropped
var targetItem = parentGrid.dataItem(dropTargetRow); // Target row data
console.log("Dragged Item:", draggedItem.Id);
console.log("Drop Target:", e.dropTarget);
console.log("Drop Target Row:", dropTargetRow);
console.log("Target Item:", targetItem.Id);
if (targetItem && draggedItem) {
//alert("Item '" + draggedItem.Title + "' dropped on Parent '" + targetItem.Name + "'");
// Add AJAX call here to save assignment in the database
$.ajax({
url: "/ParentChild/UnAssignAsset",
method: "POST",
data: { parentId: targetItem.Id, itemId: draggedItem.Id, parentItemId: targetItem.ParentItemId },
success: function (response) {
parentGrid.dataSource.read();
$("#AssetGrid").data("kendoGrid").dataSource.read();
console.log("AssignAsset ended from kendoDropTargetArea -> drop");
//parentGrid.refresh();
//alert("Assignment successful!");
},
error: function () {
alert("Error while assigning asset (Can't assign children to child asset).");
}
});
}
}
});
};
$(document).ready(function () {
// Make rows in the AssetGrid draggable
$("#AssetGrid").kendoDraggable({
filter: "tbody > tr", // Target rows in the grid
hint: function (element) {
return $("<div class='k-card k-card-type'><b>" + $(element).find("td:nth-child(2)").text() + "</b></div>");
},
group: "assetGroup"
});
var treeList = $("#ParentGrid").data("kendoTreeList");
// Configure drag-and-drop from TreeList to Grid
treeList.wrapper.kendoDraggable({
filter: "tr",
hint: function (element) {
var item = treeList.dataItem(element);
console.log("treeList.wrapper.kendoDraggable -> ", item);
return element;
},
group: "gridGroup"
});
window.initializeDropTargets();
});
Hello,
create/update posts an empty model to the controller.
It was working in a very old asp.net mvc project. I setup a new asp.net core project. I spent some hours to fix this, but no luck.
Reading the data source is ok and the data is shown in column 'valuestream'. At the moment for 'Agenda' two values are shown, editable with a mutiselect.
Controller:
public ActionResult ManagerQuestionnaireCreate([DataSourceRequest] DataSourceRequest request, QuestionnaireViewModel rs)
{
....
return Json(new[] { rs }.ToDataSourceResult(request, ModelState));
}
Model:
View:
Prior to the most recent version we could use reflection to get the grid name in this method.
We have changed it to pass the grid name, but was wondering if there is a programmatic way of getting the grid name without passing it
public static GridToolBarCommandFactory<T> SuperSearch<T>(this GridToolBarCommandFactory<T> builder, string gridName, string title = "Super Search...") where T : class