Laravel 4 display list of data into form selection - php

How do I display a list of books in laravel form builder selection?
BookController.php
$book_names = Book::all();
return View::make('books')->with('book_names', $book_names);
At the moment I only know how do manually input data:
{{ Form::select('book_name', array(
'book1' => 'book1',
'book2' => 'book2',
'book3' => 'book3')
}}
I want to do something like this:
{{ Form::select('book_name', array(
#foreach($book_names as $book_name)
$book_name->name => $book_name->name,
#endforeach
}}
But obviously It won't work..

Meet the lists() method. It allows you to create an array from one or two (key and value) properties of a collection:
$book_names = Book::lists('name');
return View::make('books')->with('book_names', $book_names);
And then simply pass that array:
{{ Form::select('book_name', $book_names) }}

Related

Get selected value from drop down Laravel 4

I want to get the selected value from a drop down list in a controller method.
The drop down list :
{{ Form::select('Organization', $organization_list ,Input::old('Organization'), array('class' => 'form-control')) }}
$organization_list is an array of organizations..
I have tried to catch the selected item of this drop down list in a controller as follows:
Input::get('Organization');
But it gives me the array index instead of the real organization name..But the real organization name is shown in drop down list.. does anyone have a solution?
Pass an associative array To Form::select as the second argument
$organization_list = array_combine($organization_list, $organization_list); //Copies the array values to keys
{{ Form::select('Organization', $organization_list ,Input::old('Organization'), array('class' => 'form-control')) }}
http://php.net/array-combine

Laravel Select Box

I'm trying to figure out how I can structure my Laravel select menu so that it shows up as this for a final render. Has anyone done such a thing.
The location is a property of the arena object.
<option value="arena_id">Arena Name - Location</option>
{{ Form::select('arena_id', [ null => 'Please Select'] + $arenas, null, ['id' => 'arena_id']) }}
I asssume $arenas comes from something like Arena::where('foo', bar)->get(), but with get() you will get an instance of Illuminate\Database\Eloquent\Collection instead of an actual array which is what you want in Form::select.
So what you need to do is to use lists($field, $key), it will fetch you rows and return it as an array.
$arenas = Arena::where('foo', bar)->lists('name', 'id');
There is a code example here with some comments from users if you want to learn more.
You can use pluck function for getting the results as array
refer https://laravel.com/docs/5.1/collections#method-pluck
$select = $this->all()->pluck('title', 'id');
Then you can use below sample code for creating select box with selected option in blade template
{{ Form::select('name',$select,'selected option id',['class' => 'form-control']) }}

perplexing check box behavior

I have a edit form with some checkboxes that I am trying to make checked when the associated many to many relationship is established.
Distributors belong to many beers
Beers belong to many distributors
in my controller I have:
$breweries = Brewery::lists('name', 'id');
$all_dist = Distributor::all();
$beer = Beer::find($id);
$distributions = [];
foreach ($beer->distributors as $distributor)
{
$distributions[$distributor->id] = BeerDistribution::where('beer_id', '=', $beer->id)
->where('distributor_id', '=', $distributor->id)->first()->price;
}
return View::make('beers.edit', ['beer' => $beer, 'distributors' => $all_dist, 'distributions' => $distributions, 'breweries' => $breweries, 'styles' => $styles]);
and I in my edit form I have:
{{ Form::model($beer, ['route' => ['beers.update', $beer->id], 'method' => 'PATCH']) }}
#foreach ($distributors as $distributor)
<?php $carried = in_array($distributor->id, array_keys($distributions)) ? true : false ?>
{{ Form::checkbox('distributors[]', $distributor->id, $carried); }}
{{ Form::label($distributor->name) }}
{{ Form::label('price' . $distributor->id, 'Retail:') }}
<?php $price = $carried ? $distributions[$distributor->id] : null ?>
{{ Form::text('price' . $distributor->id, $price ) }}
#endforeach
{{ Form::submit('Save') }}
{{ Form::close() }}
Basically I am passing an associated array of each distributor_id => price. This array also tells me which distributors the beer already belongs to so that I can mark those checked off in my edit form.
Here's where things get wonky. When I load this form, all the checkboxes will be checked no matter what. If I change my controller loop to this:
foreach ($beer->distributors()->lists('distributor_id') as $distributor_id)
Then I can do create my array.
Why does calling $beer->distributors in the controller would result in all the checkboxes being checked?
The problem is with the last argument : $carried
{{ Form::checkbox('distributors[]', $distributor->id, [ "checked" => $carried ]); }}
Pass the last parameter as array, and tell it exactly which attribute to modify and the attribute value.

Laravel form model binding for many to many select input

I have a many to many relationship between clients and assets.
For my edit client form I have multi-select box with which the user can select several assets to attach to a client. The form is using model-binding so it automatically populates the fields with the existing client data.
The model binding works for all fields in the form except the multi-select. Here is a snippet from my view:
{{ Form::model($client, ['route' => ['clients.update', $client->id], 'class' => '', 'method' => 'put']) }}
{{ Form::label('name', 'Name', $label_attributes) }}
{{ Form::text('name', null, array('class'=>'form-control')) }}
{{ Form::label('assets', 'Client Benchmarks (Select multiple)', $label_attributes) }}
{{ Form::select('assets[]', $assets, null, array('multiple' => true, 'class' => 'form-control')); }}
When I submit the form the relationship saves the data successfully via the sync method in my controller (update method):
$client = Client::find($id);
$client->name = Input::get('name');
$assets = Input::has('assets') ? Input::get('assets') : array();
$client->assets()->sync($assets);
$client->save();
Also, if I output the client assets directly they are accessible in the model collection in my form view:
<?php print_r($client->assets); ?>
How can I get the form to populate the select box with the existing selections?
echo Form::select('assets[]', $assets, array(1,2), array('multiple' => true));
As far as I know it won't set all selected values by default for you even when using form
model binding
This is what the native formBuilder method looks like:
public function select($name, $list = array(), $selected = null, $options = array())

Nesting Models Relations In Forms - Laravel

In laravel, is there some way of nesting related resources in a form?
Say I have this:
class Person extends Eloquent {
public function addresses() {
return $this->hasMany("Address");
}
}
class Address extends Eloquent {
public function person() {
return $this->belongsTo("Person");
}
}
and I want a Person form to collect information about that Person's Addresses. Does laravel facilitate this in a way that is equivalent to Rails' accepts_nested_attributes_for :address and fields_for :address?
I'd just like something simple where I can include the Address fields with the results of the Person form, since the Address doesn't really exist apart from the Person. Does this make sense?
== EDIT ==
This is hypothetical code
What I'm looking for is something that would resemble this:
{{ Form::model(new Person, array("action" => "admin\PersonController#store", "method" => "POST")) }}
{{ Form::text("name", array(...)) // <input name='person[name]' ... /> }}
{{ Form::email("email", array(...)) // <input name='person[email]' ... /> }}
{{ Form::fields_for("addresses"/* Would be name of relation */) }}
{{ Form::text("street_address") // <input name='person[addresses][][street_address]' ... /> }}
{{ Form::close_fields() }}
{{ Form::close() }}
You are on the right track with the input names.
Form
// Form open, Person fields, etc...
<h2>Addresses</h2>
#foreach ($addresses as $address)
<fieldset>
{{ Input::text('addresses['.$address->id.'][address_1]', $address->address_1) }}
{{ Input::text('addresses['.$address->id.'][address_1]', $address->address_2) }}
{{ Input::text('addresses['.$address->id.'][city]', $address->city) }}
{{ Input::text('addresses['.$address->id.'][state]', $address->state) }}
{{ Input::text('addresses['.$address->id.'][zip]', $address->zip) }}
</fieldset>
#endforeach
// Form Close
If you want to add addresses you'll need to generate some random key to use instead of the address id. This will keep the fields grouped.
Controller Logic
This is how I would handle input, using 'fillable' to filter the data going into the models.
// Get the Person model, fill, save, etc...
$addressIds = array();
foreach (Input::get('addresses', array()) as $id => $addressData)
{
$address = Address::find($id) ?: new Address;
$address->fill($addressData);
$address->save();
$addressIds[] = $address->id;
}
$changes = $person->addresses()->sync($addressIds);
// Delete the unused addresses
foreach ($changes['detached'] as $detachedAddressId)
{
$address = Address::find($detachedAddressId);
if (!empty($address)) $address->delete();
}
Now you can use the package "modelform" to create a form for various models or even a set of forms for relations.
https://github.com/andersondanilo/modelform
You should manage all of this from your controller. Collect the data from the form and use them as you please:
// Controller Code
$person = new Person(array(
'field_1' => Input::get('field_1'),
'field_2' => Input::get('field_2'),
.............
));
$person->save();
$address = new Address(array(
'field_x' => Input::get('field_x'),
'field_y' => Input::get('field_y'),
.............
));
$person->addresses()->save($address);
See it in the docs

Categories