Reputation: 1416
I'm trying to serialize a form that can contains an array of object and send it to my application service and i cannot find any way to make it work...
Here is my Save Method
var brewer = _$form.serializeFormToObject();
abp.services.app.brewer.create(brewer).done(() => {
...
});
// brewerService
serviceNamespace.create = function(brewerDto, ajaxParams) {
return abp.ajax($.extend({
url: abp.appPath + 'api/services/app/brewer/Create',
type: 'POST',
data: JSON.stringify(brewerDto)
}, ajaxParams));
};
Here is my form
<form name="AddBrewerForm" role="form" novalidate class="form-validation">
<ul class="nav nav-tabs tab-nav-right" role="tablist">
<li role="presentation" class="active">
<a href="#brewer-detail" data-toggle="tab">@L("BrewerDetails")</a>
</li>
<li role="presentation">
<a href="#beers-list" data-toggle="tab">@L("Beers")</a>
</li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane animated fadeIn active" id="brewer-detail">
<div class="row clearfix" style="margin-top:10px;">
<div class="col-sm-12">
<div class="form-group form-float">
<div class="form-line">
<input id="name" type="text" name="Name" required class="validate form-control" />
<label for="name" class="form-label">Name</label>
</div>
</div>
</div>
</div>
</div>
<div role="tabpanel" class="tab-pane animated fadeIn" id="beers-list">
<div id="beer-list-content">
<div class="brewer-beer-card row form-group form-float" style="border: 1px solid black;">
<div class="col-md-10">
<div class="form-line">
<input id="beer-0" type="text" name="Beers[0].Name" required class="validate form-control" />
<label for="beer-0" class="dynamic-beer-label form-label">@L("Name")</label>
</div>
</div>
</div>
<div class="brewer-beer-card row form-group form-float" style="border: 1px solid black;">
<div class="col-md-10">
<div class="form-line">
<input id="beer-1" type="text" name="Beers[1].Name" required class="validate form-control" />
<label for="beer-1" class="dynamic-beer-label form-label">@L("Name")</label>
</div>
</div>
</div>
</div>
<div class="row" style="margin-top: 10px;">
<div class="col-sm-12 ">
<button type="button" id="add-beer-button" class="btn btn-primary waves-effect">
@L("Add")
</button>
</div>
</div>
</div>
</div>
</form>
ApplicationServiceDto
public class InsertBrewerDto
{
[Required]
[StringLength(128)]
public string Name { get; set; }
public List<NewBrewerBeerDto> Beers { get; set; }
}
public class NewBrewerBeerDto
{
[Required]
public string Name { get; set; }
}
jquery plugin of ABP for serialization
$.fn.serializeFormToObject = function () {
//serialize to array
var data = $(this).serializeArray();
//add also disabled items
$(':disabled[name]', this).each(function () {
data.push({ name: this.name, value: $(this).val() });
});
//map to object
var obj = {};
data.map(function (x) { obj[x.name] = x.value; });
return obj;
};
I Keep receiving null for my arrays of Beers...
So I've tried to use the $(form).serialize() but i'm getting this error: Your request is not valid!
So there is no error shown...
Here is the Log file WARN 2017-09-30 10:53:13,458 [31 ] nHandling.AbpApiExceptionFilterAttribute - Method arguments are not valid! See ValidationErrors for details. Abp.Runtime.Validation.AbpValidationException: Method arguments are not valid! See ValidationErrors for details. at Abp.Runtime.Validation.Interception.MethodInvocationValidator.ThrowValidationError() at Abp.Runtime.Validation.Interception.MethodInvocationValidator.Validate() at Abp.WebApi.Validation.AbpApiValidationFilter.d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Abp.WebApi.Auditing.AbpApiAuditFilter.d__4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ActionFilterResult.d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Abp.WebApi.Security.AntiForgery.AbpAntiForgeryApiFilter.d__10.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Abp.WebApi.Authorization.AbpApiAuthorizeFilter.d__7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.AuthenticationFilterResult.d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ExceptionFilterResult.d__0.MoveNext() WARN 2017-09-30 10:53:13,458 [31 ] nHandling.AbpApiExceptionFilterAttribute - There are 1 validation errors: WARN 2017-09-30 10:53:13,458 [31 ] nHandling.AbpApiExceptionFilterAttribute - (brewerDto)
Javscript Console Error:
{code: 0, message: "Your request is not valid!", details: "The following errors were detected during validation. ↵ - ↵", validationErrors: Array(1)} code : 0 details : "The following errors were detected during validation. ↵ - ↵" message : "Your request is not valid!" validationErrors : Array(1) 0 : members : Array(1) 0 : "brewerDto" length : 1 message : ""
EDIT1
JS for getting console
var b1 = _$form.serialize();
var b2 = _$form.serializeArray();
var b3 = _$form.serializeFormToObject();
console.log(b1);
console.log(b2);
console.log(b3);
b1
Name=123&Beers%5B0%5D.Name=123&Beers%5B1%5D.Name=321
b2
(3) [{…}, {…}, {…}]
0:{name: "Name", value: "123"}
1:{name: "Beers[0].Name", value: "123"}
2:{name: "Beers[1].Name", value: "321"}
length:3
b3
{Name: "123", Beers[0].Name: "123", Beers[1].Name: "321"}
Beers[0].Name :"123"
Beers[1].Name : "321"
Name : "123"
Upvotes: 1
Views: 3739
Reputation: 43073
Try this:
$.fn.serializeFormToObjectWithArraysOfObjects = function () {
var obj = $(this).serializeFormToObject();
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var result = key.match(/(.*)\[(\d)\].(.*)/);
if (result) {
var outer = result[1];
var index = result[2];
var inner = result[3];
obj[outer] = obj[outer] || [];
obj[outer][index] = obj[outer][index] || {};
obj[outer][index][inner] = obj[key];
delete obj[key];
}
}
}
return obj;
};
Output:
{Name: "123", Beers: [{Name: "123"}, {Name: "321"}]}
Upvotes: 2
Reputation: 2217
Have you considered using JSON and iterating over the form inputs manually?
There are many ways to serialise forms into a JSON Object, and they depend on the actual markup and the form names, this example relies on the "id" parameter to be set(and as best practise, make them equal to the field name:
<input name="example" id="example" />
There are other strategies, but I like this one because we can be explicit about what we want to send to the server:
var list_of_fields = ["f1","f2","f3"];
and we can apply simple validation rules here before sending them.
Some example code:
var list_of_fields = ["f1","f2","f3"];
var serialised_values = {}
for(var i=0;i<list_of_fields.length;i++){
var dom_object = document.getElementById(list_of_fields[i]);
if(dom_object.tagName == "INPUT" || dom_object.tagName == "TEXTAREA"){
serialized_values[dom_object.name] = dom_object.value;
}
if(dom_object.tagName == "SELECT"){
serialized_values[dom_object.name] = dom_object.options[dom_object.selectedIndex].value;
}
//other field types go here
//validation can go here too...
}
console.log(serialized_values);
Upvotes: 1