C# MVC Populate group of dropdown lists in datatable - c#

So im using jquery.dataTables.js to display about a thousand rows, while only showing about twenty at a time. The problem is with the dropdownlist on every line it takes about 10 seconds to load the page and shows a lot more of the records while loading. I thought about doing it after page load with ajax but not sure how to do that cleanly with all of them. Any ideas.
#for (int i = 0; i < Model.billVersion.Count; i++)
{<tr>
<td>#Html.DisplayFor(model => model.billVersion[i].billNumber)#Html.HiddenFor(model => model.billVersion[i].billNumber)</td>
<td>#Html.DisplayFor(model => model.billVersion[i].lrNumber)</td>
<td>#Html.DisplayFor(model => model.billVersion[i].previousYear)</td>
<td>#Html.DisplayFor(model => model.billVersion[i].committeeRec)</td>
<td>#Html.DropDownListFor(model => model.billVersion[i].committeeID, #Model.committeDropDown, "")</td>
<td>#Html.CheckBoxFor(model => model.billVersion[i].save_Remove)</td>
</tr>
}

An application of Jquery UI autocomplete:
!function ($) {
var cache = {};
$("[data-options]").each(constructAjaxOptions);
function constructAjaxOptions() {
var el = $(this),
acEl = $(el.clone(false)),
url = el.attr('data-options'),
initialLabel = el.attr('data-initial-label') || el.val(),
myCache = cache[url];
if (!myCache) {
myCache = cache[url] = {};
}
el.hide();
acEl
.removeAttr('id').removeAttr('name')
.val(initialLabel)
.insertAfter(el)
.autocomplete({
autoFocus: true,
minLength: 0,
source: function (request, response) {
var term = request.term;
if (term in myCache) {
response(myCache[term]);
return;
}
$.getJSON(url, request, function (data, status, xhr) {
myCache[term] = data;
response(data);
});
},
focus: function (event, ui) {
// Overridden to keep the value of the field
// from flashing in the textbox.
return false;
},
select: function (event, ui) {
acEl.val(ui.item.label);
el.val(ui.item.value);
return false;
}
});
}
}(jQuery);
.cshtml
<input type="text" id="#Html.IdFor(model => model.billVersion[i].committeeID)" name="#Html.NameFor(model => model.billVersion[i].committeeID)" value="#Value"
data-options="#Url.Action("BillVersions", "Options")" data-initial-label="#model => model.billVersion[i].commiteeName" />
Within an MVC action:
var model = billVersions.Select(o => new
{
value = o.committeeID,
label = o.commiteeName
})
.ToList();
return new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = model };

Related

Kendo UI Grid: update/save not working (_AntiForgeryToken not present)

I have a KENDO grid that displays contract attachments, which has a column 'Status'. In that column the current status of the attachment/contract is displayed. When invoking the 'Edit' event a combobox appears in the cell with all available status options.
After selecting a status and clicking the "update" button, I get the following exception:
The required anti-forgery form field "__RequestVerificationToken" is not present.
I added the #Html.AntiForgeryToken() in the view with the grid, and the [ValidateAntiForgeryToken] annotation to my method.
What am I doing wrong here?
This is the grid:
#Html.AntiForgeryToken()
#(Html.Kendo().Grid<AttachmentGridViewModel>()
.Name("attachmentEditGrid")
.HtmlAttributes(new
{
style = "height:auto;",
#class = "kendoHover"
})
.Columns(columns =>
{
columns.Bound(c => c.number).Title(Resources.Number);
columns.Bound(c => c.Consultant.FirstName).Title(Resources.Consultant);
columns.Bound(c => c.StartDate).Title(Resources.StartDate).Format("{0:" + System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern + "}");
columns.Bound(c => c.EndDate).Title(Resources.EndDate).Format("{0:" + System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern + "}");
columns.Bound(c => c.Status).Title(Resources.Status).EditorTemplateName("ContractStatusEditor");
columns.Command(command =>
{
command.Custom(Resources.Delete).Text("<span class=\"glyphicon glyphicon-remove padding-deletebutton \"></span>" + Resources.Delete).Click("onClickAttachmentDelete").HtmlAttributes(new { #class = "btn btn-danger" });
command.Edit().Text(Resources.Edit).CancelText(Resources.Cancel);
}).Title(Resources.Action).Width(200);
})
.ToolBar(toolBar => toolBar.Template("<a class='k-button k-button-icontext' href='/FA/ContractAttachment/CreateContractAttachment?contractId=1'><span class='glyphicon glyphicon-plus'></span>" + Resources.CreateAttachment + "</a>"))
//.Scrollable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(new List<object> { 3, 6, 12, Resources.All })
.ButtonCount(5))
// .Sortable()
.Filterable(filterable => filterable
.Extra(true)
.Operators(operators => operators
.ForString(str => str.Clear()
.Contains(Resources.Contains)
.StartsWith(Resources.StartsWith)
.EndsWith(Resources.EndsWith)
.IsEqualTo(Resources.IsEqualTo)
.IsNotEqualTo(Resources.IsNotEqualTo)
)))
.Events(events => events
.Save("onSaveAttachStatus")
.Edit("onAttachEdit")
.DataBound("onAttachDataBound")
.Cancel("onCancelEditing")
)
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Selectable(s => s.Enabled(ViewBag.Permissions.ReturnValue.FaEditStatusContractAttachments))
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(true)
.Update(update => update.Action("ChangeStatus", "ContractAttachment").Data("getValues"))
.Read(read => read.Action("ReadAttachmentsGrid", "Contract", new { id = Id }))
.PageSize(10)
.Model(model =>
{
model.Id(c => c.ContractId);
model.Field(c => c.number).Editable(false);
model.Field(c => c.Consultant).Editable(false);
model.Field(c => c.StartDate).Editable(false);
model.Field(c => c.EndDate).Editable(false);
model.Field(c => c.Status).Editable(true);
}))/*End datasource*/
)
This is the actionmethod that is called to save changes:
[HttpPost]
[ValidateAntiForgeryToken]
[Auth(Permission.FaEditStatusContractAttachments)]
public JsonResult ChangeStatus(int idAttachment, string statusContractAttach)
{
var contractAttach = _getContractAttachmentByIdQueryHandler.Execute(idAttachment).ReturnValue;
var contractAttachStatus = (ContractStatus)Enum.Parse(typeof(ContractStatus), statusContractAttach);
if (contractAttach == null)
{
var json = new { result = "Failed" };
return Json(json, JsonRequestBehavior.AllowGet);
}
contractAttach.StatusContractAttachment = contractAttachStatus;
var result = _updateContractAttachmentCommandHandler.Execute(new UpdateContractAttachmentCommand(contractAttach));
if (result.HasError)
{
var json = new { result = "Failed" };
return Json(json, JsonRequestBehavior.AllowGet);
}
else
{
UpdateHistory(idAttachment, contractAttachStatus);
var json = new { result = "Success" };
return Json(json, JsonRequestBehavior.AllowGet);
}
}
This is the JQuery related to the grid :
//--------------------------Attachments EDIT Grid --------------------//
//save event
function onSaveAttachStatus(e) {
//post status data to action method
$.post('#Url.Action("ChangeStatus", "ContractAttachment")', { contractId: e.model.Id, status: e.model.StatusContract }).success(function(data) {
showErrorNotification('#Resources.ContractStatusChangedSuccessMessage', true);
});
};
//kendo notification with succesmessage
function showErrorNotification(message, success) {
var notification = $("#staticNotification").data('kendoNotification');
notification.show(message, success ? "success" : "error");
var container = $(notification.options.appendTo);
container.scrollTop(container[0].scrollHeight);
}
function onClickAttachmentDelete() {
//custom delete function
var idToDelete = $(this).closest('tr').data('attachid');
var attachNumber = $(this).closest('tr').data('number');
//initiates modal with data
$('#dialog-delete-attachnr').text(attachNumber);
$("#dialog-delete-attach").modal();
$('#dialog-delete-attach').data('attachid', idToDelete);
$('#dialog-delete-contract').data('attachnumber', attachtNumber);
}
//edit event
function onAttachEdit(e) {
var ddl = $("#Status").data('kendoDropDownList');
var oldData = ddl.dataSource._data;
var signedAccountStatus = #((int) ContractStatus.SignedByAccount);
for (var i = 0; i < oldData.length; i++) {
if (ddl.selectedIndex >= signedAccountStatus && parseInt(oldData[i].Value) < signedAccountStatus) {
ddl.dataSource.remove(oldData[i--]);
}
}
console.log("edit ok");
}
//resets grid data
function resetGrid() {
$("#attachmentEditGrid").data("kendoGrid").dataSource.read();
};
//returns data for the .Update action
function getValues(e) {
var id = e.Data.attachId;
var value = e.Data("kendoDropdownList").value();
console.log(id, value);
return { id, value };
}
//Hide edit button when status is finished and hide delete when anyone signed
//when data is loaded to the grid
function onAttachDataBound(e) {
var attachEditGrid = $("#attachmentEditGrid").data("kendoGrid");
var attachEditGridData = attachEditGrid.dataSource.view();
//loop through rows
for (var i = 0; i < attachEditGridData.length; i++){
var row = attachEditGrid.table.find("tr[data-uid='" + attachEditGridData[i].uid + "']");
var statusContractAttach = attachEditGridData[i].Status;
//hide delete when signed
if (statusContractAttach >= #((int) ContractStatus.SignedByAccount)){
row.find('.k-grid-Delete').hide();
}
//hide edit when contract is finished
if (statusContractAttach == #((int)ContractStatus.Finished)){
row.find(".k-grid-edit").hide();
}
}
};
//cancel edit
function onCancelEditing(e) {
resetGrid();
onAttachDataBound();
}
JQuery post method does not automatically add the __RequestVerificationToken parameter. I suggest add it manually.
var data = $.extend(true, { contractId: e.model.Id, status: e.model.StatusContract },
{ __RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val() });
// maybe you need convert to json befor send data:
// data = data.toJSON();
$.post('#Url.Action("ChangeStatus", "ContractAttachment")', data )
.success(function(data) {
showErrorNotification('#Resources.ContractStatusChangedSuccessMessage', true);
});

cannot load content with jquery mvc 4

I'm trying to load partial page contents with jquery.load() method it is loading content but not loading styles. I have searched internet but couldn't found any solution. I'm sharing what i have done so far.
JQUERY:
$(function () {
var site = site || {};
site.baseUrl = site.baseUrl || "";
$(document).ready(function (e) {
$(".partialContents").each(function (index, item) {
var url = site.baseUrl + $(item).data("url");
if (url && url.length > 0) {
$(item).load(url, function (response, status, xhr) {
if (status == "error") {
alert(xhr.status);
}
return false;
});
}
});
});
});
View:
<div class="owl-carousel owl-carousel5">
<span class="partialContents" data-url="#Url.Action("LoadNew","Home")"></span>
</div>
Controller Action:
public async Task<ActionResult> LoadNew()
{
var viewModel = new CategoryViewModel();
viewModel.Products = await db.Products.Include(c => c.Reviews).Include(c => c.CategoryContents).Include(c => c.Affiliates).ToListAsync();
return PartialView("_NewProducts", viewModel);
}
As you have mentioned in comments that you have referenced css in Layout, you have to return View instead of PartialView.
So,
public async Task<ActionResult> LoadNew()
{
var viewModel = new CategoryViewModel();
viewModel.Products = await db.Products.Include(c => c.Reviews).Include(c => c.CategoryContents).Include(c => c.Affiliates).ToListAsync();
return View("_NewProducts", viewModel);
}
should do the work.

Grid not updating after ajaxcall

I'm creating my own filter. The filter has a dropdownlist, when this dropdownlist changes jquery will make an ajaxcall to the corresponding HTTPPOST - controller action. In this action I filter the list and pass it through to my view.
Once the list has reached my view, the webgrid is not updating. Here is some code with some debug information to show what's happening.
Controller
normal action
public ActionResult Projects()
{
IEnumerable<Project> projects = Adapter.ProjectRepository.Get();
int test = projects.Count();
List<ProjectsDisplayViewmodel> projectsView = new List<ProjectsDisplayViewmodel>();
string strCats = "";
foreach (Project prj in projects)
{
strCats = "";
Mapper.CreateMap<Project, ProjectsDisplayViewmodel>();
ProjectsDisplayViewmodel newProject = Mapper.Map<Project, ProjectsDisplayViewmodel>(prj);
foreach (Category cat in prj.Categories)
{
strCats += cat.CategoryName + ", ";
}
newProject.strCategories = strCats;
projectsView.Add(newProject);
}
ViewBag.Categories = new SelectList(Adapter.CategoryRepository.Get(), "CategoryID", "CategoryName");
/*projectsview contains 4 projects now*/
return View(projectsView);
}
httppost action
[HttpPost]
public ActionResult Projects(string catID, string strSearch)
{
IEnumerable<Project> projects = Adapter.ProjectRepository
.Get()
.Where(x =>
x.Categories.Any(
c =>
c.CategoryID == Convert.ToInt16(19))
);
int test = projects.Count();
List<ProjectsDisplayViewmodel> projectsView = new List<ProjectsDisplayViewmodel>();
string strCats = "";
foreach (Project prj in projects)
{
strCats = "";
Mapper.CreateMap<Project, ProjectsDisplayViewmodel>();
ProjectsDisplayViewmodel newProject = Mapper.Map<Project, ProjectsDisplayViewmodel>(prj);
foreach (Category cat in prj.Categories)
{
strCats += cat.CategoryName + ", ";
}
newProject.strCategories = strCats;
projectsView.Add(newProject);
}
ViewBag.Categories = new SelectList(Adapter.CategoryRepository.Get(), "CategoryID", "CategoryName");
/*projectsview contains 1 project now AND WILL DISPLAY 4*/
return View(projectsView);
}
project.cshtml
#model IEnumerable<Freelauncher.Models.ProjectsDisplayViewmodel>
#{
ViewBag.Title = "Projects";
}
#{
var grid = new WebGrid(Model, canPage: true, rowsPerPage: 25,
selectionFieldName: "selectedRow",ajaxUpdateContainerId: "gridContent");
grid.Pager(WebGridPagerModes.NextPrevious);
}
<h2>Alle projecten</h2>
#Html.DropDownList("Categories", (SelectList) ViewBag.Categories)
<div id="gridContent">
#grid.GetHtml(
columns: grid.Columns(
grid.Column("ProjectTitle", "Titel"),
grid.Column("ProjectDeadlineDate", "project deadline"),
grid.Column("ProjectEndRegisterDate", "Registreer deadline"),
grid.Column("ProjectBudget", "Prijs"),
grid.Column("ProjectIsFixedPrice", "Vaste prijs"),
grid.Column("strCategories","Categorieën"),
grid.Column("ProjectID", "meer info", format: (item) => Html.ActionLink("info", "project", new { Id = item.ProjectID} ))
//grid.Column("ProjectID", "meer info", format: Html.ActionLink("info", "project", new { Id = }
))
</div>
What am I missing that the project list in my view is not updated, the correct data is passed to the view....
edit
The ajax call
$("#Categories").change(function () {
var param = $(this).val();
$.ajax({
type: "POST",
url: "/Project/Projects",
data: { catID: $(this).val(), strSearch: 'test' },
dataType: "json",
success: function (response) { console.log("succes"); },
error: function (xhr, ajaxOptions, thrownError) {console.log("error"); }
});
});
I just noticed that nothing is printed in my console.log.... Not the success neither the error function.
You don't seem to be doing anything in the success callback of your AJAX request (other than a console.log call). So it's perfectly normal that nothing updates. You need to manually update your DOM if you want this to happen.
So you should modify your HttpPost controller action so that it returns a PartialView containing the grid. And then in your success callback inject the newly received partial into the DOM:
success: function (response) {
$('#some_id_of_a_containing_div').html(response);
console.log("succes");
},
In this example you should wrap the partial view into a containing div which will get updated here:
<div id="some_id_of_a_containing_div">
#Html.Partial("Partial_Containing_Your_Grid")
</div>

how to access #Html.RadioButtonFor in jquery

i have a coded a radio button in MVC razor.below is the code for it.
#{
var LinkRadioName = "_Link";
var ContentRadioName ="_Content";
var TextRadioName = "_Text";
var ExternalLinkRadioName ="_ExternalLink";
var FilelistRadioName ="_Filelist";
#Html.RadioButtonFor(m => m.MenuType, true, new { #id = LinkRadioName })
#Html.Label("Link")
#Html.RadioButtonFor(m => m.MenuType, false, new { #id = ContentRadioName })
#Html.Label("Content")
#Html.RadioButtonFor(m => m.MenuType, true, new { #id = TextRadioName })
#Html.Label("Text")
#Html.RadioButtonFor(m => m.MenuType, false, new { #id = ExternalLinkRadioName })
#Html.Label("External Link")
#Html.RadioButtonFor(m => m.MenuType, true, new { #id = FilelistRadioName })
#Html.Label("File List")
}
can any one help me ,as to how can i access this radiobutton set in jquery:
i have a code like this
#Html.RadioButton("TypeOfmenu", 1)Link
#Html.RadioButton("TypeOfmenu", 2)Content
#Html.RadioButton("TypeOfmenu", 3)Text
#Html.RadioButton("TypeOfmenu", 4)ExternalLink
#Html.RadioButton("TypeOfmenu", 5)Filelist
and i access it very easily in jquery like
$("input[name$='TypeOfmenu']").click(function () {
var Selectedvalue = $(this).val();
});
is there any way to access the #Html.RadioButtonFor control in d same way like
$("input[name$='MenuType']").click(function () {
var Selectedvalue = $(this).val();
});
??????
please help me as i m very new in MVC as well as jquery.
Since you are accessing the values in your function with this.val(), you can just bind your event to all radio buttons
$(":radio").click(function () {
var Selectedvalue = $(this).val();
//OR
//var Selectedvalue = this.value;
});

Jquery Autocomplete + ASP.NET MVC 3 not displaying the results

My View Code:
Script and Css:
<link href="#Url.Content("~/Content/jquery-ui-1.8.18.custom.css")" rel="stylesheet"type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-ui-1.8.18.custom.min.js")" type="text/javascript"></script>
Input text:
#Html.TextBoxFor(model => model.Filter.HouseName, new { style = "width: 205px", onKeyUp = "updateHouseNames()" })
Javascript:
function updateHouseNames() {
var houseArray = new Array();
$.post('#Url.Action("LoadHouses")', { houseName: $("#Filter_HouseName").val() }, function(houses) {
houseArray = houses;
});
$("#Filter_HouseName").autocomplete({
source: houseArray
});
}
Controller method:
[HttpPost]
public JsonResult LoadHouses(string houseName)
{
var houses = this.HouseService.SelectByName(houseName).Select(e => new String(e.Name.ToCharArray())).ToArray();
return Json(houses);
}
I debug the javascript and the houses are selected.. but the results are not displayed in autocomplete. Why?
I don't really think you should be doing it this way. If you need to customize the logic then use a callback on the autocomplete method:
$(function () {
$('#Filter_HouseName').autocomplete({
minLength: 1,
source: function (request, response) {
var term = request.term;
var houseArray = new Array();
$.post('#Url.Action("LoadHouses")', { houseName: term }, function(houses) {
houseArray = houses;
response(houseArray);
});
}
});
});

Categories