Laravel Livewire Select2 Multiple sellect issue - php

Product variation Color first time is disable after enable can select color.
without wire:ignore after select color its disappear from select option.
If I use wire:ignore
{{ $colors_active== 0 ?'disabled':'' }}
disable is not removed, it's still disabled.
product.blade.php
<div class="row g-3 align-center">
<div class="col-lg-3">
<div class="form-group">
<input class="form-control" type="text" value="Colors" readonly>
</div>
</div>
<div class="col-lg-8">
<div class="form-group">
<select class="form-control color-select2" multiple style="width: 100%" {{ $colors_active== 0 ?'disabled':'' }} >
#foreach (App\Models\Admin\Color::orderBy('name', 'asc')->get() as $key => $color)
<option value="{{$color->code}}">
{{$color->name}}
</option>
#endforeach
</select>
</div>
</div>
<div class="col-lg-1">
<div class="form-group">
<div class="form-control-wrap">
<label class="c-switch c-switch-pill c-switch-opposite-success">
<input wire:model="colors_active" class="c-switch-input" type="checkbox" value="1" ><span class="c-switch-slider"></span>
</label>
</div>
</div>
</div>
</div>
Product.php Component
{
public $colors_active;
public $choice_attributes = [];
public $colors = [];
public function mount(){
}
public function render()
{
return view('livewire.admin.product.product')->layout('admin.layouts.master');
}
}

Livewire will ignore any changes to anything marked with wire:ignore, so naturally it will not re-render anything when its ignored.
You can solve this by using Apline.js, and entangle the $colors_active property to an attribute in Alpine.js. Entangle means that when Livewire updates the variable in its backend, Alpine updates its variable too - and vice-versa (Alpine.js updates Livewire when the variable is changed). Basically, its kept in sync between the two.
Then, you can make Alpine.js dynamically bind the disabled property of your select-element based on that variable.
<div x-data="{ 'colorsActive': #entangle('colors_active') }">
<select
class="form-control color-select2"
multiple
style="width: 100%"
wire:ignore
x-bind:disabled="colorsActive == 0"
>
#foreach (App\Models\Admin\Color::orderBy('name', 'asc')->get() as $key => $color)
<option value="{{ $color->code }}">
{{ $color->name }}
</option>
#endforeach
</select>
</div>

This is the way I use to approach this kind of solutions with Livewire, without Alpine because unfortunately I haven't learn it.
In the blade component:
<div class="col d-flex display-inline-block">
<label>Device</label>
<select {{ $customer ? '' : 'disabled' }} wire:model="selectedItem" class="form-control contact_devices_multiple" multiple="multiple" data-placeholder="Select" style="width: 100%;">
#foreach($devices as $device)
<option value="{{ $device->id }}">{{ $device->alias }}</option>
#endforeach
</select>
</div>
<script>
window.loadContactDeviceSelect2 = () => {
$('.contact_devices_multiple').select2().on('change',function () {
livewire.emitTo('contact-component','selectedItemChange',$(this).val());
});
}
loadContactDeviceSelect2();
window.livewire.on('loadContactDeviceSelect2',()=>{
loadContactDeviceSelect2();
});
</script>
in component
public $customer = null;
public $selectedItem = [];
public function hydrate()
{
$this->emit('loadContactDeviceSelect2');
}
public $listeners = [
'selectedItemChange',
];
public function selectedItemChange($value)
{
dd($value);
}

Related

Livewire Laravel add dynamic select, how do I resolve the loss of data? Please

when add next select, you lose the data of the first select of the municipalities.
Livewire controller SelectUsuario.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use Illuminate\Support\Facades\Http;
class SelectUsuario extends Component
{
public $estados;
public $estado;
public $estadoSigla;
public $municipios;
public $selects = [];
public $i = 0;
public function add($i)
{
$i = $i + 1;
$this->i = $i;
array_push($this->selects, $i);
}
public function remove($i)
{
unset($this->selects[$i]);
}
public function mount()
{
$this->estados = Http::get(
url("https://servicodados.ibge.gov.br/api/v1/localidades/estados"),
['orderBy' => 'nome']
)->json();
}
public function updatedEstadoSigla()
{
$this->getMunicipios();
}
public function getMunicipios()
{
if ($this->estadoSigla != '') {
foreach ($this->estadoSigla as $estado) {
$this->municipios = json_decode(
Http::get(
url("https://servicodados.ibge.gov.br/api/v1/localidades/estados/{$estado}/municipios")
)->body(),
true
);
}
}
}
public function render()
{
return view('livewire.select-usuario');
}
}
Livewire component select-usuario.blade.php
<div class="form-group row">
<div class="col-3"><label>Viagem</label></div>
<div class="col-3"><label>Seção</label></div>
<div class="col-4"><label>Funcionário</label></div>
<div class="col-2"><label>Ação</label></div>
<div class="col-3">
<select class="form-control" data-item_id="0">
<option value="R">Responsável</option>
</select>
</div>
<div class="col-3">
<select wire:model="estadoSigla.0" class="form-control" id="estado.0" name="estado.0">
<option value="">selecione estado...</option>
#foreach ($this->estados as $estado)
<option value="{{ $estado['sigla'] }}">{{ $estado['nome'] }}</option>
#endforeach
</select>
</div>
<div class="col-4">
#if ($this->estadoSigla)
<select class="form-control" name="municipio.0" id="municipio.0">
<option value="" selected>selecione município...</option>
#foreach ($this->municipios as $municipio)
<option value="{{ $municipio['id'] }}">{{ $municipio['nome'] }}</option>
#endforeach
</select>
#endif
</div>
<div class="col-2">
<button class="btn btn-info mb-2" wire:click.prevent="add({{ $i }})">adicionar</button>
</div>
{{-- Add Form --}}
#foreach ($selects as $key => $value)
<div class="col-3">
<select name="item_name[]" class="form-control" data-item_id="{{$value}}">
<option value="I">Ida</option>
<option value="V">Volta</option>
<option value="O">Ida e Volta</option>
<option value="R">Responsável</option>
</select>
</div>
<div class="col-3">
<select wire:model="estadoSigla.{{ $value }}" class="form-control" name="estado.{{ $value }}" id="estado.{{ $value }}">
<option value="">selecione estado...</option>
#foreach ($this->estados as $estado)
<option value="{{ $estado['sigla'] }}">{{ $estado['nome'] }}</option>
#endforeach
</select>
</div>
<div class="col-4">
#if ($estadoSigla)
<select class="form-control" name="municipio.{{ $value }}" id="municipio.{{ $value }}">
<option value="" selected>selecione município...</option>
#foreach ($this->municipios as $municipio)
<option value="{{ $municipio['id'] }}">{{ $municipio['nome'] }}</option>
#endforeach
</select>
#endif
</div>
<div class="col-2">
<button class="btn btn-dark mb-2" wire:click.prevent="remove({{ $key }})">remover</button>
</div>
#endforeach
</div>
try adding wire:key directive to the looped select elements while livewire need to keep tracking all the values of them.
<select wire:model="estadoSigla.{{ $value }}" class="form-control" id="estado.{{ $value }}" wire:key="estado-select-{{ $key }}"> // or $value, the unique identifier for its
also, try adding wire:ignore.self to the root div of the select elements

why Dynamically add section doesn't work after retrieving the data from DB?

I have a button that adds a new language section to the form for the users to add a new language to their profile and it was working fine until I added that part which gets the existing user languages from DB to show in case they want to change the language or update it. I have been struggling for hours and can't figure out why is this happening why it stops working when the getUserLanguages function is being called. and when remove the getUserLanguages function from the render method it will start working again.
component controller:
public function addLanguage($i)
{
$i = $this->i;
if ($i <= 3)
{
$i = $i + 1;
$this->i = $i;
array_push($this->languages , ['language_name'=>'', 'language_level'=>'']);
}
else
{
$this->sweetAlert('error', 'You only can add 3 langauges.');
}
}
public function getUserLanguages()
{
if (empty(!UserLanguage::where('user_id', auth()->user())))
{
$this->languages = UserLanguage::where('user_id', auth()->user()->id)->get(['language_name', 'language_level'])->toArray();
$this->i = count($this->languages);
}
}
the view:
#foreach ($languages as $index)
<div class="card card-body mb-4">
<div class="row">
<div class="form-group col-md-6">
<label class="" for="languageName">Language</label>
<select class="form-control form-control-alternative" name="language-name" {{-- id="languageName" --}} wire:model="languages.{{ $loop->index }}.language_name">
<option value="" class="form-control" selected disabled>Select Language</option>
#foreach ($language_names as $name)
<option value="{{ $name->abbreviation }}" class="form-control">{{ $name->language }}</option>
#endforeach
</select>
</div>
<div class="form-group col-md-6">
<label class="" for="languageProficiency">Proficiency</label>
<select class="form-control form-control-alternative" name="language-proficiency" {{-- id="languageProficiency" --}} wire:model="languages.{{ $loop->index }}.language_level">
<option value="" class="form-control" selected disabled>Proficinecy Level</option>
#foreach ($language_levels as $level)
<option value="{{ $level->level }}" class="form-control">{{ $level->name }}</option>
#endforeach
</select>
</div>
</div>
</div>
#error('languages.*.level')
<small class="text-warning">{{ $message }}</small>
#enderror
#error('languages.*.language')
<small class="text-warning">{{ $message }}</small>
#enderror
#endforeach
#if (count($languages) < 3)
<div class="row">
<div class="col-md-12">
<button type="button" class="btn btn-outline-secondary btn-round btn-block" wire:click="addLanguage({{$i}})"><span class="btn-inner--icon"><i class="fa fa-plus fa-2x"></i></span></button>
</div>
</div>
#endif
so finally after i called the getUserLanguages() from the mount method instead of the render method everything works as it should be.

How to show div based on data sent to blade in Laravel

i have two divs (inputbarang and inputkategori). I want to make one of the divs disappear when there's no data in it. For example, when the $produk's value is not null, the inputbarang's div will appear, and the inputkategori's div will be hidden. Whereas, if $produk is empty, then the inputbarang's div will be hidden and the inputkategori's div will appear. I try like this. When $produk is null, the inputbarang's div still appears and the inputkategori's div doesn't appear
Blade.php:
#if($produk !== null)
<div class="form-group row " id="inputbarang" >
<label class="col-form-label col-lg-3 col-sm-12">Barang</label>
<div class="col-lg-4 col-md-9 col-sm-12">
<select class="form-control m-select2" width="500px" id="kt_select2_1" name="id_product[]" multiple="multiple">
#foreach($productall as $p)
#if(in_array($p->id, $productbyIds))
<option value="{{ $p->id }}" selected="true">{{ $p->product }}</option>
#else
<option value="{{ $p->id }}">{{ $p->product }}</option>
#endif
#endforeach
</select>
</div>
</div>
#else
<div class="form-group row" id="inputkategori" >
<label class="col-form-label col-lg-3 col-sm-12">Kategori</label>
<div class="col-lg-9 col-md-9 col-sm-12">
<select class="form-control m-select2" width="500px" id="kt_select2_3" name="id_kategori[]" multiple="multiple">
#foreach($kategoriall as $k)
#if(in_array($k->id, $kategoribyIds))
<option value="{{ $k->id }}" selected="true">{{ $k->kategori }}</option>
#else
<option value="{{ $k->id }}">{{ $k->kategori }}</option>
#endif
#endforeach
</select>
</div>
</div>
#endif
Controller:
$produk = Produk::where('m_product.delete', 0)
->join('tb_promo_detail', 'tb_promo_detail.id_product','=','m_product.id')
->select('m_product.id', 'm_product.product')
->where('tb_promo_detail.id_promo',$id)
->get();
Please correct me if its wrong.. Thank you so much!
Since you are sending a collection to your blade from controller you will need to check if that collection is empty or not. Just checking if it is null or empty array will not give you the right conditional effect.
So use:
#if($produk->first())
or you can also use
#if(!$produk->isEmpty())

Laravel Multiple Filters Table with Multiple Collections

I am trying to create a multiple filter function to filter my table. I have a model called Product and it has collections named categories, colors and sizes. I have the following in my view:
<div class="col-6">
<div class="form-group mt-3">
<label>{{ __('Categories') }}</label>
<select class="form-control" id="select-categories">
<option value="0">All</option>
#foreach($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
#endforeach
</select>
</div>
</div>
<div class="col-6">
<div class="form-group mt-3">
<label>{{ __('Colors') }}</label>
<select class="form-control" id="select-colors">
<option value="0">All</option>
#foreach($colors as $color)
<option value="{{ $color->id }}">{{ $color->name }}</option>
#endforeach
</select>
</div>
</div>
<div class="col-6">
<div class="form-group mt-3">
<label>{{ __('Sizes') }}</label>
<select class="form-control" id="select-sizes">
<option value="0">All</option>
#foreach($sizes as $size)
<option value="{{ $size->id }}">{{ $size->name }}</option>
#endforeach
</select>
</div>
</div>
And then I use JQuery to send a AJAX request to my controller with the current selected option values of all three dropdowns.
Example data:
Categories: All
Colors: Red
Sizes: Small
Now I wish to show the products with the color red and size small but the category doesn't matter.
I get the collections with the use of one to many relationships and link tables.
$product->categories
$product->colors
$product->sizes
I am not sure how to approach this.
You can do something similar to below:
public function index(ProductRequest $request)
{
$query = Product::where($request->validated());
return ProductResource::collection($query);
}
and in your ProductRequest you can define filters that you want to allow
class ProductRequest extends FormRequest
{
...
public function rules()
{
return [
'categories' => 'exists:categories,id'
....
];
}

Adding data with multiple tables in one form many to many relationship in laravel 5.4

I am trying to insert with two tables with many to many relationship: Assignments and Collectors. I also make a intermediate or pivot table between them named assignment_collector.
create.blade.php in assignment folder
<form method="POST" action="{{ route('assignments.store') }}">
{{ csrf_field() }}
<div class="form-group">
<label for="area_id">Area: </label>
<select class="form-control" name="area_id">
#foreach ($areas as $area)
<option value= "{{ $area->id }}">
{{ $area->campus }} {{ $area->building }} {{ $area->floor }}
</option>
#endforeach
</select>
</div>
<div class="form-group">
<label for="mts_id">MTS: </label>
<select class="form-control" name="mts_id">
#foreach ($mts as $mt)
<option value= "{{ $mt->id }}">
{{ $mt->location }}
</option>
#endforeach
</select>
</div>
<div class="form-group">
<input type="hidden" class="form-control" id="status" name= "status" value="Active">
</div>
<div class="form-group">
<label for="collector_id">Collector: </label>
<select class="form-control" name="collector_id">
#foreach ($assignments as $assignment)
#foreach($assignment->collectors as $collector)
<option value= "{{ $collector->id }}">
{{ $collector->firstname }} {{ $collector->lastname }}
</option>
#endforeach
#endforeach
</select>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Add</button>
</div>
</form>
AssignmentsController
public function store(Request $request)
{
$this->validate($request, [
'area_id' => 'required',
'mts_id' => 'required',
'status' => 'required',
'collector_id' => 'required'
]);
$assignment = new Assignment();
$assignment->area_id = $request->area_id;
$assignment->mts_id = $request->mts_id;
$assignment->status = $request->status;
$assignment->save();
$assignment_collector = new AssignmentCollector();
$assignment_collector->collector_id = $request->collector_id;
$assignment_collector->assignment_id = $assignment->id;
$assignment_collector->save();
return redirect('/assignments');
}
Assignment Model
public function collectors()
{
return $this->belongsToMany(Collector::class);
}
Collector Model
public function assignments()
{
return $this->belongsToMany(Assignment::class);
}
I got an error on this: App\AssignmentCollector since there is no AssignmentCollector and as I read the tutorials, you don't need to make a model for the pivot table. I reading the other articles but I get even more confused. Please help me because I'm still new in Laravel and I have get confused. Thanks!
You don't need a Model for your assignment collector table. What you want to do is create the Assignment then assign
$assignment->collectors()->create([
// all the collector data
]);

Categories