I'm using Ruby with the Sinatra framework. I'm sorta new to html. I create a form, and when I look at my #params hash in post, it is a flat hash, as expected:
#params = { input_name_a => user_input_a, input_name_b => user_input_b}
Is there a way to set up some elements of the page to come back as groups, where a key points to an object of key value pairs (which are inputs), instead of a value? So my #params hash would look like this?
#params = { group_a => { input_name_a => user_input_a, input_name_b => user_input_b} }
thanks
<form accept-charset="UTF-8" action="/clients" method="post">
<input type="text" name="client[name]" value="Acme" />
<input type="text" name="client[phone]" value="12345" />
<input type="text" name="client[address][postcode]" value="12345" />
<input type="text" name="client[address][city]" value="Carrot City" />
</form>
When this form is submitted, the value of params[:client] will be {"name" => “Acme”, “phone” => “12345”, “address” => {"postcode" => “12345”, “city” => “Carrot City”}}. Note the nested hash in params[:client][:address].
Related
I'm stuck with multiple row insertion in laravel. I keep on getting an error which says:
Trying to access array offset on value of type null.
blade.php file:
<tbody>
#forelse($GIV as $GIV)
<tr>
<td> <input type="checkbox" name="status[{{$GIV->id}}]" id="status" value="Issued" ></td>
<td> <input type="text" class="form-control" id="id" name="item_id[{{$GIV->id}}]" hidden="" value="{{$GIV->id}}">{{$GIV->id}}</td>
<td> <input type="text" class="form-control" id="pr_no" name="pr_no[{{$GIV->id}}]" hidden="" value="{{$GIV->pr_no}}">{{$GIV->pr_no}}</td>
<td> <input type="text" class="form-control" id="dep_name" name="dep_name[{{$GIV->id}}]" hidden="" value="{{$GIV->dep_name}}">{{$GIV->dep_name}}</td>
<td> <input type="hidden" class="form-control" id="item_name" name="item_name[{{$GIV->id}}]" value="{{$GIV->item_name}}">{{$GIV->item_name}}</td>
<td> <input type="text" class="form-control" id="description" name="description[{{$GIV->id}}]" hidden="" value="{{$GIV->description}}" >{{$GIV->description}}</td>
<td> <input type="number" class="form-control" id="item_qty" name="item_qty[{{$GIV->id}}]" hidden="" value="{{$GIV->item_qty}}">{{$GIV->item_qty}}</td>
<td> <input type="text" class="form-control" id="unit_measure" name="unit_measure[{{$GIV->id}}]" hidden="" value="{{$GIV->unit_measure}}">{{$GIV->unit_measure}}</td>
<td> <input type="number" class="form-control" id="authorized_qty" name="authorized_qty[{{$GIV->id}}]" hidden="" value="{{$GIV->authorized_qty}}">{{$GIV->authorized_qty}}</td>
</tr>
#empty
<tr><td colspan="16"><center>No Data Found</center</td></tr>
#endforelse
</tbody>
Controller file:
public function addDataGIV(Request $request)
{
$data =request()->all;
foreach(request()->status as $status) {
DB::table('g_i_v_s')->insert(
[
'item_id' =>$data['item_id'][$status],
'item_name' =>$data['item_name'][$status],
'description' =>$data['description'][$status],
'item_qty' =>$data['item_qty'][$status],
'unit_measure' =>$data['unit_measure'][$status],
'authorized_qty'=>$data['authorized_qty'][$status],
'dep_name' =>$data['dep_name'][$status],
'pr_no' =>$data['pr_no'][$status],
]
);
}
}
When a user selects the checkbox and clicks the submit button, I want only the selected checkbox row including the checkbox value to be stored into the database, without any errors.
You're actually quite close, but you're accessing your Array indices wrong; $status, if defined properly, would be Issued, which is not what you want. Also, request()->all is null, but request()->all() (with the ()) would be an Array of your form input; hence the error when trying to use $data[...][...]; later.
This code should work (Note: you don't need $data at all here):
foreach(request()->input('status', []) as $index => $status) {
DB::table('g_i_v_s')->insert([
'item_id' => request()->input("item_id.{$index}"),
'item_name' => request()->input("item_name.{$index}"),
'description' => request()->input("description.{$index}"),
'item_qty' => request()->input("item_qty.{$index}"),
'unit_measure' => request()->input("unit_measure.{$index}"),
'authorized_qty' => request()->input("authorized_qty.{$index}"),
'dep_name' => request()->input("dep_name.{$index}"),
'pr_no' => request()->input("pr_no.{$index}"),
]);
}
Alternative syntax would be request->input('item_id')[$index], like:
foreach(request()->input('status', []) as $index => $status) {
DB::table('g_i_v_s')->insert([
'item_id' => request()->input('item_id')[$index],
'item_name' => request()->input('item_name')[$index],
'description' => request()->input('description')[$index],
'item_qty' => request()->input('item_qty')[$index],
'unit_measure' => request()->input('unit_measure')[$index],
'authorized_qty' => request()->input('authorized_qty')[$index],
'dep_name' => request()->input('dep_name')[$index],
'pr_no' => request()->input('pr_no')[$index],
]);
}
Basically, when looping over request()->input('status', []), you have access to $index, and $status (which is not referenced, but that's ok). $index will be equivalent to whatever $giv->id is on the front-end, and each field exists as an Array Index with that value, so looping and referencing is super easy.
I am trying to add oninvalid attribute in HTML element under React js code. (using react hooks not class based)
const openEndedAnswer = answer => {
return (<>
<input type="text" className="form-control"
required="required"
oninvalid="this.setCustomValidity('Enter User Name Here')"
oninput="this.setCustomValidity('')"
maxLength="255"
id={`answer_${question.id}`}
name={`answer_${question.id}`}
onChange={e => updatePostForm(e)}
pattern=".*[^ ].*"
title=" No white spaces"
/>
</>)
}
But it never renders in the browser. all other attributes can be seen in F12 source view.
The attribute names should onInvalid instead of oninvalid and onInput instead of oninput. Additionally, you need to call the setCustomValidity function on the input field as follow (because the input field is the target of the event):
onInvalid={e => e.target.setCustomValidity('Enter User Name Here')}
onInput={e => e.target.setCustomValidity('')}
If you are using React with javascript this should work:
onInvalid={e => e.target.setCustomValidity('Your custom message')}
onInput={e => e.target.setCustomValidity('')}
But if you are working with React with typescript you also need to add this:
onInvalid={e => (e.target as HTMLInputElement).setCustomValidity('Enter User Name Here')}
onInput={e => (e.target as HTMLInputElement).setCustomValidity('')}
Try onInvalid instead:
export default function App() {
return (
<form>
Name:{" "}
<input
type="text"
onInvalid={() => console.log("working!")}
name="fname"
required
/>
<input type="submit" value="Submit" />
</form>
);
}
The following is written in ASP.NET Razor.
I have a page that dynamically creates lines in an HTML form based on results from a database query. Each row in the result set corresponds to one row in the form. Each row has two input fields that I need to be able to pass via $_POST.
foreach (var #row in list) {
<li>
<span style="width: 100px; display: inline-block">#row.Name</span>
<input type="text" name="time[]" />minutes on
<input type="text" name="date[]" />
</li>
}
My expectation is that I would then be able to access and iterate over the data like this:
var timeList = Request.Form["time"];
foreach (var time in timeList) {
// Stuff
}
But this isn't working. I keep getting an "Object reference not set to an instance of an object" error for timeList. Is what I'm trying to do even possible? Any idea what's wrong?
Try removing the square brackets from your names:
foreach (var #row in list) {
<li>
<span style="width: 100px; display: inline-block">#row.Name</span>
<input type="text" name="time" />minutes on
<input type="text" name="date" />
</li>
}
The loop will create duplicate names which forms arrays in HTML, so you get what you want. However, I'm not sure if that will work when the list has a single item, so test that.
Client HTML:
<form action="~/Page" method="post">
<input type="hidden" name="product_0_id" value="0" />
<input type="text" name="product_0_name" value="Prod. #1" />
<input type="hidden" name="product_1_id" value="1" />
<input type="text" name="product_1_name" value="Prod. #2" />
</form>
Server:
string youGroupKey = "product";
Dictionary<string, string>[] values = Request.Form
.AllKeys
.Where(k => k.StartsWith(youGroupKey))
.GroupBy(k => k
.Substring(youGroupKey.Length + 1, 1),
(a, b) => {
return b
.ToDictionary(c => c
.Substring(youGroupKey.Length + 3), d => Request.Form[d]);
}
)
.ToArray();
I have created one function to add users. The parameters are username,email,password and profile image.
<form name="User" method="post" action="http://192.168.1.100/filmtastic/api/users/adduser" ENCTYPE="multipart/form-data">
<table>
<tr><td><label>username:</label></td><td><input type="text" name="username"></td></tr>
<tr><td><label>password:</label></td><td><input type="text" name="password"></td></tr>
<tr><td><label>email:</label></td><td><input type="text" name="email"></td></tr>
<tr><td><label>Image:</label></td><td><input type="file" name="image"></td></tr>
<tr><td colspan="2" align="center"><input type="submit" name="submit" value="Submit" /></td></tr></table>
</form>
Now in my UserController i have:
public function api_adduser() {
$this->layout = false;
$this->request->data['User']= $this->request->data;
if($this->request->data['User'] != array()) {
pr($this->request->data); die();
}
}
here i debug the data which is passed by that HTML form and optput is like
Array
(
[username] => jack roy
[password] => jack
[email] => jack#yahoo.com
[submit] => Submit
[User] => Array
(
[username] => jack roy
[password] => jack
[email] => jack#yahoo.com
[submit] => Submit
)
)
The problem is that it will not show me the image array. can you tell me how i will get that image array which suppose to look like
Array
(
[image] => Array
(
[name] => 06_01_2009_0692878001231258160_nanzig.jpg
[type] => image/jpeg
[tmp_name] => C:\wamp\tmp\php368F.tmp
[error] => 0
[size] => 81167
)
)
Maybe you simply forgot to set the form mime type to multipart/form-data. Here is my demo view, called add.ctp
<?php
echo $this->Form->create('User', array('enctype' => 'multipart/form-data'));
echo $this->Form->input('name');
echo $this->Form->password('password');
echo $this->Form->input('email');
echo $this->Form->file('image');
echo $this->Form->submit();
echo $this->Form->end();
Here is the UserController
class UserController extends AppController {
public $helpers = array('Html', 'Form');
public function add() {
pr($this->request->data);
}
}
And here is how the result looks like when you submit the form
Array
(
[User] => Array
(
[name] => admin
[password] => admin
[email] => asdf#qwerty.com
[image] => Array
(
[name] => cakephp-book.odt
[type] => application/vnd.oasis.opendocument.text
[tmp_name] => /tmp/phpKniokr
[error] => 0
[size] => 170247
)
)
)
Here is a dump of the generated HTML which you may want to use on your external page (may I ask why???). Note how many things the FormHelper adds... I wonder why you build an external view if your application is still accessing your server directly...
<form action="/test/cakedemo/user/add" enctype="multipart/form-data" id="UserAddForm"
method="post" accept-charset="utf-8">
<div style="display:none;">
<input type="hidden" name="_method" value="POST" />
</div>
<div class="input text">
<label for="UserName">Name</label><input name="data[User][name]"
id="UserName" />
</div><input name="data[User][password]" type="password" id="UserPassword" />
<div class="input text">
<label for="UserEmail">Email</label><input name="data[User][email]" type="text"
id="UserEmail" />
</div><input type="file" name="data[User][image]" id="UserImage" />
<div class="submit">
<input type="submit" value="Submit" />
</div>
</form>
I'm wondering before I attempt to refactor my page if its possible to have a double nested input array in html. I have an 8X5 group of elements in a form and it would be nice for me to be able to parse it using an array of arrays...something like
<input type="text" name="list[][]" /><input type="checkbox" name="list[][]" />
and so on
You are going to need to supply indexes into the first part of each field or else there is nothing to nest, and if it did work, it wouldn't look like a grid on the other end:
Row 1:
name="list[0][]"
Row 2:
name="list[1][]"
etc.
Finally, your server needs to support this as PHP and Rails do out of the box. I am not sure about other server technologies. For an example, the following HTML when posted to PHP:
<form action="post.php" method="POST" accept-charset="utf-8">
<input type="text" name="list[0][]" value="1" />
<input type="text" name="list[0][]" value="2" />
<input type="text" name="list[0][]" value="3" />
<input type="text" name="list[1][]" value="4" />
<input type="text" name="list[1][]" value="5" />
<input type="text" name="list[1][]" value="6" />
<input type="text" name="list[3][]" value="7" />
<input type="text" name="list[3][]" value="8" />
<input type="text" name="list[3][]" value="9" />
<input type="submit" name="Send" value="Send" id="Send" />
</form>
If in the PHP the following code exists:
<?php print_r($_POST['list']); ?>
The output is:
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[1] => Array
(
[0] => 4
[1] => 5
[2] => 6
)
[3] => Array
(
[0] => 7
[1] => 8
[2] => 9
)
)
HTML allows you to have several inputs with the same name, which are sent to the server through POST or GET as a comma separated array, which most (all?) server side languages recognize as a native array.
There is no native way of making a multidimensional array with pure HTML without you rolling something yourself with javascript.