Yii2 DropdownList Value not being sent to Model - yii2

I have a dropdownList which looks like this:
<select id="singleregisterform-titleid" name="SingleRegisterForm[titleId]">
<option value="1">Dr</option>
<option value="2">Miss</option>
<option value="3">Mr</option>
<option value="4">Mrs</option>
<option value="5">Ms</option>
<option value="6">Prof</option>
</select>
When I submit my form I can see this in the app.log file:
'SingleRegisterForm' => [
'titleId' => '1'
'firstName' => 'Kate'
'lastName' => 'Becky'
But when the Model tries to do the save:
$person = new Person();
$person->title_id = $this->titleId;
$person->firstname = $this->firstName;
$person->lastname = $this->lastName;
$person->save();
I get this error:
COLUMN title_id cannot be NULL.
INSERT INTO `person_register` (`title_id`, `firstname`, `lastname`) VALUES (NULL, 'Kate', 'Becky');
Any ideas?

This is very funny. I would have expected Yii2 to not worry about fields which are not part of the validation rules. In this case with my DropDownList, even if the user does not change it, it will still have a value which will be 1, the first one in the list.
Yii2 did not send this back to the Model because I don't have this field as part of the validation rules.
I had to add this to my rules:
['titleId', 'required'],
Now it works perfectly.

Related

Can't figure out a way to add two values from a select element in react

Scenario: I have a react component that allows users to select through different shipping rates. Once a user selects one I want the onChange to get the ID and the amount and I can only figure out how to get just the ID. The select element iterates through an array of rates that is structured like this:
rates = [ {id: 'r8f8hd8', amount: 45}, ...]
Here is the select element:
<select onChange={(e) => console.log(e.target.value)} className='w-8/12 h-14 rounded p-2'>
<option disabled selected hidden>
Pick a shipping rate
</option>
{rates.map((rate, index) => (
<option value={{ id: rate.rateId, amount: rate.amount }} key={index}>
{rate.service} {''}(${rate.amount})
</option>
))}
</select>
I tried setting the option value to an object with the rateId and amount but it just gives me a blank [Object object]
This should fix the issue. A word of advice I wouldn't set the key to just the index. Instead you should use the id that you assigned to the object.
The issue was you we're storing an object as the value. This lead to an issue because value automatically stores a string so your object is converted into a string hence [Object Object]. Mapping already sets its own pre defined object {value:someVal,key:someID}.
Taking your current case into account I believe this is a cleaner way to achieve what you wanted. I've added working code below. Also the extra item in rates was just for testing.
Feel free to comment any questions you have and i'll do my best to answer them.
let rates = [ {id: 'r8f8hd8', amount: 45},{id: 'r8f8hd', amount: 450}]
return (
<select onChange={(e) => console.log(e.target.value)} className='w-8/12 h-14 rounded p-2'>
<option disabled selected hidden>
Pick a shipping rate
</option>
{rates.map((rate) => (
<option value={rate.amount } key={rate.id}>
{rate.service} {''}(${rate.amount})
</option>
))}
</select>
)
Just incase your just dead set on storing multiple values here's a solution to that as well but I would go as far as saying this is just bad code but it does what you wanted. Since map has its own object as I mentioned we can mutate it and give it more characteristics hence id and trueVal that I added. We can use the index and store that as our value and instead of accessing our data through e.target.value we can instead utilize the e.target.options and simply cross reference the index value we stored to make sure we are always accessing the correct position in the array. However please take note of the +1 this is to take the first position into account which is held by the, "Pick a shipping rate".
let rates = [ {id: 'r8f8hd8', amount: 45},{id: 'r8f8hd', amount: 450}]
return (
<select onChange={(e) => console.log(e.target.options[e.target.value])} className='w-8/12 h-14 rounded p-2'>
<option disabled selected hidden>
Pick a shipping rate
</option>
{rates.map((rate, index) => (
<option value={index+1} trueVal={rate.amount} id={rate.id} key={index}>
{rate.service} {''}(${rate.amount})
</option>
))}
</select>
)
}
In html value prop is a string, so value={{ id: rate.rateId, amount: rate.amount }} is converted to string, that's why you are getting [Object object] .
Solution : change your component like this :
.....
const [option, setOption] = React.useState({});
const handlechange = (e)=>{
for (let i = 0; i < rates.length; i++) {
if (e.target.value === rates[i].id) {
setOption({ id: rates[i].id, amount: rates[i].amount });
}
}
}
return (
<select onChange={handlechange} className="w-8/12 h-14 rounded p-2">
<option disabled selected hidden>
Pick a shipping rate
</option>
{rates.map((rate, index) => (
<option value={rate.id} key={index}>
{rate.service} {""}(${rate.amount})
</option>
))}
</select>
);
Now your id and amount of selected option will be stored in option state
this is a demo in codesandbox

How to Save Form with the Dynamic Table having MultiSelect Dropdown in each row in Laravel

Multiselect Drop Down of Color and Size in Dynamic Table with name attribute
In My Form I have Dynamic Table, Having Multi Select Dropdowns with same names color_id[] and size_id[] in each row. I am Not Getting How to save the multi selected values as comma separated values in each row in database. Here I have tried to save in database, but not working.
HTML CODE:
<table><tbody><td><select name="color_id[]" class="select2" id="color_id" style="width:200px; height:100px;" required multiple></select></td><td> <select name="size_id[]" class="select2" id="size_id" style="width:200px; height:100px;" required multiple> </select></td></tbody></table>
Laravel Save Code in Controller:
$class_ids = $request->input('class_ids');
for($x=0; $x<count($class_ids); $x++) {
# code...
$color_ids = implode(',', $request->color_id[$x]);
$size_ids = implode(',', $request->size_id[$x]);
$data3[]=array(
'bom_code'=>$TrNo,
'bom_date'=>$request->bom_date,
'cost_type_id'=>$request->cost_type_id,
'Ac_code'=>$request->Ac_code,
'season_id'=>$request->season_id,
'currency_id'=>$request->currency_id,
'item_code' => $request->item_codes[$x],
'class_id' => $request->class_ids[$x],
'description' => $request->descriptions[$x],
'color_id' => $color_ids,
'size_array' => $size_ids,
'consumption' => $request->consumptions[$x],
'unit_id'=> $request->unit_ids[$x],
'rate_per_unit' => $request->rate_per_units[$x],
'wastage' => $request->wastages[$x],
'bom_qty' => $request->bom_qtys[$x],
'total_amount' => $request->total_amounts[$x],
);
}
BOMSewingTrimsDetailModel::insert($data3);
I have taken two hidden input box having name color_arrays[] and size_arrays[] in every row in the same columns color and size. I wrote below java script function to get comma separated values from multi-select drop-down of color an size. and i save hidden input box values to database.
$(document).on('change', 'select[name^="color_id[]"],select[name^="size_id[]"]', function(){CalculateQtyRowPros2($(this).closest("tr"));});
function CalculateQtyRowPros2(row){
var color_id=row.find('select[name^="color_id[]"]').val().join(",");
var size_id=row.find('select[name^="size_id[]"]').val().join(",");
row.find('input[name^="color_arrays[]"]').val(color_id);
row.find('input[name^="size_arrays[]"]').val(size_id);}
It worked for me.

How can I show in a select values that have the ID that I get from the controller?

I have a select controlled by Thymeleaf
<select th:field="*{customer}">
<option th:each="customer: ${customers}" th:value="${customer.id}" th:text="${customer.name}"></option>
</select>
This select show me all the customers of the DB.
How can I show just the customer with the ID that I get from here:
#GetMapping("/add")
public String addRoute(Model model) {
model.addAttribute("route", new RouteCommand());
/*User userAux = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
model.addAttribute("customer", userAux.getCustomer().getId());*/
return "admin/routes/add";
}
The code that is commented get the ID of the value that I want to show in the select.
I am not sure below works but you can try as I do not have a workspace to test the solution and also I assume you are using Spring Security Tag and user is logged in
<sec:authentication property="principal.customer.id" var="cId" scope="page" />
<select th:field="*{customer}">
<option th:each="customer: ${customers.?[id == __${cId}__]}" th:value="${customer.id}" th:text="${customer.name}"></option>
</select>

Conditionally deciding which option is selected in blade

Im displaying a form as a representation of data in my database. Im using a form because the data is editable by certain users.
The form contains a dropdown list:
<select name="Status" id="Status">
<option id="confirmed" value="Confirmed">Confirmed</option>
<option id="completed" value="Completed">Completed</option>
<option id="released" value="Released">Released</option>
<option id="deleted" value="Deleted">Deleted</option>
</select>
When loading the view I pass in a variable '$status' which is from the database. How do I set the 'selected' attribute for which ever option $status is equal to?
Im using blade tempting engine
if you're using blade template you may want to use the Form helper to build your form fields, pass an array of items to be listed as dropdown options on the 2nd parameter and at the 3rd parameter pass your selected value, see the code below for reference
From controller:
$selectedValue = "confirmed";
$statuses = array(
array("id"=> "confirmed", "value" => "Confirmed"),
array("id"=> "completed", "value" => "Completed"),
array("id"=> "released", "value" => "Released"),
array("id"=> "deleted", "value" => "Deleted"),
);
return view("yourview")->with("statuses", $statuses)->with("selectedValue", $selectedValue);
On your view you could do something like below:
{!! Form::select('status', $statuses , $selectedValue, ['class' => 'form-control', 'id' => 'status']) !!}
Note: the code is untested but should work in your case.
Also please check https://laravelcollective.com/docs/5.2/html

Issue when trying to populate a drop-down with database values

I am using the following HTML to show a selected drop down with values from the database and rest of the others in the list. It shows the selected name correctly but the selected is also displayed in the list.
How to remove the second time show selected name in the drop down list? Is this a good way to use drop down menu? Here Jobcategory and Jobdetails are associated.
Im using Laravel 4.2 and this is the HTML:
// view drop down form to save data
<div class="large-6 columns">
<label>Job Category
<select name="category[]">
<option value="">Select Category</option>
#foreach(JobCategory::all() as $jcat)
<option value="{{ $jcat->id }}">{{ $jcat->name }}</option>
#endforeach
</select>
</label>
</div>
// Edit drop down form to update the selected value
<div class="large-6 columns">
<label>Job Category
<select name="category[]">
<option value="{{$jobedit->jobcategory->id}}">{{$jobedit->jobcategory->name </option>
#foreach(JobCategory::all() as $jcat)
<option value="{{ $jcat->id }}">{{ $jcat->name }}</option>
#endforeach
</select>
</label>
</div>
// database table for jobcategories
id | name
1 | Accounting/Finance
2 | Advertisement/Event Mgt.
3 | .....
// after save into jobdetails table
id | jobcategory_id | .......
1 | 5 | ...
I can retrieve the value of jobcategory in the edit form but it shows twice one in the selected value and other in the listed value of all jobcategory. This is the problem and i want only show the selected value and then rest of the others from jobcategory table without duplicate value of selected in the drop down. plz help.
// controller to to edit
public function getJobEdit($id)
{
$jobedit = JobDetail::find($id);
return View::make('employers.edit_single_jobs')->with('jobedit', $jobedit);
}
// JobDetail --model
public function jobcategory()
{
return $this->belongsTo('JobCategory');
}
// JobCategory --model
public function jobdetails()
{
return $this->hasMany('JobDetail', 'jobcategories');
}
Have a look at the Forms & HTML helper of laravel.
Generating A Drop-Down List With Selected Default
echo Form::select('size', array('L' => 'Large', 'S' => 'Small'), 'S');
where the first argument is the name of the select box. The second argument is an array of all entries in the box and the last argument determines which of the array elements is the selected one.
in your case it could look something like this:
{{ Form::select(
'categoryName',
array(
'Accounting/Finance' => 'Accounting/Finance',
'Advertisement/Event Mgt.' => 'Advertisement/Event Mgt.',
// to be continued ...
),
'$cat->category_name'
); }}
//Edit
<div class="large-6 columns">
<label>Job Category
{{ Form::select('category[]', ['' => 'Select a category'] + $all_categories, $jobedit->jobcategory->id) }}
</select>
</label>
</div>
where $all_categories should be an array of all categories as in the first example. You can get this from JobCategory::all().
This is how I set up drop-downs in my projects. I prepare the data in my controller (you'd obviously need a route and controller set up for this, I'm assuming you've done that):
Controller
public function index()
{
$categories = \Category::lists('name', 'id')->orderBy('name'); // assuming you have a Category model
view('categories', compact('categories'));
}
Then you can use the Forms and HTML helper as Peh mentioned, this isn't available as a default in Laravel 5 so you'd need to add it into your project using composer. To do so either run composer install illuminate/html or add "illuminate/html": "~5.0" to your composer.json file and then run composer install. You'd then need to add 'Illuminate\Html\HtmlServiceProvider' to config/app.php in the providers array then add 'Form' => 'Illuminate\Html\FormFacade' and 'HTML' => 'Illuminate\Html\HtmlFacade' to the aliases array in the same file. Once that's sorted you can use the Form and HTML helper in your view, as so:
View
{{ Form::select('categoryName', ['' => 'Select a category'] + $categories) }}
Your view would need to be saved as filename.blade.php if using the handlebars, otherwise echo it within <?php ?> tags.
Hope that helps you on your way.