Laravel/Livewire dynamic dropdown not sending the selected value - laravel-8

Using Laravel 8 + Livewire:
I was following this tutorial of creating a dynamic dropdown: https://www.itsolutionstuff.com/post/laravel-livewire-dependant-dropdown-exampleexample.html
I have this dropdown component:
public $suppliers;
public $beans;
public $selectedSupplier = NULL;
public function mount()
{
$this->suppliers = Supplier::whereHas('greenBeans')->get();
$this->beans = collect();
}
public function render()
{
return view('livewire.admin.supplier-beans-dropdown')->layout('layouts.admin.livewire');
}
public function updatedSelectedSupplier($supplier)
{
if (!is_null($supplier)) {
$this->selectedSupplier = Supplier::find($supplier);
$this->beans = $this->selectedSupplier->greenBeans;
}
}
The component's blade:
<div>
<div class="form-group">
<label for="supplier" class="col-md-4 form-label">Supplier</label>
<select wire:model.lazy="selectedSupplier" class="form-control">
<option value="" selected>Select Supplier</option>
#foreach($suppliers as $supplier)
<option value="{{ $supplier->id }}">{{ $supplier->name }}</option>
#endforeach
</select>
</div>
#if (!is_null($selectedSupplier))
<div class="form-group">
<label for="bean" class="form-label">Green Bean</label>
<select class="form-control" name="bean" wire:model.lazy="selectedBean">
<option value="" selected>Select Green Bean...</option>
#foreach($beans as $bean)
<option value="{{ $bean->id }}">{{ $bean->name }}</option>
#endforeach
</select>
</div>
#endif
I have an other component that needs to call this dropdown. So in this parent component I have this var: $selectedSupplier and in the view I call the dropdown component:
#livewire('admin.supplier-beans-dropdown')
When I select a supplier and submit the form, the selectedSupplier is null.
So how do I use this dropdown in different components?
How do I send the selected value to the parent component?

check this first I think you have some errors here. you have:
public function updatedSelectedSupplier($supplier)
{
if (!is_null($supplier)) {
$this->supplier = Supplier::find(supplier); --> typo error here???
$this->beans = $supplier->greenBeans; --> $supplier parameter is an ID???
}
}
and I think it should be:
if (!is_null($supplier)) {
$this->supplier = Supplier::find($supplier);
$this->beans = $this->supplier->greenBeans;
}

Related

Jetstream User Profile Update: problems passing $input[] field using Livewire form input

I added some custom fields to the User Model and it stores them perfectly during registration (country_id, city_id, and state_id), but I am having problems with the profile management/update:
The fields seem to update only when using the jetstream components as input but NOT when I use my dropdown select option input
<x-jet-input id="cap" type="text" class="mt-1 block w-full" wire:model.defer="state.cap" />
So for instance this would update the $input['cap'] key but the "country_id" field from my livewire script does not update the $input['country_id'] ...
<select wire:model="selectedCountry" id="country_id" name="country_id">
<option value="{{$user->country_id}}"> {{$user->country->name}} </option>
#foreach($countries as $country)
<option value="{{$country->id}}"> {{$country->name}} </option>
#endforeach
</select>
<x-jet-input-error for="country_id" class="mt-2" />
To display or hide fields for instance I update the variables such as $SelectedCountry
The Country/City/State fields are displayed using a livewire script that hides or shows a given select dropdown and runs queries only when needed (if a Country has states/regions, it shows them otherwise it shows only the cities from the selected country etc).
If I submit though, the $input['country_id'] key is not changing though and it just keeps the previous value with which I registered.
I assume the jetstream component would do using wire:model.defer="state.country_id" for instance but again I can not use it because is just a text input... any ideas? 😬
Update-Profile-information-Form
...
<div class="col-span-6 sm:col-span-4">
<x-jet-label for="cap" value="{{ __('Postal Code') }}" />
<x-jet-input id="cap" type="text" class="mt-1 block w-full" wire:model.defer="state.cap" />
<x-jet-input-error for="cap" class="mt-2" />
</div>
<div class="col-span-6 sm:col-span-4">
<x-jet-label for="address" value="{{ __('Address') }}" />
<x-jet-input id="address" type="text" class="mt-1 block w-full" wire:model.defer="state.address" />
<x-jet-input-error for="address" class="mt-2" />
</div>
<div class="col-span-6 sm:col-span-4">
#livewire('edit-address', ['user' => Auth::user()])
</div>
...
edit-address.blade.php (view)
<div>
...
<x-jet-label for="country_id" value="{{ __('Country') }}" />
<select wire:model="selectedCountry" id="country_id" name="country_id">
<option value="{{$user->country_id}}"> {{$user->country->name}} </option>
#foreach($countries as $country)
<option value="{{$country->id}}"> {{$country->name}} </option>
#endforeach
</select>
<x-jet-input-error for="country_id" class="mt-2" />
</div>
...
EditAdress.php (livewire script)
class EditAddress extends Component
{
public $countries;
public $states;
public $cities;
public $selectedCountry = null;
public $selectedState = null;
public $selectedCity = null;
public $test = null;
public $user = null;
public function mount(User $user, $selectedCity = null){
$this->countries = Country::all();
$this->states = collect();
$this->cities = collect();
$this->selectedCity = $selectedCity;
if (!is_null($selectedCity)) {
$city = City::with('state.country')->find($selectedCity);
if ($city) {
/*if ($this->states->isEmpty()===1){
$this->cities = City::where('country_id', $this->selectedCountry);
}*/
$this->cities = City::where('state_id', $city->state_id)->get();
$this->states = State::where('country_id', $city->state->country_id)->get();
$this->selectedCountry = $city->state->country_id;
$this->selectedState = $city->state_id;
}
}
}
public function render()
{
return view('livewire.edit-address');
}
public function updatedSelectedCountry($country)
{
;
$this->states = State::where('country_id', $country)->get();
$this->selectedState = NULL;
if(!$this->states->count()){
$this->cities = City::where('country_id', $country)->get();
}
}
public function updatedSelectedState($state)
{
if (!is_null($state)) {
$this->cities = City::where('state_id', $state)->get();
}
else{
$this->cities = City::where('country_id', $this->selectedCountry);
}
}
}

how to validate two dropdowns depends upon selection?

I have two Dropdowns first dropdown 1 to 23 hours and the second dropdown also 1 to 23 hours.
If I select the first Dropdown is 4.the second drop-down is higher than the first dropdown selected value. how to do that
This is the solution for your concern. I have used the form if you are not used form then remove it and take the normal angular control.
HTML
<form [formGroup]="form" (ngSubmit)="submit()">
<div class="form-group">
<select formControlName="firstDropdown" class="form-control" (change)="firstDropDownChange($event)">
<option *ngFor="let value of values" [value]="value">
<span>{{ value }}</span>
</option>
</select>
<select formControlName="secondDropdown" class="form-control" (change)="secondDropDownChange($event)">
<option *ngFor="let value of values1" [value]="value">
<span>{{ value }}</span>
</option>
</select>
</div>
<button class="btn btn-primary" type="submit" [disabled]="!form.valid">
Submit
</button>
</form>
TS
values: any = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23];
values1: any = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23];
firstDropdown: any = 1;
secondDropdown: any = 1;
form: FormGroup;
constructor() {
this.form = new FormGroup({
firstDropdown: new FormControl(1),
secondDropdown: new FormControl(1),
});
}
firstDropDownChange(event) {
this.values1 = this.values.filter(
(data) => parseInt(event.target.value) <= data
);
console.log(this.values1);
this.form.controls['secondDropdown'].setValue(parseInt(this.values1[0]));
}
secondDropDownChange(event) {}
submit() {}

Trying to get property of non-object (View: C:\xampp\htdocs\MyP\resources\views\pekerja\index.blade.php)

i have problem 'Trying to get property of non-object' on this code. please someone check this code for make me clear. TQ
index.blade.php
<div class="form-group">
<label for="idUnit" class="control-label col-sm-3">Unit :</label>
<div class="col-sm-9">
<select name="idUnit" class="form-control input-sm" id="idUnit" disabled="disabled">
<option value="">Sila Pilih...</option> ---> error on this code!
#foreach ($KodUnit as $unit)
<option value="{{ $unit->id }}"
#if(isset(request()->idUnit) && request()->idUnit == $unit->id)
selected="selected"
#endif
>{{ $unit->nama }}</option>
#endforeach
</select>
</div>
</div>```
kodUnit model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class KodUnit extends Model
{
protected $table = 'kod_unit';
protected $primaryKey = 'id';
protected $fillable = ['id', 'kod', 'nama'];
public $timestamps = false;
}

How to get object relation inside <option> loop in Vue?

Let's go to the point of the question. I have a selection component, it looks like this:
<template>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="category_id">
Product Category
</label>
<select
name="category_id"
id="category_id"
:class="form.errors.has('category_id') ? 'form-control is-invalid' : 'form-control'"
v-model="form.sharedState.category_id">
<option value="" disabled hidden>Select Category</option>
<option
v-for="category in categories"
:key="category.id"
v-text="category.name"
:value="category.id"
#click="$emit('category-selected', category.sub_categories)">
</option>
</select>
<small
class="form-text text-danger"
v-if="form.errors.has('category_id')"
v-text="form.errors.get('category_id')"></small>
</div>
</div>
<div class="col-md-6">
<div
class="form-group"
v-if="revealSubCategory"
#category-selected="show">
<label for="category_id">
Sub Category
</label>
<select
name="sub_category_id"
id="sub_category_id"
:class="form.errors.has('sub_category_id') ? 'form-control is-invalid' : 'form-control'"
v-model="form.sharedState.sub_category_id">
<option value="" disabled hidden>Select Sub Category</option>
<option
v-for="subcategory in subcategories"
:key="subcategory.id"
v-text="subcategory.name"
:value="subcategory.id">
</option>
</select>
<small
class="form-text text-danger"
v-if="form.errors.has('category_id')"
v-text="form.errors.get('category_id')"></small>
</div>
</div>
</div>
</template>
<script>
import BaseCard from './BaseCard.vue';
export default {
components: {
BaseCard
},
data() {
return {
categories: [],
revealSubCategory: false,
subcategories: [],
form: new Form({
sharedState: product.data
})
}
},
mounted() {
this.getCategories();
},
methods: {
getCategories() {
axios.get('categories')
.then(({data}) => this.categories = data);
},
show(subcategories) {
this.revealSubCategory = true;
this.subcategories = subcategories
}
}
}
</script>
And a select sub category input (it is there on the second column) which is will be displayed once the user has selected one of the categories options. Each category option has relation to sub categories taken from the API.
How can I get the sub categories and display the input? I already tried #change on the select tag but I can't pass the sub category object because it is outside the loop. And #click event seems to be not working in an option tag.
You can watch the v-model of the first select and change subcategory.
watch:{
"form.sharedState.category_id": function (val) {
// update subcategories here
}

How to save category in laravel 5.7 with vue.js

Using Laravel 5.7 with vuejs, I am trying to display parent_id from a MySQL categories table. I want to pass the name and get all it's child categories irrespective of the parent.
My blade
<form action="{{ route('categories.store') }}" method="post">
#csrf
<div class="form-group">
<label for="name">name:</label>
<input type="text" id="name" class="form-control" v-model="name">
</div>
<div class="form-group">
<label for="sub_category">category</label>
<select id="sub_category" v-model="parent_id" class="form-control">
<option data-display="main category" value="0">main category</option>
<option v-for="category in categories" :value="category.id">#{{ category.name }}</option>
</select>
</div>
<div class="form-group">
<button type="button" #click="addCategory()" class="btn btn-info">save</button>
</div>
</form>
web.php
Route::group(['namespace' => 'Admin', 'prefix' => 'admin'],function (){
$this->get('panel', 'PanelController#index')->name('panel.index');
$this->resource('categories', 'CategoryController');
});
My vue
addCategory: function () {
axios.post(route('categories.store'), {
name: this.name,
parent_id: this.parent_id,
}).then(response => {
this.categories.push({'name': response.data.name, 'id': response.data.id});
}, response => {
this.error = 1;
console.log('Errors');
});
}
CategoryController
public function store(Request $request)
{
$category = new Category();
$category->name = $request->name;
$category->parent_id = $request->parent_id;
if ($category->save()) {
return $category;
}
}
I see this error in console for first
Too
And I get 405 error.
Remove #click from submit buttom.
Remove route... from form action and set it #
Add #submit="addCategory()" to the form
In the axios.post samply add the route without route function.
Update:
If you want to prevent page refreshing, add .prevent after #submit.