Kendo grid MVC number link column sorting - asp.net-mvc

I have a Kendo grid on a MVC .cshtml view page:
#model IEnumerable<Models.GetItems>
<script>
$(document).ready(function () {
$("#grid").kendoGrid({
sortable: true
});
});
</script>
<table class="table" id="grid">
<thead>
<tr>
<th data-field="Quantity">
Qty
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.ActionLink(item.Quantity.ToString(), "kendo", "Groups", new { ID = item.ID }, null)
</td>
</tr>
}
</tbody>
</table>
It displays the way I want; as a number with a link to a drill down page, but the sorting doesn't work at all.
How can I tell the grid I want the data type to be a number so it can sort it like a number?
(item.Quantity is Int16 from the model, but had to make it a string for the ActionLink to work)
(I'm open to binding the grid differently if I have to (bind to json output from controller and/or use rowTemplate and/or bind to empty div and define columns in JS possibly with template), but not sure at this point if that will matter, seems like a data type issue regardless of binding method???)

Related

jQuery datatable pagination not working with mvc view

I'm working on an MVC application. The table data is returned as a view from the controller. After binding the rows in the razor view, I'm initializing the datatable. The no. of rows returned is 50.
The issue is, the datatable displays all the 50 records and hence there is no pagination. I would like it to show only 10 records per page and then paginate.
Also, I do not want to get the data page by page. The total count, which is 50 in this case, is decided by the end user. That's the main reason, I choose datatables as it provides sorting, search & pagination with no coding.
So, does the pagination feature work if the data is bound to DOM and then initialized. If not, what is the best way to do it.
Here is the code:
#model ResultOutput
<table class="tblKeyMetrics" role="grid">
<thead>
<tr role="row">
<th class="">Value</th>
<th class="">Impressions</th>
</tr>
</thead>
#if (Model.KeyMetrics != null && Model.KeyMetrics.Count > 0)
{
<tbody>
for (int index = 0; index < Model.KeyMetrics.Count; index++)
{
KeyMetrics metric = Model.KeyMetrics[index];
<tr role="row">
<td>#metric.value</td>
<td>#metric.impressions</td>
</tr>
}
</tbody>
}
else
{
<tbody>
<tr class="row">
<td colspan="3">
No results found.
</td>
</tr>
</tbody>
}
</table>
<script>
$(document).ready(function () {
InitializeDataTable($(".tblKeyMetrics"));
});
function InitializeDataTable(tbl) {
if (!$.fn.DataTable.isDataTable($(tbl))) {
$(tbl).DataTable({
pageLength: 10,
iDisplayLength: 10,
"paging": true
});
}
}
</script>
using jquery.dataTables.min.js v1.10.16 with dataTables.bootstrap.min v3

MVC foreach statement

Im new with MVC.
I have a model called UAV.
│Callsign│NumDeliveries│Mileage│MaxVelocity│MinVelocity│
 Hawk61   37    96    20     10
 BURL14   2047     57     30     15
 OTTO93   82    72    25     10
in cshtml file, i made a table only using Callsign, NumDeliveries, Mileage.
<table class="UAV_table" id="UAV_table">
<tr>
<th>Callsign</th>
<th>NumDeliveries</th>
<th>Mileage</th>
</tr>
#foreach (UAV uav in Model.UAVs)
{
<tr onclick="click_row()">
<td onclick="click_row()">
#Html.DisplayFor(modelItem => uav.Callsign)
</td>
<td>
#Html.DisplayFor(modelItem => uav.NumDeliveries)
</td>
<td>
#Html.DisplayFor(modelItem => uav.Mileage)
</td>
</tr>
}
</table>
 so the table shows all datas for Callsign, NumDeliveries, Mileage.
what i want to do is, when i click the row of the table, i want to see only that correspond information.
#foreach (UAVs uavid in Model.uavs)
{
<p class="detail_title" id="detail_title">
UAV: # (#Html.DisplayFor(modelItem => uavid.MaxVelocity))
</p>
}
for example, using above line of code, if i click first row of that table(callsign = Hawk61), i want to see like UAV: # 20 (MaxVelocity for Hawk61). MaxVelocity is not in the table, so i need to get it from database.
But I have problem with showing data. If i use right above code, it has #foreach statement, it shows all the Hawk61, BURL14, OTTO93's MaxVelocity.
it shows me like
UAV:# 20
UAV:# 30
UAV:# 25
I need to see only what i selected. (just shows what i click, in this example, only need to show UAV:# 20 which is first row, Hawk61's MaxVelocity).
is there any way to get the data from database not using foreach statement?
Thank you.
Since the values of MaxVelocityand MinVelocity are populated, you can make use of data- attributes to store the values in the DOM and use jquery to display them. For example
#foreach (UAV uav in Model.UAVs)
{
<tr class="uavrow" data-maxvelocity="#uav.MaxVelocity" data-minvelocity="#MinVelocity">
<td>#Html.DisplayFor(modelItem => uav.Callsign)</td>
<td>#Html.DisplayFor(modelItem => uav.NumDeliveries)</td>
<td>#Html.DisplayFor(modelItem => uav.Mileage)</td>
</tr>
}
And include some elements to display the associated data when you click on the row
<div>
<div><span>Call Sign: </span><span id="callsign"></span>
<div><span>Max Velocity: </span><span id="maxvelocity"></span>
<div><span>Min Velocity: </span><span id="minvelocity"></span>
</div>
And the script
$('.uavrow').click(function) {
// Get the call sign for the td element
$('#callsign').text($(this).children('td').eq(0).text());
// Get the velocity from the data attributes
$('#maxvelocity').text($(this).data('maxvelocity'));
$('#minvelocity').text($(this).data('minvelocity'));
});
If however the value were not populated, or you have a large number of properties to display, then it may be better to make an ajax call to a method (passing the callsign) which returns a partial view containing the details
<div id="uavdetails"></div>
$('.uavrow').click(function) {
var callSign = $('#callsign').text($(this).children('td').eq(0).text());
var url = '#Url.Action("Details", "YourController")';
$('#uavdetails').load(url, { CallSign: callsign });
});
Controller
public ActionResult Details(string CallSign)
{
UAV uav = // Get the UAV base on the CallSign value
return PartialView(uav);
}
Actually you have all data that you need in there.
The only thing that you need is to show proper item by using JavaScript.
You need to add parameter to your function call here:
<tr onclick="click_row('#uav.Callsign')">
And also add css class here:
#foreach (UAVs uavid in Model.uavs)
{
<p class="detail_title #uavid.Callsign" id="detail_title" style="display=none;">
UAV: # (#Html.DisplayFor(modelItem => uavid.MaxVelocity))
</p>
}
And then add a bit of javascript:
<script>
function click_row(elClass){
var elements = document.getElementsByClassName("detail_title");
for (i = 0; i < x.length; i++) {
if(x[i].className.contains(elClass)){
x[i].style.display = 'block';
} else{
x[i].style.display = 'none';
}
}
};
<script/>

How do I pass an ID from View to the ViewModel as a parameter for GET function?

I'm creating a project using MVC, knockoutJS, Web API, Bootstrap and so forth, the database in use is MSSQL Server 2012. It's all working very well, the controllers have properly created CRUD operations. The data from DB is show in a grid table in the UI, and every row is clickable, and opens up a modal in which the data about that exact element is shown. The problem I'm experiencing is the inability to pass a certain value of the row, in this case an ID, to ViewModel as a parameter for getting a single result in modal. I can do it manually, and put some value in the ViewModel, and the data will show, but I'm unable to send the value from the View.
Here's the code for ViewModel:
var regionsModel = {
regionId: ko.observable(),
companyId: ko.observable(),
name: ko.observable(),
companyName: ko.observable()
};
var regionsListModel = {
regions: ko.observable()
};
function getRegions() {
get(apiUrl + "Regions/GetRegions", {}, function (data) {
regionsListModel.regions(data);
});
}
function getRegion() {
get(apiUrl + "Regions/GetRegion", { aiId: regionsModel.regionId() }, function (data) {
regionsModel.regionId(data.RegionID);
regionsModel.companyName(data.CompanyName);
regionsModel.companyId(data.CompanyID);
regionsModel.name(data.Name);
});
}
function viewRegion() {
$("#ViewRegionModal").modal('show');
//regionsModel.regionId($('#ViewRegion').val());
getRegion();
return false;
}
Here's the code for the View:
<table class="table table-striped table-bordered responsive" id="dtable">
<thead>
<tr>
<th style="width: 20px;">ID</th>
<th>Region Name</th>
<th>Company Name</th>
</tr>
</thead>
<tbody data-bind="foreach: regionsListModel.regions">
<tr id="ViewRegion" data-toggle="modal" data-bind="click: viewRegion, value: RegionID">
<td data-bind="text: RegionID"></td>
<td data-bind="text: Name"></td>
<td data-bind="text: CompanyName"></td>
</tr>
</tbody>
</table>
aiId parameter is for the GetRegion method in Controller.
This is the code for the View in which shows the data for a certain element:
<table class="table table-striped" data-bind="with: regionsModel">
<tbody>
<tr>
<th>Region ID:</th>
<td><span data-bind="text: regionsModel.regionId"></span></td>
</tr>
<tr>
<th>Region Name:</th>
<td><span data-bind="text: regionsModel.name"></span></td>
</tr>
<tr>
<th>Company Name:</th>
<td><span data-bind="text: regionsModel.companyName"></span></td>
</tr>
</tbody>
</table>
Any help would be appreciated!
Knockout adds the current bound object as first argument when it calls the event handler.
The second argument is the event object.
So the only thing you need to do is add a parameter to the viewRegion function.
function viewRegion(region) {
var regionID = region.RegionID;
// get data
return false;
}
I hope it helps.

MVC: How to insert items in a grid without refreshing the whole page

I have this view where I create a new company that gets added to the database.
The view is in 2 sections, leftside and rightside.
In the rightside I want to input the trades for that company.
A company can have 1 or more trade and this includes 1 primary trade, and 0 to many other trades.
When the user adds in the other trades, each trade will be added to a list underneath. I have NOT put in the code for this yet. For each trade in the list, he can have the option of removing it.
When he has entered all the details, he clicks submit and all the data is saved in the database.
Now I am thinking of putting in a partial view for the other trades, but I am wondering how I can do this, and every time a trade is selected from autocomplete, the data is posted to a controller method and the partial view is return.
But this will clear the data in the leftside section.
So how should I do this?
My view looks like
#model SCD.ViewModels.SubcontractorViewModel
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Create Subcontractor</legend>
<section class="wrapper">
<section class="leftside">
<table class="formTable">
<tr>
<td class="leftCell">#Html.LabelFor(model => model.Subcontractor.CompanyName)</td>
<td class="rightCell">#Html.TextBoxFor(model => model.Subcontractor.CompanyName, new { #style = "width: 300px;" })</td>
</tr>
<tr>
<td class="leftCell">#Html.LabelFor(model => model.AddressViewModel.Address1)</td>
<td class="rightCell">#Html.TextBoxFor(model => model.AddressViewModel.Address1, new { #style = "width: 300px;" })</td>
</tr>
<tr>
<td colspan="2" style="text-align: center;" class="rightCell"><input type="submit" value="Save"/></td>
</tr>
</table>
<div style="float: left">#Html.ActionLink(" ", "List", null, new { #class = "buttonBackToList" })</div>
</section>
<section class="rightside">
<table class="formTable">
<tr>
<td class="leftCell">#Html.LabelFor(model => model.PrimaryTrade)</td>
<td class="rightCell"><input type="search" name="searchPrimaryTrade" id="searchPrimaryTrade" data-scd-autocomplete="#Url.Action("AutocompletePrimaryTrade", "DataService")" style = "width: 300px;"/>
<input type="button" id="ResetPrimaryTrade" value="Reset"/>
</td>
</tr>
<tr>
<td class="leftCell">#Html.LabelFor(model => model.OtherTrades)</td>
<td class="rightCell"><input type="search" name="searchOtherTrade" id="searchOtherTrade" data-scd-autocomplete="#Url.Action("AutocompleteOtherTrade", "DataService")" style = "width: 300px;"/>
<input type="button" id="ResetOtherTrade" value="Reset"/>
</td>
</tr>
</table>
</section>
</section>
</fieldset>
}
Ajax is your answer, Whenever you do not want to reload the page then using client side ajax to communicate with the server is the only option.
I would use jQuery or to add the rows via ajax which will insert them into your database and return the populated model again and return this as a PartialView(). Your ajax would then onSuccess: replace your tableID with the returned results.
So your jQuery would be something like:
$('.rightside').children('.formTable').replaceWith(theReturnedPartialFromAjaxCall);
If you are adding a dynamic row there are two options:
On adding a row you can call an ajax request which will also add a blank row to the database and then repopulate your model and return the Partial View. This will now have the model binding in place on the new blank row, deleting the blank row or any row can also be done by ajax as the row now has an ID. Make sure however you put the ID as a hidden field in when you loop through each row.
OR (not the preferred way but probably what you will need to do as you have to perform the save)
You can capture the form collection in the save, if there are multiple rows then store this in an array
public ActionResult Save(MyModel model, FormCollection frm) {
String[] name = frm["name"].Split(',');
}
I don't like this way as it is prone to error and the first method will allow you to bind MVC's model validation

How to reset the partial view containing cascading dropdown list in MVC4 Jquery

I am using MVC4/EF and I have four cascading dropdownlist and I got it working the first time. So when the page is rendered first time, I am able to select the first dropdown and filter the result on the second and by selecting second dropdowm the third dropdwon is filtered and fourth and based on the fourth drop down I populate a edit view. But when I go back and change the selection in the first drop down, it is filtering the second drop down but not resetting the third, fourth dropdwon list and the edit partial view. Here is teh first dropdwon partial view code.
CampusUsercontrol.cshtml
#model RHMS.Models.RoomEditor
#using (Ajax.BeginForm("SelectCampus", "RoomEditor", new AjaxOptions { UpdateTargetId = "Buildings" }))
{
#Html.DropDownListFor(
m => m.SelectedCampusID,
new SelectList(Model.Campuses,"CampusId", "Name"),
string.Empty
)
}
<script type="text/javascript">
$('#SelectedCampusID').change(function () {
$(this).parents('form').submit();
});
</script>
Index.cshtml
#model RHMS.Models.RoomEditor
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<table cellpadding="0" cellspacing="4" border="0">
<tr>
<td>Campus </td>
<td> :</td>
<td>#Html.Partial("CampusUserControl", Model)</td>
</tr>
<tr>
<td>Building </td>
<td> :</td>
<td><div id="Buildings">#Html.Partial("BuildingUserControl", Model)</div></td>
</tr>
<tr>
<td>Floor </td>
<td> :</td>
<td><div id="Floor">#Html.Partial("FloorsUserControl", Model)</div></td>
</tr>
<tr>
<td>Room </td>
<td> :</td>
<td><div id="Room">#Html.Partial("RoomUserControl", Model)</div></td>
</tr>
</table>
<div id="RoomInfo">
#Html.Partial("RoomInfoUserControl", Model)
</div>
Please help me how to refresh the other partial views when the first one is changed.
Looks like this part of your javascript code is beeing executed only on the first load of the page
<script type="text/javascript">
$('#SelectedCampusID').change(function () {
$(this).parents('form').submit();
});
</script>
try wiring the change event for #SelectedCampusID using Jquery's on binding. You might also have to do the same for the other dropdowns.

Resources