Get properties of array from View to Controller in MVC? - javascript

This is my form to submit
#using (Html.BeginForm("SigningAsync", "Signing", FormMethod.Post,
new { onsubmit = "return confirm('Do you really want to submit the form?');"}))
{
<div class="col-md-6 col-sm-12 form-group" style="margin-bottom:5px !important">
<input type="submit"
id="btnConf"
name="Sign" value="Confirm"
class="btn btn-primary pull-right" style="margin-right:2px" />
<div class="form-group">
<input type="hidden" id="arr" name="arr" />
</div>
</div>
}
<input type="checkbox" value="#masterData.DocNo" name="selected" class="inforID" id="#masterData.NewDocNo" plant="#masterData.Plant" flowno="#masterData.FlowNo"/>
When checkbox is checked and Confirm button is pressed, I put attribute from checkbox to input arr
$(document).ready(function() {
$("#btnConf").click(function () {
var selected = [];
$.each($("input[name='selected']:checked"), function () {
selected.push({
DocNo: $(this).val(),
NewDocNo: $(this).attr("id"),
Plant: $(this).attr("plant"),
FlowNo: $(this).attr("flowno")
});
document.getElementById("arr").value = JSON.stringify(selected);
});
console.log(JSON.stringify(selected));
});
});
The input arr will like this
<div class="form-group">
<input type="hidden" id="arr" name="arr" value="[
{"DocNo":"100400020719-006","NewDocNo":"ABS-02072019","Plant":"VDNF","FlowNo":"FLW-000001"},
{"DocNo":"100400020719-007","NewDocNo":"ABS-02072019","Plant":"VDNF","FlowNo":"FLW-000001"}
]">
</div>
And this is the Action
public async Task<ActionResult> SigningAsync([Bind(Include = "arr")] PurchaseRequestViewModel purchaseRequestViewModel, string Sign, string[] arr)
{
bool result = false;
if(arr != null)
{
if (ModelState.IsValid && !String.IsNullOrWhiteSpace(Sign))
{
for(int i = 0; i < arr.Length; i++)
{
string test = a[i].NewDocNo;
}
}
}
}
I can't get the property of object in arr, I have tried string test = a[i][NewDocNo]; or string test = a[i]["NewDocNo"];.
But it wasn't right. How can I get the properties of array in the Controller?
I have tried console.log(selected[0].NewDocNo); in Javascript and it's ok, but in the Controller, it wasn't right.

The value that you have in your HTML will be treated as a string value as there are not multiple values passed to the controller. You are only passing a single value. You need to change the method signature and use string arr and have the value as a string. Then do the conversion on the server.
Also, instead of submitting a form manually, better to use Javascript and AJAX to submit the data. Then you can pass the value of arr in the request body as JSON. Then that will automatically be converted into an array.

Related

Serialize form and change input names (remove the array part of the input names)

I want to serialize my html form and submit it to my sever via ajax, but before submitting the form, I want to rename the variable names and remove the initiali part, which is: BranchViewModels[0]. for example, I want to change:
change: BranchViewModels[0].BranchName to: BranchName
change: BranchViewModels[1].AddressViewModel.AddressId to : AddressViewModel.AddressId
Basically when I generate form, all the input names are rendered as an array, but before submitting the form, I want to get rid of array section of the input name (BranchViewModels[0]. in this example).
I have explained why I am doing this here
I have also created a jsfiddle for the following example.
function updateBranch() {
$('.save-branch-button').click(function() {
var branchForm = $(this).closest('form');
var serializedform = branchForm.find('.form :input').serialize();
alert('I want to change the input names in this serialized form: \n\n' + serializedform );
// 1. iterated through serialized form
//
// remove BranchViewModels[i]. from the name, e.g.
// replace: BranchViewModels[0].BranchName
// with: BranchName
// 2. Submit the form
/* $.ajax({
url: "/my-server",
data: {branchViewModel: <-- serialized model},
dataType: 'json',
type: "POST"}); */
});
}
jQuery(document).ready(function($) {
updateBranch();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form onsubmit="return false;" novalidate="novalidate">
<div class="form">
<div class="form-group">
<label>Branch name</label>
<input class="form-control" data-val="true" id="BranchViewModels_0__BranchName" name="BranchViewModels[0].BranchName" type="text" value="branch 1">
</div>
<hr />
<div class="form-group">
<label>Branch location</label>
<div>
<input data-val="true" id="BranchViewModels_0__AddressViewModel_AddressId" name="BranchViewModels[0].AddressViewModel.AddressId" value="1956">
</div>
<div>
<input class="address-street-address" data-val="true" id="BranchViewModels_0__AddressViewModel_StreetAddress" name="BranchViewModels[0].AddressViewModel.StreetAddress" value="Wellington 6011, New Zealand">
</div>
</div>
<input type="button" class="btn btn-primary-action save-branch-button" value="Save">
</div>
</form>
function updateBranch() {
$('.save-branch-button').click(function() {
var branchForm = $(this).closest('form');
var serializedform = branchForm.find('.form :input').serializeArray();
console.log(serializedform);
const obj = {};
for(let d of serializedform){
obj[d.name.split('.').pop()] = d.value
}
console.log(obj);
}
Return serialize data to Deserialize then change to you want anything Hope this help you.
console.log(deparam(serializedform));
function deparam(query) {
var pairs, i, keyValuePair, key, value, map = {};
// remove leading question mark if its there
if (query.slice(0, 1) === '?') {
query = query.slice(1);
}
if (query !== '') {
pairs = query.split('&');
for (i = 0; i < pairs.length; i += 1) {
keyValuePair = pairs[i].split('=');
key = decodeURIComponent(keyValuePair[0]);
value = (keyValuePair.length > 1) ? decodeURIComponent(keyValuePair[1]) : undefined;
map[key] = value;
}
}
return map;
}

ASP.NET MVC Controller method receiving empty object from jQuery

I have a jQuery script that captures a form into an object and is supposed to send that object to a controller method. Here's the script:
var modalConfirm = function (callback) {
$("#modal-btn-si").on("click", function () {
callback(true);
$("#modal-confirm").modal('hide');
});
$("#modal-btn-no").on("click", function () {
callback(false);
$("#modal-confirm").modal('hide');
});};
function confirmar(form, text) {
$("#modal-confirm").modal('show');
modalConfirm(function (confirm) {
if (confirm) {
enviar(form);
}
}); };
function enviar(form) {
debugger;
var datos = $('#' + form).serializeArray(),
dataObj = {};
$(datos).each(function (i, field) {
dataObj[field.name] = field.value;
});
if (typeof dataObj["precio"] === "undefined") { dataObj["precio"] = 0; }
$.post("NuevaOpcion", {
contentType: "application/JSON",
data: JSON.stringify(dataObj),
}); }
Note: the script was originally much simpler, but trying to fix the issue I'm describing forced me to divide the code in the functions you see.
I created a model to receive the form's data:
public class NuevaOpcionFormModel {
public NuevaOpcionFormModel() { }
public int Id { get; set; }
public string nombre { get; set; }
public int cantidad { get; set; }
public int precio { get; set; }
public int idrespuesta { get; set; }
public int OptionSelectedItem { get; set; }
}
And the controller's method signature:
[HttpPost]
public ActionResult NuevaOpcion (Dayvo.Presupuestador.Web.Models.Form.NuevaOpcionFormModel nuevaOpcion) { ... }
What I've tried
On the script:
.serialize() instead of .serializeArray().
Not serialize at all.
Passing entire 'form' into object and then to controller.
JSON.stringify (actual state) and not using it.
Stablishing each field in data manually.
Stablishing each field in data manually and apllying JSON.stringify.
On the controller:
[FromForm] & [FromBody]
[Bind]
A single variable for each field, matching names and types.
Everything I've tried ends up with the controller's method receiving nothing. I tracked the script (that's why you're seeing a debugger; breakpoint in it), it gets the object into the array correctly, each field with it's proper value:
But still hits the controller with empty object:
Any clue about what I'm doing wrong is more than welcome. Thanks in advance.
EDIT
As requested, here's the view part I'm capturing into the form:
<div class="panel-footer">
#using (Html.BeginForm("NuevaOpcion", "Home", FormMethod.Post, new { #id = "frm_nueva_opcion" })) {
#Html.HiddenFor(m => m.Id)
<div class="row">
<div class="col-md-6">
<div class="form-group" style="margin-bottom: .7em;margin-top: .7em;">
<button class="btn btn-success btn-xs" type="button" onclick=" $('#row-nueva-opcion').toggle()" id="add-opcion">
<span class="glyphicon glyphicon-plus-sign"></span> Añadir nueva opción
</button>
</div>
</div>
</div>
<div class="row" id="row-nueva-opcion" style="display:none">
<div class="col-md-10">
<label>
<input type="checkbox" id="opcion-extra" onclick=" $('#nuevo-precio').attr('disabled', !this.checked);" />
Es opción extra
</label>
<div class="input-group" style="margin-bottom:1.7em;">
<input type="text" placeholder="Opción" class="form-control" name="nombre" style="max-width:70%;">
<input type="number" placeholder="Cantidad" min="1" value="1" class="form-control" name="cantidad" style="max-width:15%;">
<input type="number" placeholder="Precio" class="form-control" id="nuevo-precio" name="precio" style="max-width:15%;" disabled>
<input type="hidden" name="idrespuesta" id="idrespuesta" value="#listItems.Select(x=>x.Value).FirstOrDefault()" />
<div class="input-group-addon">€</div>
<span class="input-group-btn">
<a class="btn btn-primary" data-title="Confirmación de acción" data-toggle="modal" data-target="#modal_confirm" onclick="confirmar('frm_nueva_opcion')">
<span class="glyphicon glyphicon-floppy-disk"></span> Guardar
</a>
</span>
</div>
</div>
<div class="col-md-8">
<div class="form-group">
<label>
¿Para que pregunta es la opción?
#Html.DropDownList("OptionSelectedItem", listItems, new { #class = "form-control" })
</label>
</div>
</div>
</div>
}
</div>
The jquery $.post() method sends data using the default contentType='application/x-www-form-urlencoded; charset=UTF-8' where the data needs to be PlainObject.
For the DefaultModelBinder to bind to your model, the name/value pairs of the object need to match the model properties, so the format needs to be
var data = { Id: someValue, nombre: anotherValue, .... };
To generate that object, either generate it manually, or better, use the .serialize() method (not .serializeArray()) to correctly serialize all form controls. Change the script to
function enviar(form) {
var data = $('#' + form).serialize();
$.post("NuevaOpcion", data, function(response) {
... // code to execute when the response is returned
});
Note it is not clear what you where expecting with the if (typeof dataObj["precio"] === "undefined") { dataObj["precio"] = 0; } code, but it is unnecessary and can be omitted - your precio property is int and it will have a value of 0 if it is not included in the request.
I also strongly recommend you use the HtmlHelper methods to strongly bind to your model, and to ensure the correct name, value and data-val-* attributes are added for 2-way model binding and client side validation.

get checkbox values from form and add to JSON string using JavaScript

attempting to pull form values and put them into localStorage via JSON string. This code works for everything but checkbox values. How do i also get checkbox values? Please and thanks!
<form id="myForm">
<input type="submit" name="submit" value="submitOrder">
</form>
const userOrder = {};
function getValues(e) {
// turn form elements object into an array
var elements = Array.prototype.slice.call(e.target.elements);
// go over the array storing input name & value pairs
elements.forEach((el) => {
if(el.type !== "submit" && el.type !=="button") {
userOrder[el.name] = el.value;
}
});
// finally save to localStorage
localStorage.setItem('userOrder', JSON.stringify(userOrder));
}
document.getElementById("myForm").addEventListener("submit", getValues);
console.log(localStorage.getItem('userOrder'));
use the .checked attribute of a checkbox to tell if it is checked or not
const userOrder = {};
function getValues(e) {
e.preventDefault();
// turn form elements object into an array
//you can also use Array.from(e.target.elements)
var elements = Array.prototype.slice.call(e.target.elements);
console.log(elements);
// go over the array storing input name & value pairs
elements.forEach((el) => {
if(el.type == "checkbox") {
userOrder[el.name] = el.checked;
}
});
console.log(userOrder);
// finally save to localStorage
//localStorage.setItem('userOrder', JSON.stringify(userOrder));
}
document.getElementById("myForm").addEventListener("submit", getValues);
//console.log(localStorage.getItem('userOrder'));
<form id="myForm">
<input type="checkbox" name="checkbox-0">
<input type="checkbox" name="checkbox-1">
<input type="checkbox" name="checkbox-2">
<input type="submit" name="submit" value="submitOrder">
</form>
You can use JQuery serialize() function.
Then, you can do something like this:
function onSubmit( form ){
var data = JSON.stringify( $(form).serializeArray() ); // <-----------
console.log( data );
return false;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form onsubmit='return onSubmit(this)'>
<input name='user' placeholder='user'><br>
<input name='password' type='password' placeholder='password'><br>
<input type='checkbox' name='remember-me'>
<br />
<button type='submit'>Try</button>
</form>

Send only filled fields via GET

Look at simple form below:
<form method="GET" action="index.php">
<input type="text" name="price_min" >Min
<input type="text" name="price_max" >Max
</form>
When I send form with filled only one field, in my url I get empty values for not filled keys
(ex. index.php?price_min=).
Question:
How to remove empty keys from url?
You can parse serialized string and remove blank values. Then you can use post to necessary api using jQuery.
Sample
JSFiddle
$("#btn").on("click", function() {
var formjson = $("#frmTest").serialize();
var result = formjson.split("&").filter(function(val) {
return val.split("=")[1].length > 0;
}).join("&")
console.log("Serialized String:", formjson);
console.log("Processed String:", result);
// $.get('action.php', formjson, function(response){ ... })
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<form id="frmTest">
<input type="text" name="price_min">Min
<input type="text" name="price_max">Max
</form>
<button id="btn">Test Serialize</button>
Use jQuery to send the fields like this
$('your_form').submit(function() {
var min_price = $("#min_price").val();
var max_price = $("#max_price").val();
var string = "";
if(min_price.length > 0){
string += "min_price="+min_price
}
if(max_price.length > 0){
string += "&max_price="+max_price
}
window.location.href = 'index.php?'+string;
});
Hope it helps!

Trigger NgChecked in Angular JS

I need to work out a way of triggering NgChecked to re-evaluate it's expression after a user submits a form (which reloads the data). Ideally the trigged would be after the data has been reloaded, so the checkbox state is in line with that of the data and the amendments that have been made.
I've tried calling the expression directly after loadData() is called, however to no avail.
Do I instead need to use something like NgUpdate?
Any suggestions would be very much appreciated. Please see my code below:
view.html
<form ng-submit="updateinfo(item.downloadID); showDetails = ! showDetails;">
<input class="form-control" style="margin:5px 3px;" type="text"
ng-model="item.title" value="{{item.title}}"
placeholder="{{item.title}}"/>
<div class="checkbox" style="margin:5px 3px;">
<label for="downloadLive">
<input name="downloadLive" type="checkbox" ng-model="item.dlLive" ng-checked="liveCheckBoxState(item.dlLive);" ngTrueValue="1" ngFalseValue ="0"> Download live
</label>
</div>
<input class="btn btn-default form-control" style="margin:5px 3px;" type="submit"/>
</form>
controllers.js
// a scope function to edit a record
$scope.updateinfo = function(downloadID) {
id = downloadID
var result = $scope.items.filter(function( items ) {
return items.downloadID == id;
});
updatedata = $scope.items
$http({
method : 'PUT',
url : '/view1/downloadedit/'+id,
data : result
});
$scope.loadData();
};
//return correct state checkbox for downloadlive
$scope.liveCheckBoxState = function(dlLive) {
console.log(dlLive);
if (dlLive == 1) {
return true;
} else {
return false;
};
};
// a scope function to load the data
$scope.loadData = function () {
$http.get('/view1/downloadData').success(function (data) {
$scope.items = data;
});
};
$scope.loadData();

Categories