Im loading contents dynamically to table as you see i have an input and i have two Checkbox:
$.ajax({
type: "GET",
url: "/User/GetCustomerContactInfo",
data: { ids: items },
traditional: true,
dataType: 'json',
success: function (values) {
for (var i = 0; i < values.length; i++) {
value = values[i]
if (value != null) {
holderHTML += '<tr id="row' + value.CustomerNo + '">';
holderHTML += '<td><input id="NameOfCompany" name="[' + i + '].NameOfCompany" value="' + value.NameOfCompany + '" /></td>';
holderHTML += '<td><input id="checkboxCustom1" type="checkbox" name="[' + i + '].RightsCode" value="Åbne ordrer"/>
<input id="checkboxCustom1" type="checkbox" name="[' + i + '].RightsCode" value="Lukkede ordrer"/></td>
holderHTML += '</tr>';
}
}
$('#output').append(holderHTML);
},
error: function () {
console.log('something went wrong - debug it!');
}
})
And HTML Output will be like:
<form id="CustomerNEmployeeForm">
<table>
<tbody id="output">
<tr id="row10883">
<td>
<input type="text" id="NameOfCompany" name="[0].NameOfCompany" value="Center">
</td>
<td>
<input id="checkboxCustom1" type="checkbox" name="[0].RightsCode" value="Åbne ordrer">
<input id="checkboxCustom1" type="checkbox" name="[0].RightsCode" value="Fakturerede ordrer">
</td>
</tr>
</tbody>
</table>
</form>
<button class="btncreateusers" id="createusersJS" type="button" onclick="CreateCustomerNEmployees();">Create</button>
And than i want to get value of checkbox and pass to controller by Serialize form, but when form being Serialized, it will pass only value of first Checkbox:
function CreateCustomerNEmployees() {
var formdata = $("#CustomerNEmployeeForm").serializeArray();
console.log(formdata);
$.ajax({
"url": '#Url.Action("CreateCustomers", "User")',
"method": "POST",
"data": formdata ,
"dataType": "json",
complete: function () {
}
});
}
Output console.log(formdata):
0: {name: "[0].NameOfCompany", value: "Center"}
1: {name: "[0].RightsCode", value: "Åbne ordrer"}
2: {name: "[0].RightsCode", value: "Lukkede ordrer"}
Model:
public class CreateCustomers
{
public string NameOfCompany { get; set; }
public string RightsCode { get; set; }
}
Controller:
[HttpPost]
public JsonResult CreateCustomers(List<CreateCustomers> model)
{
if (model == null)
{
model = new List<CreateCustomers>();
}
var resultsOne = new List<Users>();
var resultsTwo = new List<Rettigheder>();
foreach (var item in model)
{
var UsersInsert = new Users
{
CompanyName = item.NameOfCompany,
//other property
};
var RettighederInsert = new Rettigheder
{
//other property
Rettighedskode = item.RightsCode
};
resultsOne.Add(UsersInsert);
db.Users.Add(UsersInsert);
resultsTwo.Add(RettighederInsert);
db.Rettigheder.Add(RettighederInsert);
}
db.SaveChanges();
return Json(model, JsonRequestBehavior.AllowGet);
}
Debug Output:
https://i.imgur.com/DT6TYd4.jpg
The CreateCustomers Model has specified RightsCode as a single string.
public class CreateCustomers
{
public string NameOfCompany { get; set; }
public string RightsCode { get; set; }
}
The MVC model binding in this case binds the first match only.
If you want all RightsCode checkboxes bound you need to change RightsCode to a string array.
public class CreateCustomers
{
public string NameOfCompany { get; set; }
public string[] RightsCode { get; set; }
}
Unrelated but good practice -
html tag id values should be unique. Names can be duplicated but id values that are not unique can cause problems with css/js selectors.
Related
I have 2 method to get state and city from one table :
Model:
public string Title { get; set; }
public long? ParentId { get; set; }
public bool IsDeleted { get; set; }
public bool IsActive { get; set; }
and this is its view model
public string Title { get; set; }
public long LocationId { get; set; }
I have 2 method to get city and state .
and with first I choose first to show first city of ID:
var state = await _packageService.GetStateForUserInfo();
ViewData["State"] = state;
var firstLocationId = state.First().LocationId;
var city = await _packageService.GetCityForUserInfo(firstLocationId);
ViewData["City"] = city;
I user from view model. because when I use from select list, it returns null!
so after all on view this my select tag:
<label class="w-100 d-flex align-items-center" for="">
<label> State </label>
<select asp-for="LocationId" asp-items="(#ViewData["State"] as IEnumerable<SelectListItem>)" id="Location_Id" class="form-control">
<span asp-validation-for="LocationId"></span>
#foreach (var item in ViewBag.state)
{
<option value="#item.LocationId">#item.Title</option>
}
</select>
<label> City </label>
<select asp-for="LocationId" asp-items="(#ViewData["city"] as IEnumerable<SelectListItem>)" id="SubLocation_Id" class="form-control ">
<span asp-validation-for="LocationId"></span>
#foreach (var item in ViewBag.city)
{
<option value="#item.LocationId && #item.Title==Title">#item.Title</option>
}
</select>
</label>
and this is my jQuery :but it does not return Sub Locations( city) and does not save Id( I mean in location table field that :
ParentId == locationId
#section scripts
{
<script>
$("#Location_Id").change(function() {
$("#SubLocation_Id").empty();
$.getJSON("/UserPanel/UserInfo/GetSubGroup/" + $("Location_Id:selected").val(),
function(data) {
$.each(data,
function() {
$("#SubLocation_Id").append('<option value=' + this.value + '>' + this.text + '</option>');
});
});
});
</script>
}
Update:
this is my get and post method:
[HttpGet("userInfo/first-start-userInfo/{packageId}")]
public async Task<IActionResult> FirstStartUserInfo(long packageId,UserPanelMenu menu=UserPanelMenu.Packages )
{
if (packageId <= 0) return RedirectToAction("NotFound", "Home");
var userId = User.GetCurrentUserId();
if (!await _packageService.IsPackagePurchasedByUser(userId, packageId)) return RedirectToAction("NotFound", "Home");
var state = await _packageService.GetStateForUserInfo();
ViewData["State"] = state;
var firstLocationId = state.First().LocationId;
var city = await _packageService.GetCityForUserInfo(firstLocationId);
ViewData["City"] = city;
return View();
}
[HttpPost("userInfo/first-start-userInfo/{packageId}")]
public async Task<IActionResult> FirstStartUserInfo(CreateFirstStartUserInfoViewModel firstStartUserInfo )
{
var userId = User.GetCurrentUserId();
//if (!ModelState.IsValid) return View(firstStartUserInfo);
var res = await _packageService.CreateFirstStartUserInfoByUser(firstStartUserInfo, userId);
return View(firstStartUserInfo);
}
I fill its properties on service :
......
EditFirstStartUserInfoViewModel editFirstStartUserInfo = new EditFirstStartUserInfoViewModel()
{
PackageId = firstStartUserInfo.PackageId,
Address = firstStartUserInfo.Address,
DayOfBirth = firstStartUserInfo.DayOfBirth,
Goal = firstStartUserInfo.Goal,
Job = firstStartUserInfo.Job,
Marriage = firstStartUserInfo.Marriage,
MonthOfBirth = firstStartUserInfo.MonthOfBirth,
Sex = firstStartUserInfo.Sex,
UserPackageId = userPackageId,
UserInfoId = await _packageRepository.GetUserInfoIdByUserPackageIdAndUserInfoSituation(userPackageId, i),
YearOfBirth = firstStartUserInfo.YearOfBirth,
LocationId = firstStartUserInfo.LocationId == 0 ? null : firstStartUserInfo.LocationId
Update2:
Method to get city:
public async Task<IActionResult> GetSubGroup(long id)
{
var city =await _packageService.GetCityForUserInfo(id);
return Json(city);
}
I tested your code snippet in my side and I'm afraid the issue comes from $("Location_Id:selected").val(), this line-code will bring me undefined so your ajax get request may send an error data to the server. I used $("#Location_Id option:selected").val() instead.
And here's my testing code -- Controller
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using WebApplication1.Models;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
ViewData["State"] = new List<State> {
new State{ Title="state1_part1",LocationId=1},
new State{ Title="state1_part2",LocationId=2},
new State{ Title="state1_part3",LocationId=3},
new State{ Title="state1_part4",LocationId=4}
};
ViewData["City"] = new List<City> {
new City{ Title="city3",SubLocation_Id=2,LocationId=3},
new City{ Title="city4",SubLocation_Id=2,LocationId=4}
};
return View();
}
public JsonResult getCity(string id) {
if (id == "1")
{
var citys = new List<City> {
new City{ Title="city1",SubLocation_Id=1,LocationId=1},
new City{ Title="city2",SubLocation_Id=1,LocationId=2}
};
return Json(citys);
}
else {
var citys = new List<City> {
new City{ Title="city5",SubLocation_Id=3,LocationId=5},
new City{ Title="city6",SubLocation_Id=3,LocationId=6}
};
return Json(citys);
}
}
[HttpPost]
public IActionResult savedata(HomeModelView hmv) {
return View();
}
[HttpPost]
public IActionResult savedata2(TestViewModel tmv)
{
return View();
}
}
}
View page:
#model WebApplication1.Models.HomeModelView
#{
ViewData["Title"] = "Home Page";
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<div>
<form asp-controller="Home" asp-action="savedata" method="post">
<label class="w-100 d-flex align-items-center" for="">
<label> State </label>
<select asp-for="#Model.State.LocationId" asp-items="(#ViewData["State"] as IEnumerable<SelectListItem>)" id="Location_Id" class="form-control">
<span asp-validation-for="#Model.State.LocationId"></span>
#foreach (var item in ViewBag.state)
{
<option value="#item.LocationId">#item.Title</option>
}
</select>
<label> City </label>
<select asp-for="#Model.City.LocationId" asp-items="(#ViewData["city"] as IEnumerable<SelectListItem>)" id="SubLocation_Id" class="form-control ">
<span asp-validation-for="#Model.City.LocationId"></span>
#foreach (var item in ViewBag.city)
{
<option value="#item.LocationId && #item.Title==Title">#item.Title</option>
}
</select>
</label>
<button type="submit">submit</button>
</form>
<button id="test">test</button>
</div>
<script>
$("#Location_Id").change(function () {
$("#SubLocation_Id").empty();
console.log($("Location_Id:selected").val());
var selectedid = $("#Location_Id option:selected").val();
$.getJSON("https://localhost:44386/home/getCity/" + selectedid,
function (data) {
console.log(data[0].title);
$.each(data,
function () {
$("#SubLocation_Id").append('<option value=' + this.locationId + '>' + this.title + '</option>');
});
});
});
$("#test").click(function () {
//write the logic to obtain the title and localtion id and send them to the server
var Title = "test_title";
var LocationId = 1233;
$.ajax({
url: "https://localhost:44386/home/savedata2/",
type: "POST",
data: {
Title: Title,
LocationId: LocationId
},
success: function (data) {
alert(data);
}
});
});
</script>
viewmodel:
namespace WebApplication1.Models
{
public class TestViewModel
{
public string Title { get; set; }
public long LocationId { get; set; }
}
}
Solved this problem.
first for JQUERY I had to add option as Tiny Wang " said to show city :
$("#Location_Id option:selected").val()
and for solve problem Get locationId of city , I should insert Asp-for just for city not state:
<label class="w-100 d-flex align-items-center" for="">
<label> state </label>
<select id="Location_Id" class="form-control">
#if (state.Any())
{
#foreach (var item in state )
{
<option value="#item.LocationId">#item.Title</option>
}
}
</select>
<span asp-validation-for="LocationId"></span>
<label> City </label>
<select asp-for="LocationId" id="SubLocation_Id" class="form-control ">
#foreach (var item in city)
{
<option value="#item.LocationId ">#item.Title</option>
}
</select>
<span asp-validation-for="LocationId"></span>
</label>
I am trying to create functionality that will update a product's quantity in the users shop cart. I am able to populate the ViewModel with the relevant data and display it in a table in the View.
In the script tags, I have two functions, one to increase the quantity of the product and the other to decrease the quantity in increments of 1. Now all works well if there is one product in the list. I receive the correct values. As soon as there are two or more products in the list, whenever the increase or decrease functions are fired, the values (quantity and productId) of the last item in Model.Products are sent to the 'UpdateQuantity' ActionMethod, instead of the values from the inputs in the selected table row.
For example: If there are two products in the list. Product A (Id:1 and Quantity: 3) and Product B(ID:2 and quantity:5), If I click on either the increase or decrease buttons next to Product A's quantity input, the relevant function will pass Product B's values (2 and 5) to the Action Method instead of Product A's values (1 and 3).
I'm assuming that there is a naming convention issue, but I'm unable to figure out why this is happening. Any help would be highly appreciated.
Below is what I have so far:
ViewModel:
public class ShopCartViewModel : BaseViewModel
{
public List<OrderDetail> OrderDetailList { get; set; }
public List<Order> OrderList { get; set; }
public List<Product> Products { get; set; }
}
Controller:
public List<Order> orderList = new List<Order>();
public List<OrderDetail> orderDetailList = new List<OrderDetail>();
public List<Product> productList = new List<Product>();
public ActionResult Index()
{
ShopCartViewModel vm = new ShopCartViewModel();
ConnectToDatabase();
User u = Helpers.GetUser.GetUserDetails();
orderList = GetAllOrdersForCustomer(u.Id);
GetOrderDetails();
vm.OrderList = orderList;
vm.OrderDetailList = orderDetailList;
vm.Products = productList;
return View(vm);
}
[HttpPost]
public ActionResult UpdateQuantity(string quantity, string productId)
{
//do stuff here
}
View:
#foreach(var product in Model.Products)
{
string class_quantity = "quantity_" + product.Id;
string class_productId = "productId_" + product.Id;
<div class="quantity">
<button class="dec-btn p-0" type="submit"><i class="fas fa-caret-left" onclick="q_dec()"></i></button>
<input name="quantity" id="#class_quantity" class=" form-control" type="text" value="#product.Quantity" />
<button class="inc-btn p-0" type="submit"><i class="fas fa-caret-right" onclick="q_inc()"></i></button>
<input name="productId" id="#class_productId" class=" form-control" type="text" value="#product.Id" style="visibility:hidden" />
<script type="text/javascript">
function q_inc(e) {
var p_quantity = $("##class_quantity").val();
var final_quantity = parseInt(p_quantity) + 1;
var p_productId = $("##class_productId").val();
$.ajax({
url: '#Url.Action("UpdateQuantity","ShopCart")',
type: 'POST',
data: {quantity: final_quantity, productId: p_productId },
success: function () {
alert("Increase Success");
}
})
}
function q_dec(e) {
var p_quantity = $("##class_quantity").val();
if (p_quantity >= 2) {
var final_quantity = parseInt(p_quantity) - 1;
}
var p_productId = $("##class_productId").val();
$.ajax({
url: '#Url.Action("UpdateQuantity","ShopCart")',
type: 'POST',
data: {quantity: final_quantity, productId: p_productId },
success: function () {
alert("Decrease Success");
}
})
}
</script>
</div>
}
The problem with your code is that in your loop you are duplicating functions q_inc(e) and q_dec(e)
You should fix your code with something like this:
#foreach(var product in Model.Products)
{
string class_quantity = "quantity_" + product.Id;
string class_productId = "productId_" + product.Id;
<div class="quantity">
<button class="dec-btn p-0" type="button" onclick="q_dec('#class_productId', '#class_quantity")'><i class="fas fa-caret-left"></i></button>
<input name="quantity" id="#class_quantity" class=" form-control" type="text" value="#product.Quantity" />
<button class="inc-btn p-0" type="button" onclick="q_inc('#class_productId', '#class_quantity')"><i class="fas fa-caret-right"></i></button>
<input name="productId" id="#class_productId" class=" form-control" type="text" value="#product.Id" style="visibility:hidden" />
}
<script type="text/javascript">
function q_inc(id, quantity) {
var p_id = $("#" + id);
var p_quantity = $("#" + quantity);
var quantity_val = p_quantity.val()
var final_quantity = parseInt(quantity_val) + 1;
var p_productId = p_id.val();
$.ajax({
url: '#Url.Action("UpdateQuantity","ShopCart")',
type: 'POST',
data: {quantity: final_quantity, productId: p_productId },
success: function () {
alert("Increase Success");
p_quantity.val(final_quantity);
}
})
}
function q_dec(id, quantity) {
// change this function accordingly
</script>
I have page, where i add one or many products (this part is working) and its adding products including (Product Name, Serial number, Qty) to database. As also you see in screenshots i have single input field Customer Name which i want get value of Customer Name input feild and sending with each products to database.
Example when data inserted into database:
Customer Name | Product Name | Serial number | Qty
Stackoverflow A 1234 1
Stackoverflow B 4567 2
But, right now look like this in my database when its inserting data :
Customer Name | Product Name | Serial number | Qty
null A 1234 1
null B 4567 2
To be honest i dont know how can i sending value of Customer Name input field with each products when its trying insert data into database. Can anyone please help me or point me into the right direction! Thanks in advance :)
Controller:
[HttpPost]
public JsonResult ProcessCreateRMA(CreateRMAVM vm)
{
using (var namespace = new namespace())
{
if (vm.vares == null)
{
vm.vares = new List<CreateRMAVM.vare>();
}
foreach (var item in vm.vares)
{
var rmainsert = new RMA_History
{
//CustomerName = item.CustomerName,
ProductName = item.ProductName,
Serialnumber = item.Serialnumber,
Qty = item.Qty,
};
db.RMA_History.Add(rmainsert);
}
db.SaveChanges();
}
return Json(vm, JsonRequestBehavior.AllowGet);
}
JavaScript:
<script>
$(document).ready(function () {
//Add input field
var i = 0;
$("#add").click(function (e) {
i++;
e.preventDefault();
$("#tbhold").append('<tr id="row' + i + '"><td><div><input type="text" name="vares[' + i + '].ProductName" id=' + i + ' /></div></td><td><div><input type="text" name="vares[' + i + '].SerialNumber" id=' + i + '/></div></td><td><div style="padding:0" class="col-md-12"><input id="Qty" name="vares[' + i + '].Qty"/></div></td><td><button type="button" class="btn btn-danger btn_remove" id="' + i + '" name="remove"><i class="fa fa-minus-circle" aria-hidden="true"></i>Remove</button></td></tr>');
});
//Remove input field
$(document).on('click', '.btn_remove', function () {
var button_id = $(this).attr("id");
$("#row" + button_id + '').remove();
});
//Save to db by click
$("#submit").click(function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '#Url.Action("ProcessCreateRMA", "User")',
dataType: 'json',
data: ($('#add_rma').serialize()),
success: function (result) {
console.log(result);
},
error: function () {
console.log('something went wrong - debug it!');
}
});
});
});
</script>
View:
<label>Customer Name</label>
<input type="text" name="CustomerName" id="CustomerName">
<form name="add_rma" id="add_rma">
<table id='tbhold' class="table">
<thead>
<tr>
<th>Product Name </th>
<th>Serial number</th>
<th>Qty</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div>
<input type="text" name="vares[0].ProductName" id="ProductName" />
</div>
</td>
<td>
<div>
<input type="text" name="vares[0].Serialnumber" id="Serialnumber" />
</div>
</td>
<td>
<div>
<input name="vares[0].Qty" id="Qty"/>
</div>
</td>
<td>
<button type="button" name="add" id="add">Add more</button>
</td>
</tr>
</tbody>
</table>
<input type="submit" name="submit" id="submit" value="Submit" />
</form>
ViewModel:
public class CreateRMAVM
{
public List<vare> vares { get; set; }
public class vare
{
public vare()
{
}
public vare(/*string CustomerName*/ string ProductName, string SerialNumber, string Qty)
{
}
//public string CustomerName { get; set; }
public string ProductName { get; set; }
public string SerialNumber { get; set; }
public string Qty { get; set; }
}
}
I have updated your code to work. If you are using a datagrid, I might recommend you use one of the numerous ones out there and not try to rebuild it yourself. jqGrid (http://www.trirand.com/blog/) is one that's popular
Leave the CompanyName inside your form
Update your model as such. I've include the Customer in CreateRMAVM and in vare
public class CreateRMAVM
{
public List<vare> vares { get; set; }
public string CustomerName { get; set; }
public class vare
{
public vare()
{
}
public vare(/*string CustomerName*/ string ProductName, string SerialNumber, string Qty)
{
}
public string CustomerName { get; set; }
public string ProductName { get; set; }
public string SerialNumber { get; set; }
public string Qty { get; set; }
}
}
Update your controller as such. CustomerName will come populated in CreateRMAVM, and then there's a line of code to copy into the vare lists
[HttpPost]
public JsonResult Create(CreateRMAVM vm)
{
try
{
if (vm.CustomerName != null && vm.vares != null)
{
vm.vares.Select(c => { c.CustomerName = vm.CustomerName; return c;
}).ToList();
}
<input type="text" name="CustomerName" id="CustomerName">
is not within your form definition. Move this into the form
this is my item
public class RequestViewModel
{
public long FeederId { set; get; }
public int A { set; get; }
public int B { set; get; }
public int C { set; get; }
public int Remain { set; get; }
}
and this is my Add model that i want to send from my form to my Controller
public class RequestAddListViewModel
{
public List<SuppliantRequestFeederAddViewModel> SuppliantRequestFeederAddViewModels { set; get; }
public List<SelectListItem> FeederSelectListItems { set; get; }
public long NodeId { set; get; }
}
first time my form load i have One item i have a button when i click on it my first row clone and append to my form for example now i have 8 item on my form, i can delete each item on client side. if i didn't delete any item and submit form there no problem.
My problem is when delete one of item for example second one when deleted and then submit my form there is no item on my controller. nothing send to Controller.
View
#for (int index = 0; index < Model.RequestAddListViewModel.Count; index++)
{
var req = Model.RequestAddListViewModel[index];
<tr class="requestrow">
<td>
#Html.DropDownListFor(p => p.req[index].FeederId, Model.FeederSelectListItems, new { #class = "form-control" })
</td>
<td>
#Html.TextBoxFor(p => p.req[index].A, new { #class = "form-control" })
</td>
<td>
#Html.TextBoxFor(p => p.req[index].B, new { #class = "form-control" })
</td>
<td>
#Html.TextBoxFor(p => p.req[index].C, new { #class = "form-control" })
</td>
<td>
<button type="button" class="btn btn-primary btn-icon btn-rounded newfeeder"><i class="icon-plus2"></i></button>
</td>
</tr>
}
and my jQuery script (Edited):
var inputCount=0;
$(document).on('click', '.newfeeder', function () {
inputCount++;
var tr = $(this).closest("tr").clone();
tr.find("input").val(0);
tr.find("button").removeClass("btn-primary").addClass("btn-danger").removeClass("newfeeder").addClass("deleterow");
tr.find("button i").removeClass("icon-plus2").addClass("icon-trash");
tr.find("input,select").each(function () {
$(this).attr({
'name': function (_, name) { return name.toString().replace('0', inputCount) },
'id': function (_, id) { return id.toString().replace('0', inputCount) }
});
});
$(this).closest("tr").after(tr);
});
$(document).on('click', '.deleterow', function() {
$(this).closest("tr").remove();
});
finally i found my solution after add or delete new item to my form
i call this function ReCreateIndex()
function ReCreateIndex(container) {
$(container).each(function (index, obj) {
$("input,select", $(this)).each(function () {
if ($(this).attr("name")) {
var name = $(this).attr("name").replace($(this).attr("name").replace(/[^0-9]/gi, ''), index);
$(this).attr("name", name);
}
if ($(this).attr("id")) {
var id = $(this).attr("id").replace($(this).attr("id").replace(/[^0-9]/gi, ''), index);
$(this).attr("id", id);
}
});
});
}
it means that after any change on items,index of items recreated.
I've seen many posts on SO considering this topic, though applying solutions didn't work for me and I am confused right now. Mb I'm missing sth?
Please consider I'm a noob at .js stuff.
So I get my values from dynamicly created form elements with this JS and attempt to post it:
EDIT 12:21: I got this script which should parse each element from form into custom made array resembling json. I still get null reference though. Got any idea how to get it?
var getValues = function (myForm) {
var array = [];
var parser;
$("formElement").each( function (i, elem) {
parser.empty()
parser = {
Id: $(elem,"#Id ").val(),
someOption: $(elem, "#someOption ").val(),
someText: $(elem, "#someText ").val(),
someNumber: $(elem, "#someNumber ").val()
}
array.push(parser);
});
console.log(array);
$.ajax({
type: "POST",
url: 'angus',
traditional: true,
data: {json: array },
success: function (data) {
$("#getData").empty();
$("#getData").append(array);
}
});
};
I get this in log:
(objects of index like i,i+1,i+2,i+3 match the viewmodels - is it right? and I have mixed feelings about those proto and functions - what is it?)
In my controller action I get null exception:
[HttpPost]
public ActionResult angus(IEnumerable<TrashViewModel> json)
{
return View(json.ToList());
}
I created my viewmodel:
[Serializable]
public class TrashViewModel
{
public int Id { get; set; }
public string someOption { get; set; }
public string someText { get; set; }
public string someNumber { get; set; }
}
I had my forms HTML attributes names match those of viemodel class.
EDIT:
html:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="formExample" ng-controller="ExampleController">
<button class="btn btn-primary" ng-controller="addRow" ng-click="addLine()">Dodaj przycisk</button>
<form novalidate class="simple-form">
<div class="here">
<div class="formElement row">
<input type="hidden" name="Id" value="1"/>
<div class="col-md-2">
<select name="someOption" class="optns form-group col-md-12" ng-model="user.class">
<option selected value="1"> Rodzaj... </option>
<option value="test">2</option>
<option value="2">test</option>
<option value="2">2</option>
<option value="3">3</option>
#*tutaj beda dodane opcje*#
</select>
</div>
<div class="col-md-1">
<input name="someNumber" class="form-group col-md-12" type="number" ng-model="user.number" value="" text="Ilość..." /><br />
</div>
<div class="col-md-9">
<input name="someText" class="form-group col-md-12" type="text" ng-model="user.text" value="" text="Uwagi..." /><br />
</div>
</div>
</div>
<input type="button" value="Reset" />
<input type="submit" value="Save" />
</form>
</div>
appended html:
var strVar = "";
strVar += "<div class=\"formElement row\">";
strVar += " <input type=\"hidden\" name=\"Id\" value=\" "+ $scope.counter +"\"\/>";
strVar += " <div class=\"col-md-2\">";
strVar += " <select name=\"someOption\" class=\"optns form-group col-md-12\" ng-model=\"user.class\">";
strVar += " <option selected value=\"1\"> Rodzaj... <\/option>";
strVar += " <option value=\"test\">2<\/option>";
strVar += " <option value=\"2\">test<\/option>";
strVar += " <option value=\"2\">2<\/option>";
strVar += " <option value=\"3\">3<\/option>";
strVar += " #*tutaj beda dodane opcje*#";
strVar += " <\/select>";
strVar += " <\/div>";
strVar += " <div class=\"col-md-1\">";
strVar += " <input name=\"someNumber\" class=\"form-group col-md-12\" type=\"number\" ng-model=\"user.number\" value=\"\" text=\"Ilość...\" \/><br \/>";
strVar += " <\/div>";
strVar += " <div class=\"col-md-9\">";
strVar += " <input name=\"someText\" class=\"form-group col-md-12\" type=\"text\" ng-model=\"user.text\" value=\"\" text=\"Uwagi...\" \/><br \/>";
strVar += " <\/div>";
strVar += " <\/div>";
I end up with null exception which by what other posts suggest is because of viemodel class doesn't match the serialized objects. Don't know what to do at this point.
Thank you!
In order to POST your array, you need to stringify the data and set the contentType option. You ajax code needs to be
$.ajax({
type: 'POST',
url: '#Url.Action("angus")', // do not hard code url's
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ model: array }),
success: function (data) {
and the controller
[HttpPost]
public ActionResult angus(IEnumerable<TrashViewModel> model)
try replacing
var parsed = $(myForm).serializeArray();
with
var parameters = {
Id : $("#Id ").val(),
someOption : $("#someOption ").val(),
someText : $("#someText ").val(),
someNumber : $("#someNumber ").val()
};
then pass it to the submit
JSON.stringify(parameters)
in your JavaScript code, 3 things jump out at me:
you're using .serializeArray(), which creates an array of objects each with a name and value property. this does not match the structure of your TrashViewModel object
you're wrapping the serialized object inside a new object with a single property called "json", which adds more structure to your data
you're stringifying said object
all of that is unnecessary, since the .ajax() method will package the data in the correct format for you. you simply need to pass the serialized form as the data parameter.
data: $(myform).serialize()
on the controller, you should just set the parameter on the action to be your TrashViewModel object. please note that it's a single object, not an enumerable.
public ActionResult Angus(TrashViewModel form)
{
// do something
}
if you were to use .serializeArray(), then you'd need to create a model object with Name and Value properties so that the model binder can properly resolve the params.
// JavaScript
data: $(myform).serializeArray()
// Controller
public class NameValueModel
{
public string Name { get; set; }
public string Value { get; set; }
}
public ActionResult Angus(NameValueModel[] form)
{
// do something
}
I'm not 100% happy about outcome, because I still have to parse json string at the end on server side. I think I'll soon do Q&A, so others won't have to fight a week to do sth like this. Thanks to:
#StephenMuecke
#Emil
#Jeff M
So actually what I did:
js to get inputs and push it custom style then do post ajax request:
var array = [];
var parser;
$(".formElement").each( function (i, elem) {
//parser.empty()
parser = {
Id: $("#Id", $(this)).val(),
someOption: $("#someOption", $(this)).val(),
someText: $("#someText", $(this)).val(),
someNumber: $("#someNumber", $(this)).val()
};
console.log(parser);
array.push(parser);
});
console.log(array);
$.ajax({
type: "POST",
url: 'angus',
traditional: true,
data: { json: JSON.stringify(array) },
success: function (data) {
$("#getData").empty();
$("#getData").append(array);
}
});
controller:
(don't mind the logic, because it's useless here except it gave info during debugging)
the most important thing was to give string type as parameter; I'm 100% sure that my json bounced off of the complex type viewmodel
[HttpPost]
public ActionResult angus(string json)
{
var check = json.ToString() == null;
return RedirectToAction("ErrorAction");
}