I’ve been making a fair few forms with the Laravel form-builder using model-binding. A few times I’ve had to make the user select a value for a one-to-many relation.
What’s the problem with model-binding and select-boxes?
In this example we’ll go with the status for a key (‘on loan’,’ at home’, or ‘broken’). The natural choice is a select-box, where the current state should already be chosen if we are editing the key.
The immediate solution is to just use the ‘state’-property for the model-binding
{{Form::select('keystatus', $keyStatus, null)}}
However, if you send a collection of models to a select box, you will end up with a weird box:
As you can see, this is the JSON-representation of the models – this won’t work.
The solution
This first obstacle is solved through a simple foreach-loop:
$statuses = Keystatus::all();
foreach($statuses AS $status){
$statusList[$status->id] = $status->status;
}
$view->with(array('statuses'=>$statusList));
This is taken from my composer-file. As you can see, I get a nice array with the id for key and whatever text I want as the value.
Next step is to put it in the select-box and make the Laravel model-binding work it’s magic.
The tricky thing is, that the status on my key is an object, and doesn’t match whatever is in my array. Instead I put the status_id as the name of my select-box. This way the value in my status_id-column will match one of the keys in the array:
{{Form::select('status_id', $key, null)}}
Don’t forget to set the third parameter (default chosen value) to null. This allows the model-binding to work its magic. The last thing to do, is to adapt my controller to either save the id directly in the status_id-property, or load the status using Status::find($input[“status_id”]); and then associate that to the key:
//Either do this $key->keystatus_id = $input["keystatus_id"]; //Or do this: $state = KeysStatus::find($input["keystatus_id"]); $key->keystatus()->associate($state);
Personally I prefer the first method, as it save me a few calls to the database.