I an experimenting with MVC. I have a view which contains a dropdownlist and a table.
When I select an option from the dropdownlist, I want to get the data from my controller and update the view:
View:
<div>
<h2>Current Print Statistics</h2>
#using (Html.BeginForm())
{
#Html.DropDownList("LogTypes", new SelectList(Model.LogTypes, "Value", "Text"), new
{
id = "logType",
data_url = Url.Action("GetStatistics", "Home")
})
<table id="modelTable" class="table table-condensed">
<tr>
<th>RequestedOn</th>
<th>PrintedOn</th>
<th>Message</th>
<th>Success</th>
<th>TemplateName</th>
</tr>
<tbody>
#foreach (var item in Model.PrintLogs)
{
string css = (item.Success) ? "success" : "danger";
string link = (item.Success) ? "www.google.com" : string.Empty;
<tr class="#css">
<td>#item.RequestedOn</td>
<td>#item.PrintedOn</td>
<td>#item.Message</td>
#if (item.Success)
{
<td>#item.Success</td>
}
else
{
<td>#Html.ActionLink("False", "Index", "LogView", new { id = item.LogID }, null)</td>
}
<td>#item.TemplateName</td>
</tr>
}
</tbody>
</table>
}
</div>
</div>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script type="text/javascript">
$(function () {
$('#logType').change(function () {
console.log($(this).data('url'));
var selectedValue = $(this).val();
var table = $('#modelTable');
$.ajax({
url: $(this).data('url'),
type: 'GET',
cache: false,
context: table,
data: { value: selectedValue },
success: function (result) {
$.each(result.PrintLogs,
function (index, log) {
$('<tr/>', {
html: $('<td/>', {
html: log.RequestedOn
}).after($('<td/>', {
html: log.PrintedOn
})).after($('<td/>', {
html: log.Success
})).after($('<td/>', {
html: log.Message
})).after($('<td/>', {
html: log.TemplateName
}))
}).appendTo(tableBody);
}
);
}
});
});
});
</script>
Controller:
[HttpGet]
public JsonResult GetStatistics(string value)
{
var request = LogTypeRequest.Last24H;
if (value == "0") request = LogTypeRequest.Last24H;
if (value == "1") request = LogTypeRequest.LastWeek;
if (value == "2") request = LogTypeRequest.LastMonth;
var model = new PrintServerModel
{
LogTypes = new List<ListItem>
{
new ListItem() {Text = "Last 24 Hours", Value = "0"},
new ListItem() {Text = "Last Week", Value = "1"},
new ListItem() {Text = "Last Month", Value = "2"}
},
PrintLogs = PrintServerService.GetPrinterLog(request)
};
return Json(model, JsonRequestBehavior.AllowGet);
}
Now when I try to debug in chrome, when the line $.ajax({ is reached it seems to jump to the end.
Ideally what I want is to display the data on start up and then when the user selects something from the dropdown, refresh the data.
Any help greafully appreciated!!
Odds are there is an error from the json call, you should add .done or error: to the end of it so you can see what your error is.
also there is a tab in chrome debug tool for watching the network calls, you may be able to see the response from the call in there with some additional details.
just looking over the ajax call, may want to change to have
data: JSON.stringify( { value: selectedValue }),
if you get more info i will do what i can to better my answer.
Related
I'm currently working on a project where the previous contractor had an attachments area within our site. The piece works for the most part but has issues when redirecting back after uploading the file, plus I don't like the fact the page does a full page reload just to update a grid to show the uploaded file.
My goal is to instead do an Ajax call for the upload versus form submit. I have added this in, however, the return forces a download of the Json object (using IE 11). I have researched how to get around this and have yet to find any substantial ways around it.
Is it possible to upload a file using Ajax and not send back a download of the Json object?
Below is my code.
View (Upload.cshtml)
#using (Html.BeginForm("Upload", "PM", FormMethod.Post, new { enctype = "multipart/form-data", id = "frmUpload" }))
{
#Html.ValidationSummary(true)
<table>
...
<tr>
<td>#Html.Label("File: ")</td>
<td>
<input type="file" name="file" id="file"/>
#Html.ValidationMessage("file","File is required")
</td>
</tr>
...
<tr>
<td colspan="2">
<p>
<button type="submit" class="t-button" id="btnSubmit">
Attach</button>
<button type="button" class="t-button" onclick="CloseAttachmentWindow()">
Cancel</button>
</p>
</td>
</tr>
</table>
}
<script type="text/javascript">
$(document).ready(function () {
$("#btnSubmit").click(function (e) {
e.preventDefault();
if (!$('form').valid())
return false;
//Upload document
$.ajax({
type: "POST",
cache: false,
url: "/PM/Upload",
dataType: "json",
contentType: false,
processData: false,
data: $('form').serialize(),
success: function (result) {
if (result.success) {
var window = $("#error").data("tWindow");
window.content("<b>Attachment successfully added</b>").title("Success!");
window.center().open();
CloseAttachmentWindow();
}
else {
var window = $("#error").data("tWindow");
window.content("<b>Error: Unable to Upload Document. Please try again. "
+ "If this fails, contact the administrators with the below details.</b>"
+ '\n' + '\n' + result.Error).title("Error");
window.center().open();
}
},
error: function (xhtr, e, e2) {
var window = $("#error").data("tWindow");
window.content(e + '\n' + xhtr.responseText, 'error', '');
window.center().open();
}
});
});
});
</script>
PMController.cs
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file, FormCollection formcollection)
{
if (file != null)
{
var cntPOC = int.Parse(Session["cntPOC"].ToString());
try
{
var cntFileType = _fileTypeRepo.GetCntFileTypeByMimeType(file.ContentType);
if (cntFileType == 0)
throw new Exception("This file type is not supported");
var strAttachmentName = formcollection["AttachmentName"];
var strAttachmentType = formcollection["AttachmentType"];
var length = file.ContentLength;
var tmpFile = new byte[length];
if (tmpFile.Count() > 0)
{
file.InputStream.Read(tmpFile, 0, length);
var intAttchmentId = _AttachRepo.GetNextAttachmentId() + 1;
var objAttachment = new TBLATTACHMENT
{
CNTATTACHMENT = intAttchmentId,
CNTPOC = cntPOC,
CNTFILETYPE = cntFileType,
CNTATTACHMENTTYPE = Convert.ToDecimal(strAttachmentType),
DTMCREATED = DateTime.Now,
STRATTACHMENTTITLE = strAttachmentName,
BLBATTACHMENT = tmpFile,
STRORIGINALFILENAME = file.FileName,
YSNDELETED = 0
};
_AttachRepo.Add(objAttachment);
_AttachRepo.Save();
return Json(new { success = true, Error = "" });
}
//File not real
else
return Json(new { success = false, Error = "Please select appropriate file" });
}
catch (Exception ex)
{
logger.LogError("File Upload", ex);
if (ex.InnerException != null)
ModelState.AddModelError("Error", ex.InnerException.ToString());
else
ModelState.AddModelError("Error", ex.Message.ToString());
TempData["ModelState"] = ModelState;
return Json(new { success = false, Error = ex.Message });
}
}
else
{
logger.LogError("File Upload Error. File was not selected");
ModelState.AddModelError("Error", "Please select file");
TempData["ModelState"] = ModelState;
return Json(new { success = false, Error = "File was not selected" });
}
}
As is, using this code, I can upload documents, however, I get the prompt to download the Json object upon return.
NOTE Long story short, you cannot do this. I had to learn the hard way and never did find a solution. I did find a way to do it for downloads, but not uploads.
Options:
Remove change the button type submit to button <input type="button"/>
<input type="submit" onclick="return false">
return false; or add event handlers
$("input[type='submit']").click(function() { return false; });
or
$("form").submit(function() { return false; });
<form onsubmit="return false"> ...</form>
in order to avoid refresh at all "buttons", even with onclick assigned.
changing the submit type to button is the optimal one.
I am trying to implement ASP.NET MVC Paging using MVC4.Paging nuget package.
Problem:
It is working in online demo and also in the download source code. However I am not able to find why it is not working in my particular project by AJAX. In my project it is working by full post back method but not Ajax.
I have even tried to copy over the Index action method and Index and _AjaxEmployeeList Views (.cshtml) files (except .js).
Note: In my solution its not bootstrap as shown in samples. Also my controller name is AdminController whereas in Samples its HomeController
In my solution I need it to work in AJAX method as in samples.
Kindly help regarding:
1. How to find the root cause for why it is not working?
2. How to make this working?
.
My Solution Code (which I tried to reproduce in my solution from the sample):
Index.cshtml
#using MvcPaging
#model IPagedList<MvcPagingDemo.Models.Employee>
#{
ViewBag.Title = "MVC 4 Paging With Ajax Bootstrap";
}
<div class="row-fluid">
<div class="span6">
<h2>
Ajax Paging With Bootstrap In MVC 4
</h2>
</div>
<div class="span6">
<div class="alert alert-info">
The pager also supports area's. #Html.ActionLink("Ajax paging in an area", "Index", "Admin", new { Area = "AreaOne" }, new { #class = "btn btn-success" })</div>
</div>
</div>
<div class="clearfix">
</div>
#using (Ajax.BeginForm("Index", "Admin",
new AjaxOptions { UpdateTargetId = "grid-list", HttpMethod = "get", LoadingElementId = "loading", OnBegin = "beginPaging", OnSuccess = "successPaging", OnFailure = "failurePaging" },
new { id = "frm-search" }))
{
<div class="input-append">
<input class="span2" id="appendedInputButton" type="text" name="employee_name" placeholder="Name" />
<button class="btn" type="submit">
<i class="icon-search"></i> Search</button>
</div>
<div id="grid-list">
#{ Html.RenderPartial("_AjaxEmployeeList", Model); }
</div>
}
<script type="text/javascript">
function beginPaging(args) {
// Animate
$('#grid-list').fadeOut('normal');
}
function successPaging() {
// Animate
$('#grid-list').fadeIn('normal');
$('a').tooltip();
}
function failurePaging() {
alert("Could not retrieve list.");
}
</script>
_AjaxEmployeeList.cshtml
#using MvcPaging
#model IPagedList<MvcPagingDemo.Models.Employee>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>
ID
</th>
<th>
Name
</th>
<th>
Email
</th>
<th>
Phone
</th>
<th>
City
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#item.ID
</td>
<td>
#item.Name
</td>
<td>
#item.Email
</td>
<td>
#item.Phone
</td>
<td>
#item.City
</td>
</tr>
}
</tbody>
</table>
<div class="pager1">
#Html.Raw(Ajax.Pager(
new Options
{
PageSize = Model.PageSize,
TotalItemCount = Model.TotalItemCount,
CurrentPage = Model.PageNumber,
ItemTexts = new ItemTexts() { Next = "Next", Previous = "Previous", Page = "P" },
ItemIcon = new ItemIcon() { First = "icon-backward", Previous = "icon-chevron-left", Next = "icon-chevron-right", Last = "icon-forward" },
TooltipTitles = new TooltipTitles() { Next = "Next page", Previous = "Previous page", Page = "Page {0}." },
Size = Size.normal,
Alignment = Alignment.centered,
IsShowControls = true,
IsShowFirstLast = true,
CssClass = ""
},
new AjaxOptions
{
UpdateTargetId = "grid-list",
OnBegin = "beginPaging",
OnSuccess = "successPaging",
OnFailure = "failurePaging"
}, new { controller = "Admin", action = "Index", employee_name = ViewData["employee_name"] }))
<div class="well">
Showing <span class="badge badge-success">#Model.ItemStart</span> to <span class="badge badge-success">#Model.ItemEnd</span>
of <span class="badge badge-info">#Model.TotalItemCount</span> entries</div>
</div>
AdminController.cs
public class AdminController : Controller
{
private const int defaultPageSize = 3;
private IList<Employee> allEmployee = new List<Employee>();
private string[] name = new string[4] { "Will", "Johnny", "Zia", "Bhaumik" };
private string[] phone = new string[4] { "1-274-748-2630", "1-762-805-1019", "1-920-437-3485", "1-562-653-8258" };
private string[] email = new string[4] { "donec#congueelitsed.org", "neque.non#Praesent.co.uk", "et.magna#Pellentesque.ca", "enim.commodo#orci.net" };
private string[] city = new string[4] { "Wigtown", "Malderen", "Las Vegas", "Talence" };
public AdminController()
{
InitializeEmployee();
}
private void InitializeEmployee()
{
// Create a list of 200 employee.
int index = 0;
for (int i = 0; i < 200; i++)
{
var employee = new Employee();
//int categoryIndex = i % new Random().Next(1, 5);
//if (categoryIndex > 3)
// categoryIndex = 3;
index = index > 3 ? 0 : index;
employee.ID = i + 1;
employee.Name = name[index];
employee.Phone = phone[index];
employee.Email = email[index];
employee.City = city[index];
allEmployee.Add(employee);
index++;
}
}
public ActionResult Index(string employee_name, int? page)
{
ViewData["employee_name"] = employee_name;
int currentPageIndex = page.HasValue ? page.Value : 1;
IList<Employee> employees = this.allEmployee;
if (string.IsNullOrWhiteSpace(employee_name))
{
employees = employees.ToPagedList(currentPageIndex, defaultPageSize);
}
else
{
employees = employees.Where(p => p.Name.ToLower() == employee_name.ToLower()).ToPagedList(currentPageIndex, defaultPageSize);
}
//var list =
if (Request.IsAjaxRequest())
return PartialView("_AjaxEmployeeList", employees);
else
return View(employees);
}
public ActionResult Paging(string employee_name, int? page)
{
ViewData["employee_name"] = employee_name;
int currentPageIndex = page.HasValue ? page.Value : 1;
IList<Employee> employees = this.allEmployee;
if (string.IsNullOrWhiteSpace(employee_name))
{
employees = employees.ToPagedList(currentPageIndex, defaultPageSize);
}
else
{
employees = employees.Where(p => p.Name.ToLower() == employee_name.ToLower()).ToPagedList(currentPageIndex, defaultPageSize);
}
return View(employees);
}
}
JS references in the _Layout.cshtml
You have not described how exactly it is not working. but i will guess the most common issues which might be causing your issue
make sure you actually have a reference to the correct java script files. its not enough to have them in a folder, your page must link to them.
see the following link to see how you reference scripts on you page. http://www.w3schools.com/tags/att_script_src.asp
make sure you put in the correct path.
make sure you reference the *ajax.js files for ajax to work along with any other required files.
Finally I found the solution.
Since I was using jquery-1.11.1.js, in script file jquery.unobtrusive-ajax.js I had to replace calls to .live() with .on().
But simple find and replace was not right way which I found later. I found from other sources that I have to change completely those lines of code as the .on() works.
I replaced the code as below:
Non-working code with .live() function:
$("a[data-ajax=true]").live("click", function (evt) {
debugger;
evt.preventDefault();
asyncRequest(this, {
url: this.href,
type: "GET",
data: []
});
});
$("form[data-ajax=true] input[type=image]").live("click", function (evt) {
debugger;
var name = evt.target.name,
$target = $(evt.target),
form = $target.parents("form")[0],
offset = $target.offset();
$(form).data(data_click, [
{ name: name + ".x", value: Math.round(evt.pageX - offset.left) },
{ name: name + ".y", value: Math.round(evt.pageY - offset.top) }
]);
setTimeout(function () {
$(form).removeData(data_click);
}, 0);
});
$("form[data-ajax=true] :submit").live("click", function (evt) {
debugger;
var name = evt.target.name,
form = $(evt.target).parents("form")[0];
$(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []);
setTimeout(function () {
$(form).removeData(data_click);
}, 0);
});
$("form[data-ajax=true]").live("submit", function (evt) {
debugger;
var clickInfo = $(this).data(data_click) || [];
evt.preventDefault();
if (!validate(this)) {
return;
}
asyncRequest(this, {
url: this.action,
type: this.method || "GET",
data: clickInfo.concat($(this).serializeArray())
});
});
Working code with .on() function:
$(document).on("click", "a[data-ajax=true]", function (evt) {
evt.preventDefault();
asyncRequest(this, {
url: this.href,
type: "GET",
data: []
});
});
$(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) {
var name = evt.target.name,
$target = $(evt.target),
form = $target.parents("form")[0],
offset = $target.offset();
$(form).data(data_click, [
{ name: name + ".x", value: Math.round(evt.pageX - offset.left) },
{ name: name + ".y", value: Math.round(evt.pageY - offset.top) }
]);
setTimeout(function () {
$(form).removeData(data_click);
}, 0);
});
$(document).on("click", "form[data-ajax=true] :submit", function (evt) {
var name = evt.target.name,
form = $(evt.target).parents("form")[0];
$(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []);
setTimeout(function () {
$(form).removeData(data_click);
}, 0);
});
$(document).on("submit", "form[data-ajax=true]", function (evt) {
var clickInfo = $(this).data(data_click) || [];
evt.preventDefault();
if (!validate(this)) {
return;
}
asyncRequest(this, {
url: this.action,
type: this.method || "GET",
data: clickInfo.concat($(this).serializeArray())
});
});
Thanks.
I have a form on which I am adding rows dynamically using Jquery.
Please take a look: DEMO
Now I want to save the data of all rows that has been added in my database using Jquery Ajax call on click event of SAVE button. The point where I am stuck is .. I am not sure how should I extract data of all rows and send it to the webmethod. I mean had it been c# I could have used a DataTable to store data of all rows before sending it to DataBase. I think I should create a string seperated by commas and pipe with data of each row and send it to webmethod. I am not sure if its the right approach and also how this is to be done (ie. creating such a string).
HTML
<table id="field">
<tbody>
<tr id="row1" class="row">
<td> <span class='num'>1</span></td>
<td><input type="text" /></td>
<td><select class="myDropDownLisTId"> <input type="text" class="datepicker" /></select></td><td>
<input type="submit"></input>
</td>
</tr>
</tbody>
</table>
<button type="button" id="addField">Add Field</button>
<button type="button" id="deleteField">Delete Field</button>
<button type="button" id="btnsave">SAVE</button>
2 suggestions:
To keep it as close as what you already have, you could just enclose your table in a form tag, and then you could just submit the form (use something like the jQuery Form plugin to submit it via Ajax). The trickiest part will be to bind that data to action parameters. You may be able to receive it in the form of an array, or you could default to looping through properties of the Request.Form variable. Make sure you generate proper names for those fields.
I think the cleanest way to do it would be to have a JavaScript object holding your values, and having the table generated from that object, with 2-way bindings. Something like KnockoutJS would suit your needs. That way the user enters the data in the table and you'll have it ready to be Json-serialized and sent to the server. Here's a quick example I made.
I wouldn't recommend that approach, but if you wanted to create your own string, you could do something along those lines:
$("#btnsave").click(function () {
var result = "";
$("#field tr").each(function (iRow, row) {
$("td input", row).each(function (iField, field) {
result += $(field).val() + ",";
});
result = result + "|";
});
alert(result);
});
You will have problems if the users types in a comma. That why we use well known serialization formats.
use ajax call on save button event...
like this
$(document).ready(function () {
$('#reqinfo').click(function () {
// debugger;
var emailto = document.getElementById("emailid").value;
if (emailto != "") {
$.ajax({
type: "GET",
url: "/EmailService1.svc/EmailService1/emaildata?Email=" + emailto,
// data: dat,
Accept: 'application/json',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
// debugger;
},
error: function (result) {
// debugger;
}
});
}
else {
//your validation message goes here
return false;
}
});
});
and add you all data in quesry string and transfer it to webservice..
url: "/EmailService1.svc/EmailService1/emaildata?Email=" + emailto + "data1=" + data1,
<script type="text/javascript">
var _autoComplCounter = 0;
function initialize3(_id) {
var input_TO = document.getElementById(_id);
var options2 = { componentRestrictions: { country: 'ID' } };
new google.maps.places.Autocomplete(input_TO, options2);
}
google.maps.event.addDomListener(window, 'load', initialize3);
function incrementValue() {
var value = parseInt(document.getElementById('number').value, 10);
value = isNaN(value) ? 0 : value;
value++;
document.getElementById('number').value = value;
}
function GetDynamicTextBox(value) {
var _id = "AutoCompl" + _autoComplCounter;
_autoComplCounter++;
return '<input name = "DynamicTextBox" type="text" id="' + _id + '" value = "' + value + '" onkeypress = "calcRoute();" />' +
'<input type="button" class="superbutton orange" value="Remove" onclick = "RemoveTextBox(this)" />'
}
function AddTextBox() {
var value = parseInt(document.getElementById('number').value, 10);
value = isNaN(value) ? 0 : value;
value++;
if (document.getElementById('number').value < 3) {
document.getElementById('number').value = value;
var div = document.createElement('DIV');
var _id = "AutoCompl" + _autoComplCounter;
_autoComplCounter++;
var ht = '<input name = "DynamicTextBox" type="text" id="' + _id + '" value = "" onkeypress = "calcRoute();" class="clsgetids" for-action="' + _id + '" />' +
'<input type="button" class="superbutton orange" value="#Resources.SearchOfferRides.btnRemove" onclick = "RemoveTextBox(this); calcRoute();" />';
div.innerHTML = ht;
document.getElementById("TextBoxContainer").appendChild(div);
setTimeout(function () {
var input_TO = document.getElementById(_id);
var options2 = { componentRestrictions: { country: 'ID' } };
new google.maps.places.Autocomplete(input_TO, options2);
}, 100);
document.getElementById("TextBoxContainer").appendChild(div);
}
else {
alert('Enter only 3 stop point. !!');
}
}
function RemoveTextBox(div) {
//calcStopPointRoute();
var value = parseInt(document.getElementById('number').value, 10);
value = isNaN(value) ? 0 : value;
value--;
document.getElementById('number').value = value;
document.getElementById("TextBoxContainer").removeChild(div.parentNode);
}
function RecreateDynamicTextboxes() {
var values = eval('<%=Values%>');
if (values != null) {
var html = "";
for (var i = 0; i < values.length; i++) {
html += "<div>" + GetDynamicTextBox(values[i]) + "</div>";
}
document.getElementById("TextBoxContainer").innerHTML = html;
}
}
// window.onload = RecreateDynamicTextboxes;
</script>
And get the value from textbox:
#region stop point
string[] textboxValues = Request.Form.GetValues("DynamicTextBox");
if (textboxValues != null)
{
for (Int32 i = 0; i < textboxValues.Length; i++)
{
if (textboxValues.Length == 1)
{
model.OptionalRoot = textboxValues[0].ToString();
}
else if (textboxValues.Length == 2)
{
model.OptionalRoot = textboxValues[0].ToString();
model.OptionalRoot2 = textboxValues[1].ToString();
}
else if (textboxValues.Length == 3)
{
model.OptionalRoot = textboxValues[0].ToString();
model.OptionalRoot2 = textboxValues[1].ToString();
model.OptionalRoot3 = textboxValues[2].ToString();
}
else
{
model.OptionalRoot = "";
model.OptionalRoot2 = "";
model.OptionalRoot3 = "";
}
}
}
#endregion
Short answer:
DataTable equivalent in javascript is Array of custom object (not exact equivalent but we can say that)
or
you roll your own DataTable js class which will have all the functions and properties supported by DataTable class in .NET
Long answer:
on client side(aspx)
you define a class MyClass and store all your values in array of objects of that class
and then pass that array after stingyfying it to web method
JSON.stringify(myArray);
on the server side(codebehind)
you just define the web method to accept a list of objects List<MyClass>
PS: When calling web method, Asp.net automatically converts json array into List<Object> or Object[]
Loooong answer (WHOLE Solution)
Page aspx:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link href="App_Themes/SeaBlue/jquery-ui-1.9.2.custom.css" rel="stylesheet" type="text/css" />
<script src="Scripts/jquery-1.8.3.js" type="text/javascript"></script>
<script src="Scripts/jquery-ui-1.9.2.custom.min.js" type="text/javascript"></script>
<script src="Scripts/json2.js" type="text/javascript"></script>
<script type="text/javascript">
function MyClass(title,option,date) {
this.Title = title;
this.Option = option;
this.Date = date;
}
function GetJsonData() {
var myCollection = new Array();
$(".row").each(function () {
var curRow = $(this);
var title = curRow.find(".title").val();
var option = curRow.find(".myDropDownLisTId").val();
var date = curRow.find(".datepicker").val();
var myObj = new MyClass(title, option, date);
myCollection.push(myObj);
});
return JSON.stringify(myCollection);
}
function SubmitData() {
var data = GetJsonData();
$.ajax({
url: "testForm.aspx/PostData",
data: "{ 'myCollection': " + data + " }",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function () {
alert("Success");
}
});
}
$(document).ready(function () {
filldd();
CreateDP();
var rowstring = "<tr class='row'><td class='number'></td><td><input type='text' class='title'/></td><td><select class='myDropDownLisTId'/><input type='text' class='datepicker'/></td><td><input type='submit'></input></td></tr>";
$("#addField").click(function (event) {
$("#field tbody").append(rowstring);
filldd();
CreateDP();
if ($("td").hasClass("number")) {
var i = parseInt($(".num:last").text()) + 1;
$('.row').last().attr("id", "row" + i);
$($("<span class='num'> " + i + " </span>")).appendTo($(".number")).closest("td").removeClass('number');
}
event.preventDefault();
});
$("#deleteField").click(function (event) {
var lengthRow = $("#field tbody tr").length;
if (lengthRow > 1)
$("#field tbody tr:last").remove();
event.preventDefault();
});
$("#btnsave").click(function () {
SubmitData();
});
});
function filldd() {
var data = [
{ id: '0', name: 'test 0' },
{ id: '1', name: 'test 1' },
{ id: '2', name: 'test 2' },
{ id: '3', name: 'test 3' },
{ id: '4', name: 'test 4' },
];
for (i = 0; i < data.length; i++) {
$(".myDropDownLisTId").last().append(
$('<option />', {
'value': data[i].id,
'name': data[i].name,
'text': data[i].name
})
);
}
}
function CreateDP() {
$(".datepicker").last().datepicker();
}
$(document).on('click', 'input[type="submit"]', function () {
alert($(this).closest('tr')[0].sectionRowIndex);
alert($(this).closest('tr').find('.myDropDownLisTId').val());
});
</script>
</head>
<body>
<form id="frmMain" runat="server">
<table id="field">
<tbody>
<tr id="row1" class="row">
<td>
<span class='num'>1</span>
</td>
<td>
<input type="text" class="title"/>
</td>
<td>
<select class="myDropDownLisTId">
</select>
<input type="text" class="datepicker" />
</td>
<td>
<input type="submit"></input>
</td>
</tr>
</tbody>
</table>
<button type="button" id="addField">
Add Field</button>
<button type="button" id="deleteField">
Delete Field</button>
<button type="button" id="btnsave">
SAVE</button>
</form>
</body>
</html>
CodeBehind:
public partial class testForm : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[WebMethod]
public static void PostData(List<MyClass> myCollection)
{
Console.WriteLine(myCollection.Count);
}
}
public class MyClass
{
string title;
public string Title
{
get { return title; }
set { title = value; }
}
string option;
public string Option
{
get { return option; }
set { option = value; }
}
string date;
public string Date
{
get { return date; }
set { date = value; }
}
}
Hope this helps
References:
Json2.js file
stringify method
define a class in js
I have MVC4 web-application with 2 cascading dropdownlists (parent and child) and button with post action for filtering data dislpayed in grid depending on selected values in dropdownlists. Cascading dropdownlists I realized with Microsoft AJAX (Ajax.BeginForm helper), almost as described here: http://weblogs.asp.net/raduenuca/archive/2011/03/20/asp-net-mvc-cascading-dropdown-lists-tutorial-part-3-cascading-using-microsoft-ajax-ajax-beginform-helper.aspx. BTW, dropdownlists are located in partial view.
The problem is that when I click button, postback is performed and selected values in cascading dropdownlists are reset to original values, i.e. "Please, select value".
Does anybody know how to solve this problem?
Thanks in advance for all who give an answers!
Here is my code with partial view with cascading dropdownlists:
<script type="text/javascript">
$(function () {
$('#Sections').change(function () {
var sectionId = $("#Sections :selected").val();
if (sectionId != "") {
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: '#Url.Action("GetDocumentTypesList", "DocumentTypes")',
data: { "id": sectionId },
dataType: "json",
success: function (data) {
var items = "";
$.each(data, function (i, documentType) {
items += "<option value='" + documentType.Value + "'>" + documentType.Text + "</option>";
});
$('#Types').html(items);
},
error: function (result) {
alert('Service call failed: ' + result.status + ' Type :' + result.statusText);
}
});
}
else {
var items = '<option value="">Select</option>';
$('#Types').html(items);
}
});
});
#Html.DropDownList("Sections", new SelectList(ViewBag.Sections, "Id", "Name"), "Please select parent type", new { id = "Sections" })
#Html.DropDownList("Types", new SelectList(ViewBag.Types, "Id", "Name"), "Please select child type", new { id = "Types" })
And here is controller code for partial view:
public class DocumentTypesController : Controller
{
static List<DocumentType> documentTypes = DocumentsDAL.GetDocumentTypes(true, true, false);
// GET: /DocumentTypes/
public ActionResult Index()
{
var root = documentTypes.Where(d => d.ParentId == null).ToList();
ViewBag.Sections = root;
ViewBag.Types = new List<DocumentType> { new DocumentType { Id = -1, Name = "Select" } };
return PartialView("~/Views/Shared/_DocumentTypes.cshtml", root);
}
// Get values for parent dropdownlist.
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult GetDocumentTypesList(string id)
{
var items = GetDocumentTypes(Convert.ToInt32(id)).Select(a => new SelectListItem
{
Text = a.Name,
Value = a.Id.ToString(CultureInfo.InvariantCulture)
});
return Json(items, JsonRequestBehavior.AllowGet);
}
// Get values for child dropdownlist.
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult GetDocumentTypeData(string sectionId, string typeId)
{
var documentTypeData = GetDocumentTypes(Convert.ToInt32(sectionId))
.First(d => d.Id == Convert.ToInt32(typeId));
return Json(documentTypeData, JsonRequestBehavior.AllowGet);
}
private static IEnumerable<DocumentType> GetDocumentTypes(int id)
{
return documentTypes.First(d => d.Id == id).DocumentTypes;
}
}
And this is a base view where it's used partial one:
#using (Ajax.BeginForm("Index", null, new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "documentsGrid"
}, new { #class = "form-inline" }))
{
<div>
#{ Html.RenderAction("Index", "DocumentTypes", new { area = "" }); }
</div>
<p class="form-inline">
#Html.LabelForModel(#Resources.LabelPeriodFrom)
#Html.Raw(" ")
#Html.TextBox("periodFrom", "", new { #class = "input-small" })
#Html.Raw(" ")
#Html.LabelForModel(#Resources.LabelPeriodTo)
#Html.Raw(" ")
#Html.TextBox("periodTo", "", new { #class = "input-small" })
#Html.Raw(" ")
<input type="submit" class="btn" value="Filter" />
</p>
}
And controller for basic view with post-action Index, which fired when user press button:
public class IssuerDocumentsController : Controller
{
static readonly IEnumerable<IssuerDocument> Documents = DocumentsDAL.GetDocuments(1, 1).AsEnumerable();
[HttpPost]
public ActionResult Index(FormCollection collection)
{
var documents = Documents.AsEnumerable();
// Check if document section filter is applied.
if (!string.IsNullOrEmpty(collection.Get("Sections")))
{
var documentSectionId = Convert.ToInt32(collection.Get("Sections"));
documents = documents.Where(d => d.SectionId == documentSectionId);
}
// Check if document type filter is applied.
if (!string.IsNullOrEmpty(collection.Get("Types")))
{
var documentTypeId = Convert.ToInt32(collection.Get("Types"));
documents = documents.Where(d => d.TypeId == documentTypeId);
}
return View(documents);
}
}
so when the user click the edit link to edit one of the client (field) and another user have erase already that client how can show to the user that the client (field) is gone?
so I'am using TempData is another way to do it? i think jquery but i don't know how to use it properly
public ActionResult Edit (int id)
{
client cliente = db.Clients.Find(id);
if (cliente != null)
{
return View(cliente);
}
TempData["message"] = string.Format("this client have be erase for other user");
return RedirectToAction("Index");
}
edit:
and view is this
<table class="widgets">
<tr>
<th></th>
<th>
#Html.ActionLink("Nombre", "Index", new { ordenacion = ViewBag.NameSortParm, filtro = ViewBag.filtro })
</th>
</tr>
#foreach (var item in Model) {
<tr id="widget-id-#item.id">
<td>
#Html.ActionLink("Editar", "Edit", new { id=item.id }) |
#Ajax.ActionLink("Eliminar", "Eliminar", "Cliente",
new {item.id },
new AjaxOptions {
HttpMethod = "POST",
Confirm = string.Format("Esta Seguro que quiere eliminar '{0}'?", item.descripcion),
OnSuccess = "deleteConfirmation"
})
</td>
<td>
#Html.DisplayFor(modelItem => item.descripcion)
</td>
</tr>
}
</table>
i guees the script will be this? so i have to make my edit link like i did for the delete (eliminar) link using #Ajax.ActionLink right?
<script type="text/javascript">
var validateForEdit = function (id) {
var validateCallbackFunction = function (result) {
if (result) {
window.location = '/Client/Editar/' + id;
}
else {
window.Alert('this client have be erase for other user');
}
};
$.post('/Client/ValidateForEdit/', { id: id }, validateCallbackFunction, 'json');
}
</script>
Hi you can use following code to validate data before user can edit that
var validateForEdit = function (id) {
var validateCallbackFunction = function (result) {
if (result) {
window.location = '/Client/Edit/' + id;
}
else {
Alert('this client have be erase for other user');
}
};
$.post('/Client/ValidateForEdit/', { id: id }, validateCallbackFunction, 'json');
}
And your Action :
[HttpPost]
public JsonResult ValidateForEdit(int id)
{
var cliente = db.Clients.Find(id);
return cliente != null ? Json(true) : Json(false);
}
Edit : And you have to replace your following code
#Html.ActionLink("Editar", "Edit", new { id=item.id })
with this code :
<input class="button" type="button" value="Edit" onclick="validateForEdit(item.id)" />
Hope this help.