KendoUI Grid custom footer using two or more column with MVC wrapper - kendo-ui

I have a Kendo Grid and want to use two column to crete a ClientFooterTemplate (Value2).
So, I have :
#(Html.Kendo().Grid<MyGridDto>().Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.Value1)
.ClientFooterTemplate("#= sum #");
columns.Bound(p => p.Value2);
.ClientFooterTemplate ( HERE I WANT TO GET SUM OF VALUE3 / SUM VALUE 2)
columns.Bound(p => p.Value3).Visible(false);
}
.DataSource(dataSource => dataSource
.Ajax()
.Aggregates(aggregates =>
{
aggregates.Add(p => p.Value1).Sum();
aggregates.Add(p => p.Value2).Sum();
aggregates.Add(p => p.Value3).Sum();
})
.Read(read => read.Action("List", "MyController)) )
)
MyGridDto
public class MyGridDto
{
public decimal Value1 { get; set; }
public decimal Value2 { get; set; }
public decimal Value3 { get; set; }
}
I want to show the Value2 footer using sum of Value3 / Sum of Value2. How can I do that?
Thanks

You can achieve this by getting the value of the ValueComputed into a temp variable on datasource request end and adding the footer row in as below:
<div class="k-grid k-widget">
<table class="k-focusable" id="totals" >
<tr>
<td/>
<td/>
<td>
Total price: <span data-bind="text: priceTotal" />
</td>
</tr>
</table>
</div>
Please see the below example for more info:
Kendo UI Grid With Table Footer by Darren Bell
You might need to create the Data Source sepearately and will have to bind viewmodel once Data Source is created.
EDIT:
As per your update, I have created an working sample for your reference using same logic as per the previous table footer example. Please find the working example at below link:
Kendo UI Grid Custom Calculated Footer
Do let me know if this is not what you are looking for!
Edit 2:
Client Footer only

Related

Kendo Grid: Toolbar template issue

I have a grid that lists Road information and want a Toolbar Template that will allow me to filter the roads by choosing a Concession from a DropDownList. Something like this
My code:
CSHTML
<div id="datagrid">
#(Html.Kendo().Grid<SustIMS.Models.RoadModel>()
.Name("datagrid_Roads")
.Columns(columns =>
{
columns.Bound(r => r.RoadCode).Title(ViewBag.lblCode).Width(140);
columns.Bound(r => r.RoadType).Title(ViewBag.RoadType).Width(140);
columns.Bound(r => r.RoadMediumDescription).Title(ViewBag.lblDescription);
columns.Bound(r => r.ConcessionCode).Title("CCode").Hidden();
columns.Bound(r => r.ConcessionMediumDescription).Hidden().Title(ViewBag.Concession);
})
.ToolBar(toolbar =>
{
toolbar.Template(#<text>
<div class="toolbar">
<label class="category-label" for="category">Concessão:</label>
#(Html.Kendo().DropDownList()
.Name("concessions")
.OptionLabel("All")
.DataTextField("ConcessionMediumDescription")
.DataValueField("CCode")
.AutoBind(false)
.Events(e => e.Change("concessionChange"))
.DataSource(ds =>
{
ds.Read("ConcessionFiltering", "MasterData");
})
)
</div>
</text>);
})
.HtmlAttributes(new { style = "height: 534px;" })
...
)
)
</div>
<script type="text/javascript">
function concessionChange() {
var value = this.value(),
grid = $("#datagrid_Roads").data("kendoGrid");
if (value) {
grid.dataSource.filter({ field: "ConcessionMediumDescription", operator: "eq", value: value });
} else {
grid.dataSource.filter({});
}
}
Controller
public ActionResult ConcessionFiltering()
{
ConcessionModel cm = new ConcessionModel();
var aux = cm.getConcessions();
return Json(aux.concessions.Select(c => c.concession.mediumDescription).Distinct(), JsonRequestBehavior.AllowGet);
}
This is the current result:
The list is filled with the word "undefined" 16 times, which is the number of concessions I currently have. When I select one of the undefined options, it shows the actual name of the concession, refreshes the grid but doesn't filter it.
I want the list to show the concession names and to filter the grid by concession as I select one of them. What am I missing?
change this
return Json(aux.concessions.Select(c => c.concession.mediumDescription).Distinct(), hJsonRequestBehavior.AllowGet);
to
return Json(aux.concessions.Select(c => new ConcessionModel { Description = c.concession.mediumDescription }).Distinct(), JsonRequestBehavior.AllowGet);
First, double check what Json you are returning from the controller method. It looks like your ConcessionMediumDescriptions may have no data in them.
Second, it looks like, in your controller, that you are returning a list of "ConcessionMediumDescription" data objects.
I am guessing it looks like this...
{ConcessionMediumDescription: {
CCode: 'mycode',
...
}
}
You may consider returning a title field as a part of this Json and to use that for the text field of your dropdown. This is just me guessing from what you are returning in that controller.
Ideal Json would be somting like this...
[{
{{id: 'id1'},{text: 'text1'}},
{{id: 'id2'},{text: 'text2'}}
}]
And you defind your dropdown as such.
.DataTextField("text")
.DataValueField("id")
You have to do json return line like this.
return Json(aux.concessions.Select(c => new { Value = c.concession.DATAVALUE, Text = c.concession.DATATEXT }), JsonRequestBehavior.AllowGet);
Just change DATAVALUE and DATATEXT

MVC 5 Conditional Validation Option?

I'm developing an MVC 5 web application. Within a particular View I need to validate a ViewModel, however, I need some of the validation only to occur depending on the users inpupt.
For example, I have a ViewModel
public class TimeEntryViewModel
{
public int proposalID { get; set; }
public int proposalCode { get; set; }
public int nonchargeCode { get; set; }
public SelectList UserProposals { get; set; }
public SelectList TimeEntryClientCodes { get; set; }
public SelectList TimeEntryNonChargeCodes { get; set; }
}
This ViewModel is passed to a View which looks like this
<div class="form-group">
#Html.LabelFor(m => m.proposalID, "Proposal")
#Html.DropDownListFor(m => m.proposalID, Model.UserProposals, "No Proposal", new { #class = "form-control"})
#Html.ValidationMessageFor(m => m.proposalID)
</div>
<div id="ClientCodes" class="form-group" style="display:none">
#Html.LabelFor(m => m.proposalCode, "Client")
#Html.DropDownListFor(m => m.proposalCode, Model.TimeEntryClientCodes, "Select", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.proposalCode)
</div>
<div id="NonChargeCodes" class="form-group">
#Html.LabelFor(m => m.nonchargeCode, "Non Charge")
#Html.DropDownListFor(m => m.nonchargeCode, Model.TimeEntryNonChargeCodes, "Select", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.nonchargeCode)
</div>
If the user selects 'No Proposal' from the first drop down list, then the drop down list 'nonchargeCode' appears and I need to validate so that the user selects an option from it.
However, if the user selects another option from the first down drop list, then the drop down list 'nonchargeCode' will disappear and another drop down called 'proposalCode' will appear. I then want to validate to ensure the user selects an option from this drop down, but not the 'nonchargeCode' (which will be hidden).
In an MVC 4 application I previously coded, I used http://fluentvalidation.codeplex.com/ to help with this scenario.
I'm just wondering if anyone else had used anything else to overcome this problem of conditional validation? If so, I'd be keen to hear.
Thanks again.
You can use conditional validation in jQuery and in fluentvalidation.
You can use a jQuery selector on the validation, something like this.
I'm not sure about the HTML element names.
$( "#myform" ).validate({ rules: {
proposalCode: {
required: "#proposalCode:visible"
} }
Check out jQuery Dependency expression for more information.
In FluentValidation validation (Server side only) you can use the 'When' expression.
RuleFor(r => r.proposalCode).NotNull().When(e => // Check selected value);
Check out the documentation here
I think this should get you started.

Telerik MVC Grid in Razor view, GridCommand not populating

I have a telerik mvc grid in a Razor view. I am using custom server binding. My issue is that on paging and sorting the GridCommand object properties "Page", "PageSize" & "SortDescriptors" are not getting the correct value. The funny thing is that the exact same code works for an aspx view. Since this is a new view, I have started using "Razor".
My view is -
#(Html.Telerik().Grid((IEnumerable<Mitek.MobileImaging.AdminSite.Models.ImagingTransactionModel>)ViewData["DeficientGridView"])
.Name("DeficientImagesGrid")
.DataBinding(databinding => databinding.Server()
.Select("ViewDeficientImages", "SuperAdmin", new { orgId = ViewData["OrgId"], beginDate = ViewData["BeginDate"], endDate = ViewData["EndDate"], searchString = ViewData["SearchString"] }))
.DataKeys(keys => keys.Add(o => o.TranId))
.EnableCustomBinding(true)
.BindTo((IEnumerable<Mitek.MobileImaging.AdminSite.Models.ImagingTransactionModel>)ViewData["DeficientGridView"])
.Columns(
columns =>
{
columns.Template(
#<text>
<a href="#Url.Action("DeficientImageDetails", "SuperAdmin", new { id = item.TranId }) ">
<img alt="Deficient Image Details" src= "#Url.Content("~/Content/ImagesUI/detail_icon.gif")" style="border:0px" /></a>
</text>
).Title("Actions").Width(75);
columns.Bound(o => o.TranId).Hidden(true);
columns.Bound(o => o.user_email).Title("User Email").Width(250);
columns.Bound(o => o.xml_config_name).Title("Job File").Width(200);
columns.Bound(o => o.datetime_created).Title("Date Created").Format("{0:MM/dd/yyyy}").Width(200);
columns.Bound(o => o.short_note).Title("Note").Width(200);
columns.Bound(o => o.iqa_code).Title("IQA Code").Width(200);
}).HtmlAttributes(new { style = " font-family:arial; font-size: .9em; " })
.Sortable()
.Pageable(paging => paging.Position(GridPagerPosition.Bottom)
.Style(GridPagerStyles.NextPreviousAndNumeric)
.Total((int)ViewData["DeficientImagesCount"])
.PageSize(25))
)
The controller looks like
[GridAction(GridName = "DeficientGridView")]
public ActionResult ViewDeficientImages(DeficientImagesViewModel model, GridCommand command, string button)
{
//Some Code......;
GridCommand myCommand = new GridCommand() { PageSize = 25 };
}
The command object never has any values for command.Page, command.SortDescriptors at the time of paging or sorting. Please note that the exact same code works in a asps page.
Please help.
Thanks,
SDD
Can you check if it has to do with [GridAction(GridName = "DeficientGridView"] attribute and your grid name being different.Name("DeficientImagesGrid") ?
You have to change [GridAction(EnableCustomBinding = true, GridName = "DeficientImagesGrid")] to this. I have the same problem today and i found this is working. If you don't specify the GridName then you will not get GridCommand.
gridCommand is NOT populated when the query string parameters are QueueGrid-size=2&QueueGrid-page=3
gridCommand is populated when the query string parameters are size=2&page=3

How to set Id for EditorFor() html helper in asp .net MVC3

I used this to override framework generated id #Html.EditorFor(model => model.cost, new { id = "checkCost" })But unfortunately id is not changing. i.e When i use string d = Request.Form["checkCost"];
at controller action then string filled with null value.WHY?? I also replaced EditorFor with TextBoxFor but nothing changed then also controller takes cost as ID
<td >
#Html.DropDownList("check_master", "--select package--")
</td>
<td >
#Html.EditorFor(model => model.check_name)
#Html.ValidationMessageFor(model => model.check_name)
</td>
<td >
#Html.EditorFor(model => model.cost, new { id ="checkCost" })
#Html.ValidationMessageFor(model => model.cost)
</td>
Updated:
This is my partial view and my main view(rendering partial from ajax.actionLink) also hold a EditorFor(model=>mode.cost)
Partial view is strongly typed to Check_master table and main view is strongly typed to package_master where both entitySet hold same name property i.e "COST" Secondly both partial and main view hold EditorFor "cost"I tried to change the name of check_master property like by
[Column("check_cost")]
public Nullable cost { get; set; }But dont know why this is not working i.e property naem is not changing while referring it like
model.something
Create 2 view models with properties CheckCost and PackageCost that way there's a seperation:
public class CheckViewModel{
public string CheckCost{get;set;}
}
public class PackageViewModel{
public string PackageCost{get;set;}
}
This way avoid conflicts.
To specifically answer the question asked, try this:
#Html.EditorFor(model => model.cost, new { #id = "checkCost" })
Note the slight (but important) difference: ... new { #id = "checkCost" })

Bound column to a list and loop...Is it possible at all?

I'm a novice Telerik Grid user and was wondering if it is a possibility to use Telerik Grid such that I bound one column to a string array and then somehow loop through it to show the array items as list.
StoreViewModel:(One store can have multiple displays)
public string Name { get; set; }
public string[] StoreDisplays { get; set; }
Controller:
private IQueryable<StoreViewModel> GetRetailers()
{
var stores = from sg in db.Store
select new RetailerViewModel
{
Name = sg.sg_Name,
Name = sg.sg_Name,
StoreDisplays = ( from ca in db.Categories.Where(item => item.c_ParentId == null)
join sd in db.StoreDisplays.Where(item => item.sd_StoreGroupId == sg.sg_Id)
on ca.c_Id equals sd.sd_CategoryId into gj
from subpet in gj.DefaultIfEmpty()
select (ca.c_Name)).ToArray<string>()
};
return stores;
}
Index.aspx
<%= Html.Telerik().Grid<StoreLocatorBackOffice.Models.RetailerViewModel>(Model) <br/>
.Name("Grid")
.Columns(columns =>
{
columns.Bound(sg => sg.Name)
columns.Bound(sg => sg.StoreDisplays);
})
.DataBinding(dataBinding => dataBinding
.Ajax()
.Select("_Index", "Retailer", true)
)
.Scrollable(scrolling => scrolling.Enabled(false))
.Sortable(sorting => sorting
.OrderBy(sortOrder => sortOrder.Add(p => p.Name).Ascending()))
.Pageable(settings => settings.PageSize((int)ViewData["pageSize"]))
.Filterable(filtering => filtering.Enabled(true))
.Footer(true)
%>
Currently it Displays like this.
Name Store Display
Store#1 Display#1Display#2Display#6
Store#2 Display#3Display#9
And want to some how show it as follows.
Name Store Display
Store#1 Display#1
Display#2
Display#6
Store#2 Display#3
Display#9
Instead of:
columns.Bound(sg => sg.StoreDisplays);
You should bind using a template. That template can be whatever you want, (even another grid).
Here's a template that will put an image in:
columns.Template(c => {
%>
<img
alt="<%= c.CustomerID %>"
src="<%= Url.Content("~/Content/Grid/Customers/" + c.CustomerID + ".jpg") %>"
/>
<%
});
Changing that template to display a list should be simple.
Look here for more info.
I would use HTML tags in to make data to spread vertically
For example
StoreDisplays = "
<ul>
<li>Display#1</li>
<li>Display#2</li>
<li>Display#3</li>
</ul>";
.Columns(columns =>
{
columns.Bound(o => o.StoreDisplays).ClientTemplate("<#= StoreDisplays #>");
}

Resources