Laravel 5.2 How to populate edit form with multiple select? - laravel

I want to create a zone which contain few cities. So I decided to use jQuery Select2
Here is my create form multiple selection
<div class="form-group {{ $errors->has('cities') ? 'has-error' : '' }}">
<label>Tentukan Kota</label>
<select name="cities[]" class="city form-control" data-placeholder="Pilih Kota" style="width: 100%;" multiple="multiple">
#foreach($cities as $city)
<option value="{{ $city->id }}">{{ $city->name }}</option>
#endforeach
</select>
</div>
I can multiple select just like in documentation.
Here is my controller which handle display create form
public function zone_create()
{
$cities = City::where('zone_id', null)->get();
return view('backend.admin.pricings.zone_create', compact('cities'));
}
The relationship is One Zone Has Many City.
class Zone extends Model
{
protected $fillable = [
'name',
];
public function cities(){
return $this->hasMany(City::class);
}
}
The city belongs to zone
class City extends Model
{
protected $fillable = [
'zone_id',
'name',
];
public function zone(){
return $this->belongsTo(Zone::class);
}
}
Here is my edit method
public function edit($id)
{
$zone = Zone::find($id);
$cities = City::all();
return view('backend.admin.pricings.zone_edit', compact('zone', 'cities'));
}
Here is my edit form so far
<div class="form-group {{ $errors->has('cities') ? 'has-error' : '' }}">
<label>Tentukan Kota</label>
<select name="cities[]" class="city form-control" data-placeholder="Pilih Kota" style="width: 100%;" multiple="multiple">
//load option from cities table
//set selected the city belongs to zone
//the other city which don't belong to zone still here for option
</select>
</div>
But how I can populate my edit form (multiple selection) with City belongs to zone?

Just like this in my view
<select name="cities[]" class="city form-control" data-placeholder="Pilih Kota" style="width: 100%;" multiple="multiple">
#foreach($cities as $city)
#if(in_array($city->id, $zoneCityIds))
<option value="{{ $city->id }}" selected="true">{{ $city->name }}</option>
#else
<option value="{{ $city->id }}">{{ $city->name }}</option>
#endif
#endforeach
</select>
and like this in my controller
public function zone_edit($id)
{
$zoneCityIds = [];
$zone = Zone::find($id);
$cities = City::all();
foreach($zone->cities as $zoneCity)
{
$zoneCityIds[] = $zoneCity->id;
}
return view('backend.admin.pricings.zone_edit', compact('zone', 'cities', 'zoneCityIds'));
}
actually it's jus about option tag selected="true"

for multiple values simply use
<div class="form-group">
{!! Form::label('Categories') !!}<br />
{!! Form::select('categories[]', $cost_centers,
$post->categories->pluck('id')->toArray(),
['class' => 'form-control',
'multiple' => 'multiple']) !!}
</div>

In your edit function you can get all the cities of that particular zone
$zone_cities = implode(',',$zone->cities->lists('name')->toArray());
and pass $zone_cities in your view.
return view('backend.admin.pricings.zone_edit', compact('zone', 'cities','zone_cities'));
You will have to use Form Model binding in your view
Read about laravel collective form model binding [here].1
You will open your form like this
Your Edit form will be like this
{!! Form::label('cities','Cities: ') !!}
{!! Form::text('cities',$zone_cities,['class'=>'input','id'=>'cities','aria-required'=>'true','data-seperator'=>',']) !!}

Related

How to use select2 multiselect with livewire

What I am trying to achieve is, there are two models A and B with a relationship of One to many, where A has many B. So if the records for A and B have already been created, A can be assigned to many B. So I started this current project with livewire, and now I am at a loss. Normal select with multiple works just fine and populates the array in the backend of livewire. But when I use select2 nothing is stored in the array, and when I dd it, it shows an empty array.
Even though livewire provides wonderful set of tools, I am starting to realize that there is a lot of gray areas where things are missing or lacks external support, like select2 here.
Here is what I have done so far:
<div>
<div class="tab-pane fade show active" id="card1" role="tabpanel" aria-labelledby="card1-tab">
<div class="pt-3"></div>
<div class="row" >
<div class="form-group col">
<label for="cards">Enter Cards</label>
<select class="form-control select2" id="cards" multiple="multiple" onchange="this.dispatchEvent(new InputEvent('input'))>
<option disabled="">Select Cards</option>
#foreach($cardsUnassigned as $card)
<option value="{{ $card->id }}">{{ $card->imei_number }}</option>
#endforeach
</select>
</div>
<div class="form-group col">
<label for="technicians" class="">Technicians</label>
<select class="form-control select2" id="technicians" wire:model='techies.'>
<option disabled="">Select Technicians</option>
#foreach($technicians as $tech)
<option value="{{ $tech->id }}">{{ $tech->first_name }}</option>
#endforeach
</select>
</div>
</div>
#foreach($cardSelect as $key => $value)
{{$value}}
#endforeach
<button wire:click="assignCardToTech()" class="btn btn-primary">Submit</button>
</div>
</div>
#push('scripts')
<script>
$('#cards').select2({
placeholder: 'Select Cards to assign'
});
//send data to livewire
$('#technicians').select2({
placeholder: 'Select Technicians'
});
</script>
#endpush
And the backend:
<?php
namespace App\Http\Livewire\Stock\Assigns;
use App\Models\Card;
use App\Models\Sim;
use App\Models\Technician;
use Livewire\Component;
use Livewire\WithPagination;
use Illuminate\Support\Facades\Auth;
class Assigns extends Component
{
public $sortBy_card = 'imei_number';
public $sortBy_sim = 'ip';
public $sortDirection = 'asc';
public $search = '';
public $perPage = 10;
public $cardSelect = [];
public $techies;
public function render()
{
$simsUnassigned = Sim::query()
->whereNull('technician_id')
->searchUnassigned($this->search)
->get();
$cardsUnassigned = Card::query()
->whereNull('technician_id')
->searchUnassignedCard($this->search)
->get();
// dd($cardsUnassigned);
$simsAssigned = Sim::query()
->searchAssigned($this->search)
->orderBy($this->sortBy_sim, $this->sortDirection)
->paginate($this->perPage);
$cardsAssigned = Card::query()
->searchAssignedCard($this->search)
->orderBy($this->sortBy_card, $this->sortDirection)
->paginate($this->perPage);
$technicians = Technician::query()->get();
return view('livewire.stock.assigns.assigns',compact('simsUnassigned','cardsUnassigned','simsAssigned','cardsAssigned','technicians'))
->extends('layouts.base')
->section('content');
}
public function assignCardToTech(){
dd($this->cardSelect);
if($this->cards){
foreach($this->cards as $card){
}
}
}
}
Hopefully this helps.
######## INSIDE LIVEWIRE COMPONENT
public array $locationUsers = [];
protected $listeners = ['locationUsersSelected'];
public function locationUsersSelected($locationUsersValues)
{
$this->locationUsers = $locationUsersValues;
}
######## INSIDE LIVEWIRE BLADE
<div class="col-md-12 mb-3" wire:ignore>
<label for="locationUsers">Select Users</label>
<select id="locationUsers" class="form-control select2" multiple="multiple">
<option value="">--select--</option>
#foreach($this->users as $id => $name)
<option value="{{ $id }}">{{ $name }}</option>
#endforeach
</select>
</div>
######## INSIDE LIVEWIRE SCRIPTS
document.addEventListener('livewire:load', function () {
$('#locationUsers').on('select2:close', (e) => {
#this.emit('locationUsersSelected', $('#locationUsers').select2('val'));
});
$('#locationUsers').val(#this.get('locationUsers')).trigger('change');
});
Your could try adding this to your html
<div class="form-group col-md-6" wire:ignore>
<label for="manager" class="mb-0 h5">Assign Managers:</label>
<select wire:model="reporting_managers" id="manager" class="select-2 multiple='multiple' data-placeholder="Assign Managers">
#foreach ($managers as $manager)
<option value="{{ $manager->id }}" data-name="{{ $manager->name }}">{{ $manager->name }}</option>
#endforeach
</select>
</div>
and then in your javaScript section
$('#manager').on('select2:select', function (e) {
#this.set('reporting_managers', $('#manager').select2('val'));
});
$('#manager').on('select2:unselect', function (e) {
#this.set('reporting_managers', $('#manager').select2('val'));
});
This will directly store your selection in variable in livewire and won't get deselected on render.

Laravel - How to make students not to score beyond the max mark

I am using Laravel-5.8 for a web application project. In the project I have these tables:
class SubjectCategory extends Model
{
protected $table = 'subject_categories';
protected $fillable = [
'name',
'parent_id',
'max_mark',
];
public function children()
{
return $this->hasMany('App\Models\SubjectCategory', 'parent_id');
}
public function exams()
{
return $this->hasMany('App\Models\Exam');
}
}
class Exam extends Model
{
protected $table = 'exams';
protected $fillable = [
'subject_category_id',
'student_id',
'student_mark',
'subject_name',
];
public function subjectcategory()
{
return $this->belongsTo('App\Models\SubjectCategory','subject_category_id');
}
}
SubjectCategory is an hierarchical table. Only the parent have the max_mark
Here is the Controller
public function create()
{
$categories = SubjectCategory::with('children')->whereNull('parent_id')->get();
return view('exams.create')
->with('categories', $categories);
}
public function store(StoreExamRequest $request)
{
$exam = new Exam();
$exam->stubject_category_id = $request->stubject_category_id;
$exam->student_id = $student_id;
$exam->student_mark = $request->student_mark;
$exam->save();
return redirect()->route('exams.index');
}
view blade
<div class="row">
<div class="col-md-12">
<!-- general form elements -->
<div class="card card-secondary">
<form method="POST" action="{{route('exams.store')}}">
#csrf
<div class="card-body">
<div class="form-body">
<div class="row">
<div class="col-12 col-sm-6">
<div class="form-group">
<label class="control-label"> Subject Category:<span style="color:red;">*</span></label>
<select id="subject_category" class="form-control" name="subject_category_id">
<option value="">Select Subject Category</option>
#foreach ($categories as $category)
<option disabled="disabled" value="{{ $category->id }}" {{ $category->id == old('category_id') ? 'selected' : '' }}>{{ $category->name }}</option>
#if ($category->children)
#foreach ($category->children as $child)
<option value="{{ $child->id }}" {{ $child->id == old('category_id') ? 'selected' : '' }}> {{ $child->name }}</option>
#endforeach
#endif
#endforeach
</select>
</div>
</div>
<div class="col-12 col-sm-6">
<div class="form-group">
<label class="control-label"> Subject Name:<span style="color:red;">*</span></label>
<input type="text" name="subject_name" placeholder="Enter Subject Name here" class="form-control">
</div>
</div>
<div class="col-12 col-sm-4">
<div class="form-group">
<label class="control-label"> Mark Obtained:</label>
<input type="number" name="student_mark" placeholder="Enter Mark Obtained here" class="form-control">
</div>
</div>
</div>
</div>
</div>
<!-- /.card-body -->
<div class="card-footer">
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
</div>
<!-- /.card -->
</div>
<!--/.col (left) -->
</div>
Subjects are categorized. From SubjectCategory, the parent subject have sub subjects as children. Only the Parent Subject Category have the Maximum Obtainable Score (Max Mark).
From the Exam (subject_category_id) dropdownlist contains all the children fields from subject_categories. What I want to achieve is this:
When Subject Category is selected from the dropdownlist, the system goes to the exams table. It displays total student_mark based on student_id and subject_category_id.
In each subject, the student accumulated mark cannot be more than the max_mark in the parent subject_category.
When the user tries to enter data into student_mark text field, the application adds the value in the text field to the student aggregate. If the result is more than the max_mark in subject_categories (SubjectCategory) based on the parent max_mark, then an error message is displayed.
How do I achieve this?
Thank you.
This is achievable in a couple of different ways; you could use validation to prevent someone entering a value over the max mark, or if they do enter a value over the max mark then you just silently reduce it back to the max mark.
I would suggest you take the validation approach and to do this you would need to use a custom validation rule.
You can read up on the documentation for how to create one (https://laravel.com/docs/5.8/validation#custom-validation-rules) but the implementation might look a little something like this:
// Inside a form request (or you could use inline validation in your controller
'student_mark' => [new NotOverMaxMark($this->input('subject_category_id'))]
Then for the rule itself might look a little something like this:
<?php
namespace App\Rules;
use App\SubjectCategory;
use Illuminate\Contracts\Validation\Rule;
class NotOverMaxMark implements Rule
{
private $subjectCategory;
public function __construct($subjectCategoryId)
{
$this->subjectCategory = SubjectCategory::findOrFail($subjectCategoryId);
}
public function passes($attribute, $value)
{
return $value <= $this->subjectCategory->max_mark;
}
public function message()
{
return 'The :attribute must not be higher than the max mark.';
}
}
The above is an example of how you might do this, you may need to tweak the imports or implementation to your needs.

Laravel $request value is null

I want to make dropdown menu where you choose company and it shows you owners that are in that company but when i request data from my blade.php in my controller i get NULL.
This is my blade.php
<form>
<label>Company:</label>
<select id="test" name="test" class="form-control input-sm">
#foreach($companies as $company)
<option value="{{$company->id}}">{{$company->name}}</option>
#endforeach
</select>
</form>
and this is my controller
public function index(Request $request)
{
$companies = Company::all();
$company_id = $request->get('company');
$owners = Owner::where('company_id',$company_id)->get();
return view ('owners', compact('owners','companies'));
}
and it's not showing any user but if I put any number manually like this
$company_id = 1;
then it shows owners from company where ID is 1.
UPDATE 2
My form looks like this now
<form action="{{ action('OwnerController#index') method="get"}}">
and my route is this
Route::get('owners', 'OwnerController#index');
Its still same.
Not sure what you want. But here is something for you.
File => create.blade.php
<form action='/item' method='POST'>
<label>Item Name:</label>
<input type="text" name="name" class="form-control input-sm">
<label>Company:</label>
<select id="company" name="company" class="form-control input-sm">
#foreach($companies as $company)
<option value="{{ $company->id }}">{{ $company->name }}</option>
#endforeach
</select>
<button class="btn btn-primary">Create</button>
</form>
File => ItemController.php
public function store(Request $request)
{
try {
$this->validate($request, [
'company_id' => 'required',
'name' => 'required|unique:items,name'
]);
$obj = new Item();
$obj->company_id = $request->input('company_id');
$obj->name = $request->input('name');
$obj->save();
return redirect()->route('item.index')
->with('success', 'Create Successful');
} catch (\Exception $ex) {
Log::error($ex->getMessage());
return redirect()->route('item.create')
->with('fail', $ex->getMessage());
}
}
As I said before I was missing some script. This solved my problem.
<form method="get" id="company_change">
<label for="company">Company:</label>
<select id="company" name="company" onchange="document.getElementById('company_change').submit()">
<option value="">----Select Company-----</option>
#foreach($companies as $company)
<option value="{{$company->id}}">{{$company->name}}</option>
#endforeach
</select>
</form>
My route is
Route::resource('owners', 'OwnerController');
You dont need a form to fill your dropdown;
You create a relationship in your model between Company and Owner and you dont even need a where,simply use eloquent like this
$owners = Owner::get();
And then in your view simply get the company using eloquent:
$owner->company->name;
That's it done!

Laravel Dropdown Selected item send to edit view

This is my view index page
<div class="form-group">
{!! Form::label('cname','Clients: ') !!}
{!! Form::select('cname',[''=>'Select Category']+$client,null,['class'=>'form-control selectpicker']) !!}
<span class="input-group-btn">
<a class="btn btn-primary" href="">Edit</a>
</span>
</div>
Controller:
public function index() {
$client = Client::pluck('cname','clientid')->all();
return view('client.index', compact('client'));
}
How can i get select item from dropdown and from button click send the selected details to edit view?
You can do something like this
// Controller
public function index()
{
$roles = Roles::all();
$selectedRole = User::first()->role_id;
return view('my_view', compact('roles', 'selectedRole');
}
And then in your view
<select class="form-control m-bot15" name="role_id">
#if ($roles->count())
#foreach($roles as $role)
<option value="{{ $role->id }}" {{ $selectedRole == $role->id ? 'selected="selected"' : '' }}>{{ $role->name }}</option>
#endif
</select>

Laravel 4 - Update many to many

I am currently trying to amend an update page which features a many to many relationship. It updates to my database perfectly, however all I'm trying to achieve now is to actually show the already selected items in my multiple select list in my view.
It currently just shows the entire list of oilgas jobs, just not the currently selected ones which should come from the query in some way.
So, it currently looks like this:
I need it to look like this, if Instrument Technician was previously chosen.
The associated files are as follows:
MODELS
OilGasJob.php
<?php
class OilGasJob extends \Eloquent {
protected $table = 'oilgasjobs';
public function industryjobs()
{
return $this->belongsToMany('IndustryJob');
}
}
IndustryJob.php
<?php
class IndustryJob extends \Eloquent {
protected $table = 'industryjobs';
public function oilgasjobs()
{
return $this->belongsToMany('OilGasJob');
}
}
CONTROLLER (CREATE PAGE AND STORE)
public function edit($id)
{
$industryjob = IndustryJob::find($id);
if(is_null($id))
{
return Redirect::to('/admin/industry-jobs')->with('message', 'This division job is not valid');
}
View::share('page_title', 'Edit Division Job');
return View::make('admin/industry-jobs/edit')->with('industryjob',$industryjob);
}
public function update($id)
{
$rules = array(
'job_title' => 'Required|Min:3|Max:80'
);
$validation = Validator::make(Input::all(), $rules);
If ($validation->fails())
{
return Redirect::back()->withErrors($validation);
} else {
$industryjob = IndustryJob::find($id);
if(is_null($id))
{
return Redirect::to('/admin/industry-jobs')->with('message', 'This divison job is not valid');
}
View::share('page_title', 'Edit Division Job');
$industryjob->job_title = Input::get('job_title');
$industryjob->slug = Str::slug(Input::get('job_title'));
$industryjob->job_description = Input::get('job_description');
$industryjob->job_qualifications = Input::get('job_qualifications');
$industryjob->save();
$industryjob->oilgasjobs()->sync(Input::get('oilgasjobs'));
return Redirect::to('/admin/industry-jobs')->with('message', 'Division Job updated successfully');
}
}
VIEW
{{ Form::open(array('url' => URL::to('admin/industry-jobs/edit/'.$industryjob->id), 'class'=>'form-horizontal', 'method' => 'POST')) }}
<div class="form-group">
<label class="col-md-2 control-label" for="industry_name">Job Title (*)</label>
<div class="col-md-10">
<input class="form-control" type="text" name="job_title" id="job_title" value="{{ $industryjob->job_title }}" />
</div>
</div>
<!-- Industry Type -->
<div class="form-group">
<label class="col-md-2 control-label" for="body">Related Jobs in Oil & Gas</label>
<div class="col-md-10">
<select name="oilgasjobs[]" id="oilgasjobs[]" size="6" class="form-control" multiple>
#foreach(OilGasJob::orderBy('job_title', 'ASC')->get() as $oilgasjob)
<option value="{{ $oilgasjob->id }}" >{{ $oilgasjob->job_title }}</option>
#endforeach
</select>
</div>
</div>
<!-- ./ Industry Type -->
<!-- Form Actions -->
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="reset" class="btn btn-default">Reset</button>
<button type="submit" class="btn btn-success">Update Job</button>
</div>
</div>
<!-- ./ form actions -->
{{ Form::close() }}
In edit method add this code:
// ...
$linkedOilgasjob = DB::table('oilgasjob_industryjob')->lists('oilgasjob_id');
return View::make('admin/industry-jobs/edit'
,compact('industryjob')
,compact('linkedOilgasjob'));
Then in your view
<option value="{{ $oilgasjob->id }}" {{ in_array($oilgasjob->id,linkedOilgasjob) ? "selected='selected'" : "" }} >
{{ $oilgasjob->job_title }}
</option>
CONTROLLER
public function edit($id)
{
$data['industryjob'] = IndustryJob::find($id);
$data['oilgasjobs'] = DB::table('industry_job_oil_gas_job')->where('industry_job_id','=',$id)->lists('oil_gas_job_id');
if(is_null($id))
{
return Redirect::to('/admin/industry-jobs')->with('message', 'This division job is not valid');
}
View::share('page_title', 'Edit Division Job');
return View::make('admin/industry-jobs/edit', $data);
}
VIEW
<select name="oilgasjobs[]" id="oilgasjobs[]" size="6" class="form-control" multiple>
#foreach(OilGasJob::orderBy('job_title', 'ASC')->get() as $oilgasjob)
<?php
$selected = "";
if(in_array($oilgasjob->id, $oilgasjobs))
$selected = "selected";
?>
<option value="{{ $oilgasjob->id }}" <?php echo $selected; ?>>{{ $oilgasjob->job_title }}</option>
#endforeach
</select>

Resources