How to fire Ajax function with radiobutton click MVC - ajax

I have a View made up of 3 Partial Views:
Partial View #1 is listing RadioButtons. When I click a button I would like to send the resulting selection to the controller in order to update the Partial View #2 (which is a Telerik grid). Then the selection in PV #2 will update Partial View #3 (another Telerik grid).
I am currently doing a Window.location to send selected values to the Controller which causes the Controller and ViewModel to be reloaded and lose state. Other than losing the state, the flow works as I would like.
Is there a way to do this in Ajax to where I do not have to reload the Controller?
I will spare you the Partial Views #2 & #3 of the Telerik grids. If I can get the answer to how to get the radio button to call the Controller without a postback, I can apply the same to those Partial Views.
View:
#model MyProject.ViewModel.MaterialsListVM
#{
ViewBag.Title = "Materials List";
}
<div>
<div class="row">
<div class="col-sm-2">
#Html.Partial("MaterialTypeFilter")
</div>
<div class="col-lg-10">
#Html.Partial("MaterialsGrid")
</div>
</div>
<div class="row"> </div>
<div class="row">
<div class="col-sm-2"> </div>
<div class="col-lg-10">
#Html.Partial("ProjectMaterialsGrid")
</div>
</div>
</div>
Partial View #1:
#model MyProject.ViewModel.MaterialsListVM
<div class="container">
<h5> #Html.Label("Material Type: ", new { style = "font-weight:bold;" })</h5>
#if (Model != null)
{
for (int i = 0; i < Model.Material_Type.MaterialTypeList.Count; i++)
{
<span class="btn-group-sm">
#Html.RadioButton("MatType", new { Model.Material_Type.MaterialTypeList[i].Name }, Model.Material_Type.MaterialTypeList[i].Selected, new { #onclick = "CallChangefunc(this.value)" })
#Html.Label(Model.Material_Type.MaterialTypeList[i].Name)
</span><br />
}
}
</div>
<script>
function CallChangefunc(value) {
var selected = value.replace("{ Name = ", "");
selected = selected.replace("}", "");
window.location = '#Url.Action("Index", "MaterialsList")' + '?selectedMatType=' + selected;
//alert("val is:" + selected);
}
Update
I changed the JavaScript to this Ajax call and that called my Controller HttpPost Index() function:
$(document).ready(function () {
$(':radio[name="MatType"]').change(function (e) {
$.ajax({
type: 'POST',
url: '/MaterialsList/Index',
data: { selectedMatType: $(':radio[name="MatType"]:checked').val()},
dataType: "json",
success: function (data) {
alert('did it');
}
});
});
})
Unfortunately the Controller is still being reloaded and I'm losing the state of the data selected into the Partial View #3 Telerik grid...
...any help would be much appreciated...
Update #2
This solution sucks but I don't know what else to do...
The goal is to retain the state of the datasource for a Telerik grid in Partial View #3. The datasource is a ViewModel with a List of class objects.
Added Partial View #2 code and ActionResult from Controller. There is no HttpPost Index function. Every radio button change fires the ActionResult Index. Every select event in Telerik grid fires ActionResult Index.
Pertinent Controller code:
public ActionResult Index(string selectedMatType, string selectedMaterials, string projectMaterialsList)
{
if (projectMaterialsList != null)
{
materialsListVM.ProjectMaterialsList = JsonConvert.DeserializeObject<List<ProjectMaterialsListVM.ProjectMaterial>>(projectMaterialsList);
}
if (selectedMatType != null)
{
materialsListVM.SelectMaterialType(selectedMatType);
materialsListVM.GetMaterials();
}
if (selectedMaterials != null)
{
string[] materialIds = selectedMaterials.Split(',');
foreach (string id in materialIds)
{
MoveToProjectMaterialsList(id, selectedMatType);
}
}
ViewBag.ProjectMaterialsList = materialsListVM.ProjectMaterialsList;
ViewBag.SelectedMatType = selectedMatType;
return View(materialsListVM);
}
Partial View #2 code:
#model MyProject.ViewModel.MaterialsListVM
<div>
#if (ViewBag.SelectedMatType == "Cap Weld")
{
#(Html.Kendo().Grid(Model.CapWeld_Materials)
.Name("grid")
.Columns(columns =>
{
columns.Select().Width(40);
columns.Bound(c => c.MaterialId).Hidden();
columns.Bound(c => c.MaterialTypeName);
columns.Bound(c => c.PcsPartNum);
columns.Bound(c => c.ClientPartNum);
columns.Bound(c => c.Type).Filterable(ftb => ftb.Multi(true));
columns.Bound(c => c.OuterDiameter).Filterable(ftb => ftb.Multi(true));
columns.Bound(c => c.WallThickness).Filterable(ftb => ftb.Multi(true));
columns.Bound(c => c.Specification).Filterable(ftb => ftb.Multi(true));
columns.Bound(c => c.Grade).Filterable(ftb => ftb.Multi(true));
})
.Events(ev => ev.Change("onChange"))
.Pageable()
.Sortable()
.Scrollable()
.TableHtmlAttributes(new { width = "100%" })
//.HtmlAttributes(new { style="height:500px"})
.PersistSelection(true)
.Filterable()
.DataSource(datasource => datasource
.Ajax()
.ServerOperation(false)
.Model(m => m.Id(d => d.MaterialId))
)
);
}
</div>
#{
var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
var val = jss.Serialize(ViewBag.ProjectMaterialsList);
}
<script>
function onChange(arg) {
var selectedMatType = '#(ViewBag.SelectedMatType)';
var projectMaterialsList = '#Html.Raw(val)';
//var obj = $.parseJSON(val);
var grid = $('#grid').data('kendoGrid');
var selectedMaterials = grid.selectedKeyNames().join(", ");
// alert(selectedMaterials);
#*$.ajax({
type: "POST",
data: { selectedMatType: selectedMatType, selectedMaterials: selectedMaterials, projectMaterialsList: projectMaterialsList },
dataType: "json",
url: #Url.Action("Index", "MaterialsList")
});*#
window.location = '#Url.Action("Index", "MaterialsList")' + '?selectedMatType=' + selectedMatType + '&selectedMaterials=' + selectedMaterials
+ '&projectMaterialsList=' + projectMaterialsList;
}
</script>

Related

How to get input data from MVC ViewModel into ajax post

I am fetching data from a SQL database table into an ASP.NET MVC Razor view but I have troubles getting changed input data into an Ajax post such as:
#model MyViewModel
<div class="row">
<div class="col-1">
#Html.LabelFor(model => model.Id, "Id:", new {})
</div>
<div class="col-4">
#Html.Label(Model.Id.ToString(), new { title = "" })
</div>
</div>
<div class="row">
<div class="col-1">
#Html.LabelFor(model => model.Test, "Test:", new { })
</div>
<div class="col-9">
#Html.TextBoxFor(model => model.Test, new { data_bind = "value: Test", #type = "text" })
</div>
</div>
#section scripts {
<script type="text/javascript">
$("#save-click").click(function () {
var nr = #Model.Id;
var postData = #Html.Raw(Json.Encode(#Model));
//alert(postData.Test);
$.ajax({
type: "POST",
url: actions.test.createOrUpdate + "?id=" + nr,
dataType: "json",
traditional: true,
data: postData,
success: function (response) {
if (response.Code == 0) {
else {
window.location.reload(false);
}
} else {
alert('err');
}
}
});
});
});
</script>
}
When I load the view everything is displayed correctly. The controller action is triggered correctly and the Id (which can not be altered) is passed properly too. However when input fields are changed not the changed values get passed to the controller but the original values that were fetched into the view.
The serialization seems to work, since the alert (postData.Test) returns a value - but always the unchanged one.
Any help would be appreciated.
var postData = #Html.Raw(Json.Encode(#Model));
This line is the culprit. When Razor renders the script, it will assign the original/unchanged model to your postData variable.
If you use "Inspect Element" or dev tools to check the value of postData, you'll see that the values won't change because they're statically assigned.
You need to check for the new values every time you click the button by using
var postData = $("form").serialize();
And be sure to wrap your input fields inside a form tag. See code below:
<form>
<div class="row">
<div class="col-1">
#Html.LabelFor(model => model.Id, "Id:", new {})
</div>
<div class="col-4">
#Html.Label(Model.Id.ToString(), new { title = "" })
</div>
</div>
<div class="row">
<div class="col-1">
#Html.LabelFor(model => model.Test, "Test:", new { })
</div>
<div class="col-9">
#Html.TextBoxFor(model => model.Test, new { data_bind = "value: Test", #type = "text" })
</div>
</div>
</form>
#section scripts {
<script type="text/javascript">
$("#save-click").click(function () {
var nr = #Model.Id;
// use form.serialize or use the id/class of your form
var postData = $("form").serialize();
$.ajax({
type: "POST",
url: actions.test.createOrUpdate + "?id=" + nr,
dataType: "json",
traditional: true,
data: postData,
success: function (response) {
if (response.Code == 0) {
else {
window.location.reload(false);
}
} else {
alert('err');
}
}
});
});
});
</script>
}

Partial View not printing values in mvc 5

I'm using ajax call to execute partial view controller action to print max batch number. Everything executes, but the value doesn't print in partial view. On selected dropdown list I'm calling ajax method to execute. Below is my code that i'm using.
Models.Batch.cs
[Required]
[StringLength(100)]
[DataType(DataType.Text)]
[Display(Name = "Batch Number")]
public string BatchNumber { get; set; }
BatchController.cs
public PartialViewResult GetBatchNumber(string CourseID)
{
Context.Batches contBatch = new Context.Batches();
Models.Batches b = new Models.Batches();
b.BatchNumber = contBatch.GetallBatchList().ToList().Where(p => p.CourseId == CourseID).Select(p => p.BatchNumber).Max().FirstOrDefault().ToString();
ViewBag.Message = b.BatchNumber;
return PartialView(b);
}
CreateBatch.cshtml
<div class="col-md-10">
#Html.DropDownListFor(m => m.CourseId, Model.Courses, new { id = "ddlCourse" })
<div id="partialDiv">
#{
Html.RenderPartial("GetBatchNumber", Model);
}
</div>
<script>
$("#ddlCourse").on('change', function () {
var selValue = $('#ddlCourse').val();
$.ajax({
type: "GET",
url: '/Batch/GetBatchNumber?CourseId=' + selValue,
dataType: "json",
data: "",
success: function (data) {
$("#partialDiv").html(data);
},
failure: function (data) {
alert('oops something went wrong');
}
});
});
</script>
</div>
GetBatchNumber.cshtml
#model WebApplication1.Models.Batches
<div class="form-group">
#Html.LabelFor(model => model.BatchNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DisplayFor(model => model.BatchNumber)
#Html.ValidationMessageFor(model => model.BatchNumber, "", new { #class = "text-danger" })
</div>
</div>

Kendo Grid doesn't send all checked items

I have a Kendo Grid that has checked box items. I want to check all items and send them to the controller, for export checked data to PDF. But, when I have checked all items, Kendo Grid sends only checked items from the first page of grid, and my report in PDF has only one page. How to get all checked items from Kendo Grid? My code is here:
<div style="text-align:right; font-size: 0.9em;height:28px;position: relative;">
<span style="float:left;text-align:left;">
Check All
Uncheck All
<a class="k-button k-button-icontext k-grid-Patient" id="hrefCheckedPatients" href="#" onclick="getChecked();">Export to PDF</a>
Download Generated PDF
<label id="checkedMsg" style="color:red;display:none;"></label>
</span>
(Html.Kendo().Grid<RunSummary>()
.Name("CheckedPatients")
.DataSource(datasource => datasource
.Ajax().PageSize(25)
.Sort(sort => sort.Add("UniqueId").Ascending())
.Read(read => read.Action("GetRunSummaries", "PatientReport")))
.Columns(columns =>
{
columns.Bound(c => c.UniqueId).Title(ELSORegistry.Resources.Views.Home.HomeStrings.UniqueId)
.ClientTemplate("<input type='checkbox' class='primaryBox' id='#= UniqueId #'>#= UniqueId #</input>");
columns.Bound(c => c.RunNo).Title(SharedStrings.Run);
columns.Bound(c => c.Birthdate).Title(SharedStrings.Birthdate).Format("{0:g}").Filterable(true);
columns.Bound(c => c.customAge).Title(SharedStrings.Age)
.Filterable(
filterable => filterable
.UI("AgeFilter")
.Extra(false)
.Operators(operators => operators
.ForString(str => str.Clear().IsEqualTo("Is equal to"))
)
);
columns.Bound(c => c.TimeOn).Title(PatientStrings.DateOn)
.Format("{0:g}")
.Filterable(true);
columns.Bound(c => c.TimeOff).Title(PatientStrings.DateOff)
.Format("{0:g}")
.Filterable(true);
columns.Bound(c => c.DischargedAlive).Title(PatientStrings.DischargedAlive).Filterable(true).ClientTemplate("#= DischargedAlive ? 'Yes' : 'No' #");
columns.Bound(c => c.ShowSubmitted).Title(PatientStrings.Submitted).Filterable(true).ClientTemplate("#= ShowSubmitted ? 'Yes' : 'No' #");
columns.Bound(c => c.SupportTypeEnum).Title(PatientStrings.SupportType).Filterable(true);//.ClientTemplate("#= SupportType ? 'Yes' : 'No' #");
}
)
.Pageable(p => p.PageSizes(new[] {10, 25, 50, 100}))
.Sortable()
.Filterable( )
.Events( e => e.FilterMenuInit("FilterMenuFuncWithAge") ) // apply x [closing box] on pop up filter box
)
function getChecked() {
$('#checkedMsg').text('');
var ids = new Array();
$('.primaryBox:checked').map(function (index) {
ids.push(this.id);
});
if (ids.length == 0) {
$('#checkedMsg').text('#ELSORegistry.Resources.Views.Patient.PatientStrings.NoPatientsSelected').show();
$('#hrefCheckedPatients').blur();
return;
} else {
$('#checkedMsg').text('').hide();
$('#hrefCheckedPatients').blur();
}
$.ajax({
type: "POST",
url: "/PatientReport/ExportToPDF",
dataType: "json",
traditional: true,
data: { uniqueIds: ids },
success: function (data) {
if (data.success) {
$('#lnkPdfDownload').show();
$('#lnkPdfDownload').attr('href', '/PatientReport/DownloadFile' + '?fName=' + data.fName);
} else {
$('#lnkPdfDownload').hide();
}
},
error: function (jqXHR, textStatus, errorThrown) {
$('#checkedMsg').text('#ELSORegistry.Resources.Views.Patient.PatientStrings.CheckedError').show();
$('#hrefCheckedPatients').blur();
}
});
}
</script>
Thank you in advance for any help.
We can't get directly all Ids from the kendo grid from all pages. So we have to manually get it from all the pages.
Please try with the below code snippet.
<script>
var ids = [];
function checkAll() {
var dataSource = $("#CheckedPatients").data("kendoGrid").dataSource;
var filters = dataSource.filter();
var totalRowCount = parseInt(dataSource.total().toString());
var totalPages = Math.ceil(totalRowCount / dataSource.pageSize());
var currentPageSize = $("#CheckedPatients").data("kendoGrid").dataSource.page();
PageTraverser(dataSource, 1, totalPages,filters, function () {
$("#CheckedPatients").data("kendoGrid").dataSource.page(currentPageSize);
alert("You have slected this Ids:- " + ids.join(','));
});
}
function PageTraverser(dataSource, targetPage, totalPages,filters, completionFunction) {
dataSource.query({
page: targetPage,
filter: filters
pageSize: 1,
}).then(function () {
var view = dataSource.view();
for (var viewItemId = 0; viewItemId < view.length; viewItemId++) {
var viewItem = view[viewItemId];
ids.push(viewItem.UniqueId); //Please change your field name here
}
targetPage++;
if (targetPage <= totalPages) {
PageTraverser(dataSource, targetPage, totalPages, filters, completionFunction);
} else {
completionFunction();
}
});
}
</script>
Let me know if any concern.

How to create page using Kendo Gird and Tabstrip

I want to select a row of grid and show detail row at tabstrip. The same image should attach.
Can anyone help me? I am using asp.net mvc 4 + Kendo Ui controls.
Image is here.
File CandidateController.cs
public ActionResult Index()
{
return View();
}
public ActionResult Can_Read([DataSourceRequest]DataSourceRequest request)
{
return Json(GetAllCan().ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
public ActionResult Can_ReadId([DataSourceRequest]DataSourceRequest request, Guid id)
{
return Json(GetCanById(id).ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
In partial view: Candidate Info
#model RecruitmentOnlineMVC.Models.CandidateViewModel
<div class="candidate-detail" style="width: 827px!important">
<table>
<tr>
<th>Candidate Name</th>
<td>#(Html.TextBoxFor(model => model.CandidateName, new { #class = "k-input k-textbox" }))</td>
<th>ID</th>
<td>#Html.TextBoxFor(model => model.ID, new { #class = "k-input k-textbox" })</td>
</tr>
<tr>
<th>Email</th>
<td>#Html.TextBoxFor(model => model.Email, new { #class = "k-input k-textbox" })</td>
<th>Phone</th>
<td>#Html.TextBoxFor(model => model.Phone, new { #class = "k-input k-textbox" })</td>
</tr>
</table>
</div>
In View Index
#model RecruitmentOnlineMVC.Models.CandidateViewModel
#(Html.Kendo().Splitter()
.Name("splitter")
.Panes(panes =>
{
panes.Add()
.Content(#<div>
#(Html.Kendo().Grid<RecruitmentOnlineMVC.Models.CandidateViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.CandidateName);
columns.Bound(c => c.ID);
})
.Selectable(selectable => selectable
.Mode(GridSelectionMode.Single))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Can_Read", "Candidate"))
)
.Pageable(pageable => pageable.ButtonCount(3))
.Filterable()
.Sortable()
.ColumnMenu()
.Events(e => e.Change("onSelected"))
)
</div>)
.Scrollable(true)
.Collapsible(true)
.Size("370px");
panes.Add()
.Content(#<div>
#(Html.Kendo().TabStrip()
.Name("tabstrip")
.Items(tabstrip =>
{
tabstrip.Add().Text("Candidate Detail")
.Selected(true)
.LoadContentFrom("/Candidate/CandidateInfo");
tabstrip.Add().Text("Work History")
.LoadContentFrom("/Candidate/WorkHistory");
})
)
</div>);
}))
Script
<script>
function onSelected() {
var can = this.select();
var propId = this.dataItem(can).ID;
\\In here, I want call action at Controller with propId and return detail on Tabstrip
Can anyone help me?
Thank so much !
I want to handled according to process like this :
Please guide me. Thank so much!
You need to make a seprate function in you controller with Json http post
and calls ajax request from the OnSelected() function..
following is the example
//Get Company List
[HttpPost]
public JsonResult GetCandidateDetails(string propId)
{
var Model= repository.GetCnadidatedetails(propId);
return Json(Model), JsonRequestBehavior.AllowGet);
}
<script>
function onSelected() {
var can = this.select();
var propId = this.dataItem(can).ID;
var dataItem = this.dataItem(e.item.index());
$.ajax({
url: '#Url.Action("GetCnadidatedetails", "Controller")',
//note: only string type is allowed as paramater to send to controller
data: { propId : this.propId },
dataType: "json",
type: "POST",
statusCode: {
404: function () {
showMessage("page not found.");
}
},
error: function () {
alert("error");
},
success: function (result) {
//add your result to tabstripe
$("#tabstrip").add(result.Id+result.Name);
}
});

Using Jquery to collect data, use data to get a Partial View from the controller, and append the passed information to the end of a page

I am attempting to append a partial view to the end of my 'currently displayed page' when a selection from a dropdown menu is chosen.
This is the dropdown from my view:
<div>
#Html.DropDownListFor(x => x.DropDownInfo, Model.Info, "DefaultSelection")
#Html.ValidationMessageFor(model => model.Courses)
</div>
I am in most need here in my Jquery. What do I need to do to append the PartialView that is returned by my controller (pasted below)? My current Jquery:
$(document).ready(function() {
$("#DropDownInfo").change(function() {
var strSelected = "";
$("#DropDownInfo option:selected").each(function() {
strSelected += $(this)[0].value;
});
var url = "/Controller/PreFillMethod/?MethodString=" + strSelected;
$.post(url, function(data) {
//*****
// Assuming everything else is correct,
// what do I do here to have my partial view returned
// at the end of the currently displayed page?
//*****
});
});
});
This is the part of my controller that replies with a PartialView (I want the string from the dropdown selection to be passed into this controller to ultimately be used to fill in a field in the PartialView's form) :
public PartialViewResult PreFillCourse(string selectedFromDropDown)
{
ViewBag.selectedString = selectedFromDropDown;
MyViewModel preFill = new MyViewModel
{
Title = selectedFromDropDown, // I am using this to pre-fill a field in a form
};
return PartialView("_PartialViewForm", preFill);
}
The Partial View (in the case that it matters):
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>CourseTemplates</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
I am open to suggestions if I am approaching the situation entirely incorrectly.
My goal is to have a user select a 'template' from the drop-down menu and have that template's data autopopulate into a form below the drop-down.
My Jquery is very rough - I am using this post as a guide
you should have a div in your view
<div id ="divToAppend">
</div>
then append the partial view to your div
$(document).ready(function() {
$("#DropDownInfo").change(function() {
var strSelected = "";
$("#DropDownInfo option:selected").each(function() {
strSelected += $(this)[0].value;
});
var url = "/Controller/PreFillMethod/?MethodString=" + strSelected;
$.post(url, function(data) {
$('#divToAppend').html(data);
//*****
// Assuming everything else is correct,
// what do I do here to have my partial view returned
// at the end of the currently displayed page?
//*****
});
});
});

Resources