HTML Form: POST an array of objects - html

Submitting a class roster. Adding 3 students at once. Each student has first, last, age.
Question: How can we get all of the students in an array of arrays?
students[0] => Array (
["first"] => "first name for 0",
["last"] => "last name for 0",
["age"] => "age for 0"
),
students[1] => Array (
["first"] => "first name for 1",
["last"] => "last name for 1",
["age"] => "age for 1"
),
...
Details
For one student:
<input type="text" name="first">
<input type="text" name="last">
<input type="text" name="age">
We can return multiple students in separate arrays like this:
<input type="text" name="students[first][]">
<input type="text" name="students[last][]">
<input type="text" name="students[age][]">
which returns an array of firsts, lasts and ages
students["first"] = [array of first names]
students["last"] = [array of last names]
students["age"] = [array of ages]
Theoretically we can get all the info for a student by accessing the same index (say "3" for each array).
We do not want to programatically add an index in the form.
Do not want:
<input type="text" name="students[hardcoded_index][first]">
<input type="text" name="students[hardcoded_index][last]">
<input type="text" name="students[hardcoded_index][age]">
If for any reason it matters, we are using Rails for views but can use form helpers or HTML.

tl;dr: Add empty brackets ([]) after students to the input names.
Fiddling with Rack::Utils.parse_nested_query it seems you can get the payload you want like this:
<!-- first student -->
<input type="text" name="students[][first]">
<input type="text" name="students[][last]">
<input type="text" name="students[][age]">
<!-- second student -->
<input type="text" name="students[][first]">
<input type="text" name="students[][last]">
<input type="text" name="students[][age]">
Note the empty brackets ([]) after students. This tells Rack you want the students param to be an array. Subsequent params encountered (with the same name) will start a new element.
POST /myroute?students[][first]=foo&students[][last]=bar&students[][age]=21&students[][first]=baz&students[][last]=qux&students[][age]=19
Gets parsed like this:
{"students" => [
{
"first" => "foo",
"last" => "bar",
"age" => "21"
},
{
"first" => "baz",
"last" => "qux",
"age" => "19"
}
]}
Further reading: http://codefol.io/posts/How-Does-Rack-Parse-Query-Params-With-parse-nested-query

I know the question is old , but I would like to add my experiences
also for future readers.
For those of you who want to process the data in a PHP enviroment ,
#messanjah's method won't work ,
The methods for parsing data like the built-in serializeArray or serialize are not parsing it as expected either.
This is what I tried so far ...
students[name]
students[][name] - Very Strange since it was meant to automatically index the array
students[name][]
Neither of them worked, but this students[<hardcoded-index>][name] worked for PHP ,
I know that although the question is against this method , but it
will be useful for PHP users who will land here in the nearby future
as the asker needed it for Ruby On Rails.
The method you choose to hard code the indexes is upto you , you can use a cleaner method by using javascript or you can manually hard code them initially in your form element.
Cheers

Related

How do I validate a checkbox array in laravel?

I've been trying to validate all 10 checkbox array items but I cannot seem to find or understand how to use Laravels validator to validate a checkbox array.
The below code is my array HTML.
<div id="CLAagree" style="display: none;">
<div class="form-group form-check">
<div class="col-sm-2">
<div class="checkbox checkbox-green ck-button">
<input type="checkbox" class="form-check-input" oninput="this.className = ''" name="claAgree[]" id="CLAagreeCB1" onclick="saveOnboard()" >
</div>
</div>
</div>
I have tried to get all info that I can about this but I just can't seem to understand arrays in validation for some reason.
I know adding "required" made the inputs required but I have 10 so at least one will be required but I need 10 to be required. Does anyone have any options? I'm just lost at this point lol
$rules = array(
"claAgree" => "required",
"claAgree.*" => "required",
);
$validation = Validator::make($request->all(),$rules);
if($validation->fails()) return back()->with('error',$validation->messages()->first());
Here is a link to show how the array is posted
You can do like that ,check you request array name (claAgree.*.claAgree) ,
then define the input value , if same then you can use same like that
$rules = array(
"claAgree" => "required",
"claAgree.*.claAgree" => "required",
);
$validation = Validator::make($request->all(),$rules);
if($validation->fails()) return back()->with('error',$validation->messages()->first());

How to display complex object attributes in form fields in angular

I have a JSON object with the structure below which I want to display in a form for edit when I clicked on edit button on my table row.
json
{
"id": 123,
"name": "Paul",
"cars": [
{
"type": "toyota",
"year": "2013"
},
{
"type": "audi",
"year": "2010"
}
]
}
I need help on how to display the type of each cars object in my table file separated by comma(,). I got the object id and name displayed but not attributes in the cars array. How do I complete my .ts code so that the type of each car could show up in my table.
.ts
showRowDetail( data: any ) {
this.formData.controls.id.setValue( data.id );
this.formData.controls.name.setValue( data.name );
//how do I update here to set the cars: types
}
.html
<div class="form-group">
<label>ID:</label> <input type="text" class="form-control"
formControlName="id">
</div>
<div class="form-group">
<label>Name:</label><input type="text" class="form-control"
formControlName="name">
</div>
<div class="form-group">
<label>Cars:</label> <input type="text" class="form-control"
formControlName="cars">
</div>
I omitted the *ngFor table code, the showRowDetail function is used on the edit button, which when clicked it opens a modal that present the form where the object data are shown. data.id and data.name fields are working, just the cars type I needed help with.
how to display the "type" of each "cars" object in my table file
seperated by comma(,)
Generate comma separated type values from carsarray using map() and join().
showRowDetail( data: any ) {
this.formData.controls.id.setValue( data.id );
this.formData.controls.name.setValue( data.name );
let types = data.cars.map(car => car.type).join(", ");
this.formData.controls.cars.setValue(types);
}

Check_box_tag input id

I have a check_box_tag that looks like this :
check_box_tag('shipping_method[shipping_categories][]', category.id,
#shipping_method.shipping_categories.include?(category))
When inspecting the output in browser, I have the following :
<input id="shipping_method_shipping_categories_"
name="shipping_method[shipping_categories][]" type="checkbox" value="1" />
I don't get why the id has no "id", meaning that the underscore at the end of
id="shipping_method_shipping_categories_"
makes me expect an id for this particular shipping_category.
Any of you guys and gals have thoughts on this ?
Thanks !
I don't get why the id has no "id", meaning that the underscore at the
end of id="shipping_method_shipping_categories_" makes me expect an id
for this particular shipping_category.
That is the default behavior of the check_box_tag. In other words it is constructed that way. When you look upon the code of how it is constructed, you will see the below
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 374
def check_box_tag(name, value = "1", checked = false, options = {})
html_options = { "type" => "checkbox", "name" => name, "id" => sanitize_to_id(name), "value" => value }.update(options.stringify_keys)
html_options["checked"] = "checked" if checked
tag :input, html_options
end
So, the "id" is constructed with the method sanitize_to_id(name). So I've further looked upon sanitize_to_id(name) to see its code and I've found this
def sanitize_to_id(name)
name.to_s.delete("]").tr("^-a-zA-Z0-9:.", "_")
end
So, shipping_method[shipping_categories][].to_s.delete("]").tr("^-a-zA-Z0-9:.", "_") returns shipping_method_shipping_categories_. That explains its behavior.
If you want to achieve what you are expecting, I recommend you to go with collection_check_boxes
For example,
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial)
returns
<input id="post_author_ids_1" name="post[author_ids][]" type="checkbox" value="1" checked="checked" />

Sinatra: wrong number of arguments (4 for 0..2)

I'm currently developing an app with Sinatra, ActiveRecord and MySQL. I'm working on the sign up form, which looks like this:
app.rb:
post '/signup' do
password_salt = BCrypt::Engine.generate_salt
password_hash = BCrypt::Engine.hash_secret(params[:password], password_salt)
#usuarios = User.new(params[:nombre], params[:cedula], password_hash, "admin")
if #usuarios.save
redirect './signup', :notice => "Usuario creado exitosamente."
else
redirect './signup', :error => "Ha ocurrido un error, intente nuevamente."
end
end
And the view looks like this, signup.erb:
<form id="registro" action="/signup" method="POST">
<fieldset>
<legend>Ingrese sus datos</legend>
<label>Nombre
<input type="text" name="nombre">
</label>
<label>Cédula
<input type="text" maxlength="10" name="cedula">
</label>
<label>Contraseña
<input type="password" name="password">
</label>
<!-- TO-DO:
Dropdown list con los diferentes tipos de usuarios, i.e.: admin, secretario, etc.
-->
<input type="submit" id="registerButton" class="button small">Finalizar registro</a>
</fieldset>
</form>
Whenever I try to create a new user, I get the following error:
ArgumentError - wrong number of arguments (4 for 0..2)
Considering that the table I'm trying to insert the values has 4 columns, I don't understand why I'm getting this error.
Any insight to help me solve this inconvenience would be greatly appreciated!
Thanks in advance.
ActiveRecord::new method allows only 2 parameters as arguments, it should be a hash. fix:
User.new(params[:nombre], params[:cedula], password_hash, "admin")
to:
User.new(nombre: params[:nombre], cedula: params[:cedula], password: password_hash, role: "admin")
You should always check the documentation, in 99% cases you can find a problem:
New objects can be instantiated as either empty (pass no construction
parameter) or pre-set with attributes but not yet saved (pass a hash
with key names matching the associated table column names). In both
instances, valid attribute keys are determined by the column names of
the associated table – hence you can’t have attributes that aren’t
part of the table columns.
new(attributes = nil, options = {})
Examples:
# Instantiates a single new object
User.new(:first_name => 'Jamie')
# Instantiates a single new object using the :admin mass-assignment security role
User.new({ :first_name => 'Jamie', :is_admin => true }, :as => :admin)
# Instantiates a single new object bypassing mass-assignment security
User.new({ :first_name => 'Jamie', :is_admin => true }, :without_protection => true)

Is there an HTML 5 way of submitting fields with the same name but different identifiers?

I would like to submit multiple ROWS of field columns using an HTML form with the only difference being the corresponding server side identifier.
Pseudo:
ID(257) -> Name, Color, Price
ID(415) -> Name, Color, Price
I prefer NOT to:
Have each group as its own form and submit via JavaScript.
Concatenate the id and real name and unmerge on the server.
Thanks
You can use the same input name when attaching a [] to it, in PHP this will result in an array on submission:
<?php
print_r($_POST);
?>
<form method="post">
<input type="text" name="name[257]">
<input type="text" name="name[415]">
<input type="submit">
</form>
Result:
Array
(
[name] => Array
(
[257] => first field
[415] => second field
)
)
If you're using PHP as your server side language this is easy. Just name your fields with brackets which is array syntax in PHP:
Pseudo code:
name[1] = 'Name, Color, Price'
name[2] = 'Name, Color, Price'