Kendo UI for MVC: Rendering a Grid in a PanelBar - asp.net-mvc-4

MVC 4. When I place a Grid inside a Kendo UI PanelBar it does not work as expected. The View ends up not putting the Grid in the Content(), but rather itself into the panel over and over again recursively forever.
#(Html.Kendo().PanelBar()
.Name("IntroPanelBar")
.Items(items =>
{
items.Add()
.Text("papering Reports")
.Selected(true)
.Expanded(true)
.Content(() => Html.RenderAction("Grid"));
To see if it's my code, I put the Grid outside of the PanelBar and everything renders fine with the gird outside the PanelBar :
#{
Html.RenderAction("Grid");
}
#(Html.Kendo().PanelBar()
.Name("IntroPanelBar")
.Items(items =>
{
items.Add()
.Text("papering Reports")
.Selected(true)
.Expanded(true)
.Content("PLAIN TEXT");

I know this is an older question but it popped up when I searched a similar problem. It could be solved by using the Razor helper function. My example shows a Panel with a tab strip that contains a grid.
<div id="panel">
#(Html.Kendo().PanelBar()
.Name("panelbar")
.ExpandMode(PanelBarExpandMode.Single)
.Items(panelbar =>
{
foreach (var a in Model) {
panelbar.Add().Text(a.dom.fileName)
.Content(#<div id="tabs">
#RenderTabStrip(a)
</div>
);
}
})
)
#helper RenderTabStrip(DominguezReport.WebInterface.Models.accModelTest a)
{
#(Html.Kendo().TabStrip()
.Name("tabs" +a.dom.recordID)
.Items(tabstrip =>
{
tabstrip.Add()
.Text("Status")
.Content(#<div>#RenderStatusGrid(a)</div>);
tabstrip.Add()
.Text("Errors")
.Content(#<div>#RenderErrorGrid(a)</div>);
})
);
}
#helper RenderStatusGrid(DominguezReport.WebInterface.Models.accModelTest a)
{
#(Html.Kendo().Grid(a.drs)
.Name("Status")
.Columns(columns=>
{
columns.Bound(c => c.currentStatus);
columns.Bound(c => c.updateTime);
})
.Scrollable()
)
}
#helper RenderErrorGrid(DominguezReport.WebInterface.Models.accModelTest a)
{
#(Html.Kendo().Grid(a.dre)
.Name("Errors")
.Columns(columns =>
{
columns.Bound(c => c.errorType);
columns.Bound(c => c.errorDetail);
columns.Bound(c => c.updateTime);
})
.Scrollable()
)
}

I tried the below code and it worked. Enclose your grid code in <div> tag in the Content part of PanelBar.
#(Html.Kendo().PanelBar()
.Name("panelbar")
.ExpandMode(PanelBarExpandMode.Single)
.Items(panelbar =>
{
panelbar.Add().Text("Devices")
.Expanded(true)
.Content(#<div>#(Html.Kendo().Grid(Model)
...grid code here
</div>
);
})
)

The solution is to use the MVCHtmlString output of the Action instead:
#(Html.Kendo().TabStrip()
.Name("tabstrip")
.Items(tabstrip =>
{
tabstrip.Add().Text("papering")
.Selected(true)
.Content(Html.Action("Grid").ToHtmlString()); <---

Related

Kendo MVC Group Paging

I have a kendo grid that shows around more than a million records and in its initial load, it takes more than a minute to display.
how can I use the kendo Grouppaging feature to minimize the load time so the page loads the group items on demand? Loading of the group items happens when a group is expanded. Any other options to speed up are also appreciated.
what it basically does is that based on the dropdown value it draws the kendo grid
<div>
#(Html.Kendo().DropDownList()
.Name("samplegrid")
.DataTextField("samplegrid")
.DataValueField("samplegrid")
.HtmlAttributes(new { style = "width:90%" })
.DataSource(source => source
.Custom()
.Transport(transport => transport
.Read(read =>
{
read.Action("infoDropdown_Read",
"sample").Type(HttpVerbs.Get);
})))
.Events(e =>
{
e.Select("onCheckSelectForDetail");
})
)
</div>
Here is the code for the Grid.
#(Html.Kendo().Grid<Portal.Data.Models.InfoModel>()
.Name("gridSummary")
.DataSource(dataSource => dataSource
.Ajax()
.Aggregates(aggregates =>
{
aggregates.Add(p => p.OutstandingCount).Sum();
})
.Group(groups =>
{
groups.Add(p => p.OfficeNumber);
})
.Batch(true)
.ServerOperation(false)
.Sort(sort => sort.Add(column => column.Date))
)
.Columns(columns =>
{
columns.Bound(c => c.OfficeState).Width(70)
.Title("xxxx");
columns.Bound(c => c.OfficeNumber).Width(70)
.Title("zzzz");
columns.Bound(c => c.OutstandingCount).Width(60)
.Title("yyyy");
})
)
and the controller looks like
public async Task<IActionResult> infoDropdown_Read(){
try{
var infoListSR = await _eService.GetInfoListAsync();
if (infoListSR.Failed){
Log.Error($"Unexpected error occured due to
{infoListSR.ErrorData.ApplicationErrorMessage}");
throw new DataException($"{infoListSR.ErrorData.ApplicationErrorMessage}");
}
return Json(infoListSR.ResultData, new JsonSerializerOptions() {
PropertyNameCaseInsensitive = false});
}
catch (Exception ex){
Log.Error($"Username: {User.Identity.Name} - Dropdown list Failed with
Exception: {ex}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
An option to boost the performance, you could use the server grouping along with virtualization:
Demo

CellTemplate and ContentTemplate not rendering properly in Devextreme ASP.NET Core

I have a datagrid, where for each item on the table I need to attach one or many documents. When you click the last column button, you should open a popup which then has the file uploader.
I'm trying to create the custom button in my Datagrid, which will open the custom popup that has the FileUploader widget, but the button is not rendering at all.
Instead of the button showing, this is the result.
\[%!function(){%\]\ [%DevExpress.aspnet.createComponent("dxButton",{"text":"Attach","onClick":function (e) { attachButtonClick(data) }},arguments\[0\])%\]\[%}("dx-" + new DevExpress.data.Guid())%\]
I'm imagining the same will happen even if the popup shows. Just this text which would seem to represent the file uploader.
This is my .chtml code for this part.
#(Html.DevExtreme().DataGrid<myModel>()
.ID("dataGrid")
.DataSource(ds => ds.Mvc().Controller("DataGridMaterials")
.LoadAction("Get")
.InsertAction("Insert")
.UpdateAction("Update")
.DeleteAction("Delete")
.Key("ID")
)
.Columns(columns => {
columns.AddFor(m => m.Equipment);
columns.AddFor(m => m.Client);
columns.AddFor(m => m.Number);
columns.AddFor(m => m.Address);
columns.AddFor(m => m.Phone);
columns.Add().Width(160).Alignment(HorizontalAlignment.Center).CellTemplate(#<text>
#Html.DevExtreme().Button().Text("Attach").OnClick("function (e) { attachButtonClick(data) }")
</text>);
})
.OnRowDblClick(#<text>
function MyHandler(selectedItem) {
var dataGrid = $("#dataGrid").dxDataGrid("instance");
var selectedRowsData = dataGrid.getSelectedRowsData();
var allData = selectedRowsData[0];
var id = allData.ID;
console.log(id);
$('#customPopup').dxPopup('instance').option('visible', true);
}
</text>)
.RowAlternationEnabled(true)
.Editing(editing => {
editing.Mode(GridEditMode.Row);
editing.AllowUpdating(true);
editing.AllowDeleting(true);
editing.AllowAdding(true);
})
.Selection(s => s.Mode(SelectionMode.Single))
.RemoteOperations(true)
)
#(Html.DevExtreme().Popup().ID("customPopup").Width(660).Height(540).Title("Attachments").Visible(false)
.ContentTemplate(#<text>
#(Html.DevExtreme().FileUploader()
.ID("file-uploader")
.Name("myFile")
.Multiple(true)
.Accept("*")
.UploadMode(FileUploadMode.UseButtons)
.UploadUrl(Url.Action("Upload", "FileUploader"))
.OnValueChanged("fileUploader_valueChanged")
)
</text>)
)
I based my solution on this sample app.
View
Custom popup
It's strange, I follow the sample codes you provide and it can work on my side. I am using Asp.net core 3.1 and Devextreme 20.1:
#model Order
#{
ViewBag.Title = "Index";
}
<h2>Home</h2>
#(Html.DevExtreme().DataGrid<Order>()
.ID("gridContainer")
.ShowBorders(true)
.DataSource(d => d.Mvc().Controller("Orders").LoadAction("Get").Key("OrderID").UpdateAction("Put"))
.Columns(columns => {
columns.AddFor(m => m.CustomerName);
columns.AddFor(m => m.OrderDate);
columns.AddFor(m => m.ShipCity);
columns.Add().Width(160).Alignment(HorizontalAlignment.Center).CellTemplate(#<text>
#Html.DevExtreme().Button().Text("Attach").OnClick("function (e) { attachButtonClick() }")
</text>);
})
.Selection(s => s.Mode(SelectionMode.Single))
.RemoteOperations(true)
)
#(Html.DevExtreme().Popup().ID("customPopup").Width(660).Height(540).Title("Attachments").Visible(false)
.ContentTemplate(#<text>
#(Html.DevExtreme().FileUploader()
.ID("file-uploader")
.Name("myFile")
.Multiple(true)
.Accept("*")
.UploadMode(FileUploadMode.UseButtons)
.UploadUrl(Url.Action("Upload", "FileUploader"))
)
</text>)
)
<script>
function attachButtonClick() {
$('#customPopup').dxPopup('instance').option('visible', true);
}
</script>

kendodropdownlist not binding value to model after post

I'm using kendo UI for my project. I have a kendo dropdownlist that I'm populating with json. I get the values in my dropdownlist but on post, the model doesn't get the selected value of the dropdownlist. I have been stuck on it for a day with no result. I'm not sure where I'm going. Please review the code
View:
#model IEnumerable<EntityFrameworkClasses.StaggingException>
#foreach (var item in Model)
{
#(Html.Kendo().DropDownListFor(modelItem => item.Level2)
.Name("Level2")
.HtmlAttributes(new { style = "width:10%" })
.OptionLabel("Select level 2...")
.DataTextField("Text")
.DataValueField("Value")
.BindTo((System.Collections.IEnumerable)ViewBag.Level2)
)
}
#(Html.Kendo().Grid(Model)
.Name("CashExceptionsGridTest")
.Columns(columns =>
{
columns.Bound(p => p.Category).Title("Category").Width(130);
columns.Bound(p => p.EnterText1).Title("Comments").Width(130);
columns.Bound(p => p.Dateoftransaction).Title("Date").Width(130);
columns.Bound(p => p.InternalLocalAmount).Title("InternalAmt").Width(130);
columns.Bound(p => p.ExternalLocalAmount).Title("ExternalAmt").Width(130);
})
.ToolBar(toolbar =>
{
//toolbar.Template("<a class='k-button k-button-icontext' onclick='customCommand()' href='#'></span>Cutom Command</a>");
toolbar.Create(); // The "create" command adds new data items.
toolbar.Save();// The "save" command saves the changed data items.
})
.Editable(editable => editable.Mode(GridEditMode.InCell)) // Use in-cell editing mode.
.HtmlAttributes(new { style = "height: 550px;" })
.HtmlAttributes(new { style = "height: 350px;" })
.Pageable(pageable => pageable
.Input(true)
.Numeric(false)
)
.Reorderable(r => r.Columns(true))
.Sortable()
.ColumnMenu()
.Scrollable(scr => scr.Height(430))
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.ServerOperation(false)
.Batch(true) // Enable batch updates.
.Model(model =>
{
model.Id(p => p.RowID); // Specify the property which is the unique identifier of the model.
model.Field(p => p.RowID).Editable(false); // Make the ProductID property not editable.
})
.Update("Editing_Update", "MultiTab")
.Create("Editing_Create", "MultiTab")
)
)
}
I have a kendo grid below which im not including for code brevity.
Controller:
public ActionResult GetLevel()
{
IEnumerable<SelectListItem> Level2 = db2.StaggingInternalCashExceptions.Where(x=>x.LoadID==loadid).Select(c => new SelectListItem
{
Value = c.Level2.ToString(),
Text = c.Level2
}).Distinct();
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Editing_Create([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<StaggingException> results)
if (results != null && ModelState.IsValid)
{
foreach (var result in results)
var entity = new StaggingException();
entity.RowID = result.RowID;
entity.Category = result.Category; //this is a textbox in the view for which i get the value
entity.Level1 = result.Level1; //gives null
//I'm adding those values to the db. Didn't include all that for the sake of keeping it short.
}
}
The grid has batch editing, once i hit on save changes, the grid's data is posted to the controller where i can see it in results. I cannot get the dropdown value though.
Any ideas or leads please.
Thank you.
Late to this post but I have had a similar issue, for those with the same problem of the value not being posted in the model, if your model value is a nullable int? (can't see from the above post...) then you need to configure the DropDownListFor as below to avoid the default value binding behavior to update the field with the selected item when the initial value is null. Hope this helps someone.
Html.Kendo().DropDownListFor(m => m)
.HtmlAttributes(new { data_value_primitive = "true" })

Kendo MVC treeview Passing selected node to grid

I'm new to Kendo, I just trying to pass the selected node of treeview to the grid, this is my code:
<div>
#(
Html.Kendo().TreeView()
.Name("treeview")
.BindTo((IEnumerable<TreeViewItemModel>)ViewBag.TreeData)
.Events(events => events
.Select("onSelect")).ExpandAll(true)
)
</div>
#(Html.Kendo().Grid<DocunetViewer.Models.MyModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.ID);
columns.Bound(c => c.Name);
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("GetData", "Home").Data("getParameter")))
and this is the script:
<script>
function onSelect(e) {
BindGrid();
}
function BindGrid() {
$("#grid").data("kendoGrid").dataSource.read();
$("#grid").data("kendoGrid").refresh();
}
function getParameter() {
var treeview = $("#treeview").data("kendoTreeView");
var selectedNode = treeview.select();
var id = -1;
if (selectedNode.length != 0) {
var item = treeview.dataItem(selectedNode);
id = item.id;
}
return {
myId: id
};
}
my problem is that I always get the previous selected node not the current selected node, so what is the problem? and how can I solve it?
Thanks in advance.
In your onSelect method, you can get at the node with some JavaScript like this.
var node = ($(e.node));
and here I'm getting the id attribute of the node (your node may have different things on it).
var id = ($(e.node).data("id"));

fill kendo combo box parameter

I have a kendo combobox Clients, and I fill his content with
.DataSource(
source =>
{
source.Read(read => { read.Action("GetAllClientsJSONCombo", "CrmCProfile"); });
})
Now, I have another kendo combobox ContactsClient, but I need pass the Id of the selected client in first combobox, like this:
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetAllContactsClientJSONCombo", "CrmCProfile", new object { Id_Cliente = (????????)});
})
.ServerFiltering(false);
})
Thanks.
It is fine if you dont write new object just specify the word new
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetAllContactsClientJSONCombo", "CrmCProfile", new { Id_Cliente = Model.Value});
})
.ServerFiltering(false);
})
OR
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetAllContactsClientJSONCombo", "CrmCProfile").Data("yourParameters");
})
.ServerFiltering(false);
})
<script>
function yourParameters(){
return {"Id_Cliente": yourParameterValue};
}
</script>
And make sure that on the server side, the name of the parameter (i.e, Id_Cliente) is same.
public JsonResult GetAllContactsClientJSONCombo(string Id_Cliente){
//your logic here
}