select options based on another select VueJS Laravel - laravel

I am using VueJs with laravel, I am new in VueJs and i want to display the Categories dynamically whenever i choose any Collection, i am sending API and using Axios, but i cant seem to figure out how to make this work.
Any help will be highly appreciated
<div class="form-group">
<label for="">Collection</label>
<select
class="form-control"
v-model="collection"
#change="getCategory()"
>
<option
v-for="datas in data"
:key="datas.collection_name"
:value="datas.collection_id"
>
{{ datas.collection_name }}
</option>
</select>
</div>
<div class="form-group">
<label for="">Category</label>
<select class="form-control" v-model="category">
<option :value="category">
{{ category_name }}
</option>
</select>
</div>
data() {
return {
category_name: "",
collection: null,
category: null,
};
},
methods: {
getCategory() {
console.log(this.collection);
axios
.get("/api/products")
.then((response) => {
console.log(response.data[0].category_id);
this.category = response.data[0].category_id;
this.category_name = response.data[0].category_id;
})
.catch((err) => {
console.log(err);
});
},
Controller:
public function create(){
$collection = Collection::join('categories','collections.id','=','categories.collection_id')
->select('categories.name as category_name','categories.id as category_id','collections.name as collection_name','collections.id as collection_id')
->get();
return response()->json($collection);
}
Axios response.data output is :

if I got your question very well. You want to dynamically display your categories after choosing collection data that are in laravel backend API.
in your script in vue js
data(){
return {
form: {
collection:'',category: '' //define your v-models here
},
categories:{},
errors: [],
}
},
method:{
getCategories(){
axios.get('/categories/' + this.form.collection).then(response => {
this.categories = response.data
}).catch(errors => {
this.errors = error.response.data.errors
})
},
},
in your template now (html)
<div class="col-lg-6">
<div class="mb-3">
<label class="form-label">collection</label>
<select v-model="form.collection" class="form-control" #change="getCategories()">
<option value="">Select Collection</option>
<option :value="collection.id" v-for="collection in collections" :key="country.id">{{ country.name }}</option>
</select>
<div v-if="errors.collection" class="text-small text-danger"> {{ errors.collection[0] }}</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Category</label>
<div class="form-icon position-relative">
<select class="form-control" v-model="form.category">
<option value="">Select Category</option>
<option :value="category.id" v-for=" categories" :key="city.id">{{ category.name }}</option>
</select>
<div v-if="errors.category" class="text-small text-danger">{{ errors.city_id[0] }}</div>
</div>
</div>
</div>
you better define your v-models with form as I did above it will help you not confusing yourself. example form.collection

This should work.
<template>
<div>
<div class="form-group">
<label for="">Collection</label>
<select
class="form-control"
v-model="collection"
#change="getCategory()"
>
<option
v-for="datas in data"
:key="datas.collection_name"
:value="datas.collection_id"
>
{{ datas.collection_name }}
</option>
</select>
</div>
<div class="form-group">
<label for="">Category</label>
<select class="form-control" v-model="category" v-if="category_list.length > 0">
<option v-for="(category, index) in category_list" :key="index" :value="category.id">
{{ category.category_name }}
</option>
</select>
</div>
</div>
</template>
<script>
export default{
data() {
return {
category: null,
category_list: null
};
},
methods: {
getCategory() {
axios
.get("/api/products")
.then((response) => {
this.category_list = response.data;
})
.catch((err) => {
console.log(err);
});
},
}
</script>

Related

Laravel Vue, pass data in form from component after submit

i need a little help about how to get values from a component that is in a form.
This is the form also a photo: form
`
<form #submit.prevent="form.patch(route('profile.update.account'))" class="mt-6 space-y-6">
<div>
<InputLabel for="adresa" value="Adresa" />
<TextInput
id="adresa"
type="text"
class="mt-1 block w-full"
v-model="form.adresa"
required
autofocus
autocomplete="adresa"
/>
<InputError class="mt-2" :message="form.errors.adresa" />
</div>
<DropdownCountries
id="tara"
v-model="form.tara"
required
autocomplete="Romania"
/>
<div class="flex items-center gap-4">
<PrimaryButton :disabled="form.processing">Save</PrimaryButton>
<Transition enter-from-class="opacity-0" leave-to-class="opacity-0" class="transition ease-in-out">
<p v-if="form.recentlySuccessful" class="text-sm text-gray-600">Saved.</p>
</Transition>
</div>
</form>
`
There is the component also a photo: dropdown
`
<template>
<div class="container">
<div class="row justify-content-center" style="margin: 20px 0px 20px 0px;">
<div class="col-md-8">
<div class="card">
<div class="card-body">
<div class="form-group">
<select name="tara" class='form-control' v-model='country' #change='getStates()'>
<option value='0' >Select Country</option>
<option v-for='data in countries' :value='data.id'>{{ data.name }}</option>
</select>
</div>
<div class="form-group">
<select name="judet" class='form-control' v-model='state' #change='getCities()'>
<option value='0' >Select State</option>
<option v-for='data in states' :value='data.id'>{{ data.name }}</option>
</select>
</div>
<div class="form-group">
<select name="oras" class='form-control' v-model='city'>
<option value='0' >Select City</option>
<option v-for='data in cities' :value='data.id'>{{ data.name }}</option>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return {
country: 180,
countries: [],
state: 0,
states: [],
city: 0,
cities: [],
}
},
methods:{
getCountries: function(){
axios.get('/api/tari')
.then(function (response) {
this.countries = response.data;
}.bind(this));
},
getStates: function() {
axios.get('/api/judete/' + this.country).then(function(response){
this.states = response.data;
}.bind(this));
},
getCities: function() {
axios.get('/api/orase/' + this.state).then(function(response) {
this.cities = response.data
}.bind(this));
}
},
created: function(){
this.getCountries()
}
}
</script>
`
My problem is that when i press Save button for submitting the form the values from dropdowns are not applied: response
I've been looking on internet for 2 hours can someone explain me why is that.
You should check this: v-model and child components?
This should answer your question. Let me know if you need more informaiton of how passing v-model values works.

Laravel Vue store data foreign key

<form #submit.prevent="store">
<div class="form-group mb-3">
<label class="form-label">NIP</label>
<input type="text" class="form-control" v-model="pegawai.nomor_induk_pegawai"
placeholder="Masukkan nomor induk pegawai">
<!-- validation -->
<div v-if="validation.nomor_induk_pegawai" class="mt-2 alert alert-danger">
{{ validation.nomor_induk_pegawai[0] }}
</div>
</div>
<div class="form-group mb-3">
<label for="content" class="form-label">Nama Pegawai</label>
<input class="form-control" v-model="pegawai.nama_pegawai"
placeholder="Masukkan nama pegawai">
<!-- validation -->
<div v-if="validation.nama_pegawai" class="mt-2 alert alert-danger">
{{ validation.nama_pegawai[0] }}
</div>
</div>
<div class="form-group mb-3">
<label for="content" class="form-label">Departemen</label>
<select class="form-control" v-model="pegawai.id_departemen">
<option v-for="departemen in departemens" v-bind:value="departemen.id">{{ departemen.nama_departemen }}</option>
</select>
<div v-if="validation.id_departemen" class="mt-2 alert alert-danger">
{{ validation.id_departemen[0] }}
</div>
</div>
<div class="form-group mb-3">
<label class="form-label">Email</label>
<input type="text" class="form-control" v-model="pegawai.email"
placeholder="Masukkan email">
<!-- validation -->
<div v-if="validation.email" class="mt-2 alert alert-danger">
{{ validation.email[0] }}
</div>
</div>
<div class="form-group mb-3">
<label for="content" class="form-label">Telepon</label>
<input class="form-control" v-model="pegawai.telepon" placeholder="Masukkan telepon">
<!-- validation -->
<div v-if="validation.telepon" class="mt-2 alert alert-danger">
{{ validation.telepon[0] }}
</div>
</div>
<div class="form-group mb-3">
<label for="content" class="form-label">Gender</label>
<select class="form-control" v-model="pegawai.gender">
<option value="0"> Wanita </option>
<option value="1"> Pria </option>
</select>
<!-- validation -->
<div v-if="validation.gender" class="mt-2 alert alert-danger">
{{ validation.gender[0] }}
</div>
</div>
<div class="form-group mb-3">
<label for="content" class="form-label">Status</label>
<select class="form-control" v-model="pegawai.status">
<option value="1"> Aktif </option>
<option value="0"> Tidak Aktif </option>
</select>
<!-- validation -->
<div v-if="validation.status" class="mt-2 alert alert-danger">
{{ validation.status[0] }}
</div>
</div>
<button type="submit" class="btn btn-primary">SIMPAN</button>
<script>
import { reactive, ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import axios from 'axios'
export default {
setup() {
//state departemen
const pegawai = reactive({
nomor_induk_pegawai: '',
id_departemen:'',
nama_pegawai: '',
email: '',
telepon: '',
gender: '',
status: ''
})
let departemens = ref([])
onMounted(() => {
//get API from Laravel Backend
axios.get('http://localhost:8000/api/departemens')
.then(response => {
//assign state posts with response data
departemens.value = response.data.data
}).catch(error => {
console.log(error.response.data)
})
})
//state validation
const validation = ref([])
//vue router
const router = useRouter()
//method store
function store() {
let nomor_induk_pegawai = pegawai.nomor_induk_pegawai
let nama_pegawai = pegawai.nama_pegawai
let id_departemen = departemen.id
let email = pegawai.email
let telepon = pegawai.telepon
let gender = pegawai.gender
let status = pegawai.status
axios.post('http://localhost:8000/api/pegawais', {
nomor_induk_pegawai: nomor_induk_pegawai,
nama_pegawai: nama_pegawai,
id_departemen: id_departemen,
email: email,
telepon: telepon,
gender: gender,
status: status
}).then(() => {
//redirect ke post index
router.push({
name: 'pegawai.index'
})
}).catch(error => {
//assign state validation with error
validation.value = error.response.data
})
}
//return
return {
departemens,
pegawai,
validation,
router,
store
}
}
I'm trying to create data in table pegawais with id_departemen as foreign key from table departemens. the dropdown on label departemen suppose to show nama_departemen from table departemen with value id from table department. So I tried this and it said
32:37 error Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key
128:33 error 'departemen' is not defined no-undef
As written in the error, this is how you should have it
<option v-for="departemen in departments"
:value="departemen.id"
:key="departmen.id" // 👈🏻 missing that one
>
{{ departemen.nama_departemen }}
</option>
More details are available here: https://eslint.vuejs.org/rules/require-v-for-key.html
And also here: https://vuejs.org/guide/essentials/list.html#maintaining-state-with-key
TLDR: when using a v-for, add a :key to it.

How to Display a selected grade with its subject?

I want to when a user select a dropdown from the list, a group of subjects available for that grade must be displayed with checkboxes next to them
My controller
public function create()
{
$grades = Grade::with('subjects')->orderBy('slug', 'asc')->get();
return view('admin.users.create', compact( 'grades'));
}
Blade file
<div class="form-group">
<select id="grade" name="grade" class="form-control #error('grade') is-invalid #enderror" v-model="selectedSubjects">
<option value="">Choose a Grade...</option>
#foreach($grades as $grade)
<option value="{{ $grade->id }}" {{ old('grade', $grade) == $grade->name ? 'selected' : "" }}>{{ $grade->name }}</option>
#endforeach
</select>
</div>
<div class="custom-control custom-checkbox mt-2">
#foreach($grade->subjects as $subject)
<input type="checkbox" class="custom-control-input" id="{{$subject->slug}}" name="subjects[]" :value="selectedSubjects" />
<label class="custom-control-label" for="{{$subject->slug}}">{{$subject->name}}</label>
#endforeach
</div>
vue
<script>
window.addEventListener('load',function(){
var app = new Vue({
el: '#app',
data:{
selectedSubjects: {!! $grade->subjects->pluck('name') !!},
}
});
});
</script>
THIS IS IMPOSSIBLE... I GIVE UP
As per I have understood, you want to select grades from dropdown & show its corresponding checkbox as per subjects for the grades.
I would suggest to create a vue component for that lets say grades-component,
in your blade you can add,
<form action="" class="form-control">
#csrf
<grade-component :grades='#json($grades)'></grade-component>
</form>
here in blade, $grades is the object(or array) you are passing via compact. Basically it is to pass your data to the component, we will use that with help of props.
Now you can add your GradeComponent.vue in resources->js->components->GradeComponent.vue
GradeComponent.vue
<template>
<div class="container">
<select v-model="selected_grade" #change="onChange($event)">
<option v-for="grade in grading" :value="grade.slug">{{grade.name}}</option>
</select>
<div class="custom-control custom-checkbox mt-2" v-if="subjects !== null" v-for="subject in subjects">
<input type="checkbox" :id="subject.slug" :value="subject.slug"/>
<label :for="subject.slug">{{subject.name}}</label>
</div>
</div>
</template>
<script>
export default{
props: ['grades'],
data: function() {
return {
grading: this.grades,
selected_grade: null,
subjects : null
}
},
methods: {
onChange(event) {
this.grading.forEach((obj, index) => {
if (obj.slug === event.target.value){
this.subjects = obj.subjects;
}
})
}
}
}
</script>
Now finally you can add it in app.js
Vue.component('grade-component', require('./components/GradeComponent.vue').default);
Then compile your vuejs code, I would use npm run watch
A similar one but with fake data, you can see https://jsfiddle.net/bhucho/2yu4nmws/3/,

two select dynamics vue laravel

I want to load 2 select with vue, I have country, city state, but I don't want to call the js from resources / app.js since I don't need it in all the pages only in a particular sight. I am new to vue. when I load it from resources / app.js if it works but only for status but not for city and in the other pages it throws me an error since it cannot find the object.
I don't want to call him here
require('./bootstrap');
window.Vue = require('vue');
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
//require('./estado');
//require('./ciudad');
so how do i make the call and where do i put the js files
file get state resources/js/estado.js
const app = new Vue({
el: '#app',
data: {
selected_pais: '',
selected_estado: '',
selected_ciudad: '',
estados: [],
ciudades: [],
},
mounted(){
document.getElementById('estado').disabled = true;
this.selected_pais = document.getElementById('pais').getAttribute('data-old');
if(this.selected_pais !='')
{
this.loadEstados();
}
this.selected_estado = document.getElementById('estado').getAttribute('data-old');
document.getElementById('ciudad').disabled = true;
this.selected_estado = document.getElementById('estado').getAttribute('data-old');
if(this.selected_estado !='')
{
this.cargarCiudades();
}
this.selected_ciudad = document.getElementById('ciudad').getAttribute('data-old');
},
methods: {
loadEstados() {
this.selected_estado ='';
document.getElementById('estado').disabled =true;
if (this.selected_pais !="") {
axios.get(`http://127.0.0.1:80/estados/pais`, {params: {pais_id: this.selected_pais} }).then((response) => {
this.estados = response.data;
document.getElementById('estado').disabled =false;
});
}
},
cargarCiudades() {
this.selected_ciudad ='';
document.getElementById('ciudad').disabled =true;
if (this.selected_estado !="") {
axios.get(`http://127.0.0.1:80/ciudades/estado`, {params: {estado_id: this.selected_estado} }).then((response) => {
this.ciudades = response.data;
document.getElementById('ciudad').disabled =false;
});
}
},
}
});
file get city resources/js/ciudades.js
const app = new Vue({
el: '#app',
data: {
selected_estado: '',
selected_ciudad: '',
ciudades: [],
},
mounted(){
document.getElementById('ciudad').disabled = true;
this.selected_estado = document.getElementById('estado').getAttribute('data-old');
if(this.selected_estado !='')
{
this.cargarCiudades();
}
this.selected_ciudad2 = document.getElementById('ciudad').getAttribute('data-old');
},
method: {
cargarCiudades() {
this.selected_ciudad2 ='';
document.getElementById('ciudad').disabled =true;
if (this.selected_estado !="") {
axios.get(`http://127.0.0.1:80/ciudades/estado`, {params: {estado_id: this.selected_estado} }).then((response) => {
this.ciudades = response.data;
document.getElementById('ciudad').disabled =false;
});
}
}
}
});
files view
#extends('layouts.app')
#section('content')
#inject('paises','App\Services\Paises')
<div class="container">
<div class="row">
<div class="col-md-8">
#if ($errors->any())
<div class="alert alert-danger">
<h4>Por Favor corriga los siguientes errores </h4>
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
<form action="/usuarios" method="POST">
#csrf
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputEmail4">Nombre</label>
<input type="text" class="form-control" name="nombre" id="inputEmail4" placeholder="Nombre" value="{{old('nombre')}}">
</div>
<div class="form-group col-md-6">
<label for="inputPassword4">Email</label>
<input type="text" class="form-control" name="email" id="inputPassword4" placeholder="Email" value="{{old('email')}}">
</div>
</div>
<div class="form-group">
<label for="inputAddress">Direccion</label>
<input type="text" class="form-control" id="inputAddress" placeholder="1234 Main St" name="direccion" value="{{old('direccion')}}">
</div>
<div class="form-row">
<div class="form-group col-md-4" id="div_pais">
<label for="inputCity">Pais</label>
<select v-model="selected_pais" id="pais" data-old="{{old('cbo_pais')}}"
v-on:change="loadEstados()" name="cbo_pais" class="form-control">
#foreach ($paises->get() as $index => $pais)
<option value="{{$index}}" >{{$pais}}</option>
#endforeach
</select>
</div>
<div class="form-group col-md-4">
<label for="inputCity">Estado</label>
<select v-model="selected_estado" id="estado" data-old="{{old('cbo_estado')}}"
v-on:change="cargarCiudades()" name="cbo_estado" class="form-control" >
<option value="">Selecione un Estado</option>
<option v-for="(estado, index) in estados" v-bind:value="index">#{{estado}}</option>
</select>
</div>
<div class="form-group col-md-4">
<label for="inputState">Ciudad</label>
<select v-model="selected_ciudad" id="ciudad" data-old="{{old('cbo_ciudad')}}"
name="cbo_ciudad" class="form-control" >
<option value="">Selecione un Ciudad</option>
<option v-for="(ciudad, index) in ciudades" v-bind:value="index">#{{ciudad}}</option>
</select>
</div>
</div>
<div class="form-group">
<label for="inputZip">Zip</label>
<input type="text" class="form-control" id="inputZip" name="zip">
</div>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="gridCheck">
<label class="form-check-label" for="gridCheck">
Check me out
</label>
</div>
</div>
<button type="submit" class="btn btn-primary">Registrar</button>
<button type="reset" class="btn btn-danger">Cancelar</button>
</form>
</div>
</div>
</div>
#endsection
#section('scripts')
#endsection
how do I call the files in the view?

Dynamic select box data binding on vuejs

i have questions about data binding in vuejs and i hope everyone here can help me to solve this problem.
I'm in the stage of learning to use vuejs with laravel. I have problems doing data bindings in the data editing process, I can not display any information in the select box.
Next I include the data response that i want to display and the code.
data response
{
"data":{
"id":101,
"kode":"B100",
"nama":"Bendung Jules Rutherford",
"desa":{
"id":"5103050018",
"district_id":"5103050",
"name":"BONGKASA PERTIWI",
"district":{
"id":"5103050",
"city_id":"5103",
"name":"ABIANSEMAL",
"city":{
"id":"5103",
"province_id":"51",
"name":"KABUPATEN BADUNG",
"province":{
"id":"51",
"name":"BALI",
}
}
}
}
}
}
and this is the code :
<template>
<div>
<div v-if="!loading">
<div class="form-group row">
<label class="col-sm-3">Kode</label>
<div class="col-sm-9">
<input :class="{'is_invalid' : errors.kode}" v-model="bendung.kode" type="text" class="form-control" placeholder="B0001">
<div class="invalid-feedback" v-if="errors.kode">{{ errors.kode[0] }}</div>
</div>
</div>
<div class="form-group row">
<label class="col-sm-3">Nama</label>
<div class="col-sm-9">
<input :class="{'is-invalid': errors.nama}" v-model="bendung.nama" type="text" class="form-control" placeholder="Bendungan Mengwi">
<div class="invalid-feedback" v-if="errors.nama">{{ errors.nama[0] }}</div>
</div>
</div>
<div :class="['form-group row', {'has-error' : errors.provinces }]">
<label class="col-sm-3">Provinsi</label>
<div class="col-sm-9">
<select #change="province" v-model="bendung.desa.district.city.province_id" class="form-control">
<option value="">Pilih Provinsi</option>
<option v-for="province in provinces" :value="province.id">
{{ province.name }}
</option>
</select>
</div>
</div>
<div :class="['form-group row', {'has-error' : errors.cities }]">
<label class="col-sm-3">Kota / Kabupaten</label>
<div class="col-sm-9">
<select #change="city" v-model="bendung.desa.district.city_id" class="form-control">
<option value="">Pilih Kota/Kabupaten</option>
<option v-for="city in cities" :value="city.id">
{{ city.name }}
</option>
</select>
</div>
</div>
</div>
<div class="row" v-else>
<div class="col-sm-12">
<content-placeholders>
<content-placeholders-text/>
</content-placeholders>
</div>
</div>
<div class="form-group row">
<div class="col-sm-3"></div>
<div class="col-sm-9">
<a class="btn btn-success" href="#" :disabled="submiting" #click.prevent="update">
<font-awesome-icon :icon="['fas', 'spinner']" v-if="submiting" />
<font-awesome-icon :icon="['fas', 'check']" v-else/>
<span class="ml-1">Perbaharui</span>
</a>
<a href="/sda/bendung" class="btn btn-danger">
<font-awesome-icon :icon="['fas', 'times-circle']" /> Batal</a>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
errors: {},
bendung: {},
provinces: [],
cities:[],
districts: [],
state: {
province: '',
city: '',
district: '',
},
loading: true,
submiting: false
}
},
mounted() {
this.getBendung();
this.getProvinces();
},
methods: {
getBendung() {
this.loading = true;
let str = window.location.pathname;
let res = str.split("/");
axios.get(`${process.env.MIX_WEBSERVICE_URL}/sda/bendung/${res[3]}`)
.then(response => {
this.bendung = response.data.data;
this.state.province = this.bendung.desa.district.city.province_id;
})
.catch(error => {
this.$toasted.global.error('Bendung tidak ditemukan!');
location.href = '/sda/bendung';
})
.then(() => {
this.loading = false;
});
},
getProvinces() {
axios.get(`${process.env.MIX_WEBSERVICE_URL}/location/province`).then(response => {
this.provinces = response.data;
}).catch(error => console.error(error));
},
province() {
this.state.city = '';
const params = {
province: this.state.province
}
axios.get(`${process.env.MIX_WEBSERVICE_URL}/location/city`, {params}).then(response => {
this.cities = response.data;
}).catch(error => console.error(error));
},
city() {
this.state.district = '';
const params = {
city: this.state.city
};
// /location/district?city=cityId
axios.get(`${process.env.MIX_WEBSERVICE_URL}/location/district`, {params}).then(response => {
this.districts = response.data;
}).catch(error => console.error(error));
}
}
}
</script>
<style scoped>
</style>
the result is like this picture.
i want to show city name on select box but i got blank selectbox and when i change the selectbox (e.g provinsi/province), the other selectbox (e.g. kabupaten/kota/city) will change it data.
You could fetch new data when previous data has been changed.
Here is the working example: https://codesandbox.io/embed/vue-template-2zv2o
Have you tried to use the v-bind:key prop within your v-for loop?
v-bind:key="city.id"
or better with an additional index:
v-for="(city, index) in cities"
[...]
v-bind:key="`${index}-${city.id}`"

Resources