First of all, let me mention that my knowledge of JavaScript and Vue is quite limited as I am still a student. These are not taught in my classes, so if you notice any significant mistakes in my code, please know that I consider it to be expected. I am not yet familiar with best practices or other nuances.
I've encountered an issue while trying to create a dependent combobox.
The first combobox is supposed to update the values in the second one. Although the values in the second combobox get updated, the default value is not "selected", it does not render the default option text.
To provide more context: I am trying to implement a feature where a user selects a floor, which contains several classrooms. When switching from one floor to another, I would like the second combobox to display "select a classroom" as its default value.
This is the code I currently have.
<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';
import APIComboBox from './components/APIComboBox.vue';
// Llamar a la función al montar el componente
onMounted(() => {
cargaListadoPlantas();
});
// Definir las variables reactivas
const plantaSeleccionada = ref('');
const listadoPlantasOpciones = ref([]);
// Función para cargar los datos de la API
const cargaListadoPlantas = async () => {
console.log("Cargando listado plantas.");
try {
const response = await axios.get('http://localhost:8085/floors');
listadoPlantasOpciones.value = response.data;
console.log("Listado obtenido.\n" + response.data);
} catch (error) {
console.error('Error al cargar el listado de valores', error);
}
};
// Función para manejar la selección de plantas
const manejarSeleccionPlantas = (nuevoValor) => {
console.log("Cambios en selección de plantas.");
plantaSeleccionada.value = nuevoValor;
console.log('Valor seleccionado en combo plantas:', nuevoValor);
// Resetea el aula seleccionada y carga el listado de aulas
cargarAulasServidor(plantaSeleccionada.value);
};
const aulaSeleccionada = ref('');
const listadoAulasPlanta = ref([]);
// Función para cargar los datos de la API (Aulas)
const cargarAulasServidor = async (plantaParam) => {
console.log('Recuperando aulas para ' + plantaParam);
try {
const response = await axios.get('http://localhost:8085/classrooms', {
params: { floor: plantaParam }
});
listadoAulasPlanta.value = response.data;
console.log('Aulas recuperadas:\n' + response.data);
aulaSeleccionada.value = '';
} catch (error) {
console.error('Error al cargar el listado de aulas', error);
}
};
// Función para manejar la selección de aula
const manejarSeleccionAula = (nuevoValorAula) => {
console.log("Cambios en selección de aulas.");
aulaSeleccionada.value = nuevoValorAula;
console.log('Valor seleccionado en combobox aulas:', aulaSeleccionada.value);
cargarProyectoresAulas(aulaSeleccionada.value);
};
const listadoProyectores = ref([]);
const selectedRow = ref(null); // Variable para almacenar la fila seleccionada
// Función para cargar los proyectores de un aula específica
const cargarProyectoresAulas = async (aulaParam) => {
console.log('Recuperando proyectores para ' + aulaParam);
try {
const response = await axios.get('http://localhost:8085/classroom-projectors', {
params: { classroom: aulaParam }
});
listadoProyectores.value = response.data;
console.log('Proyectores recuperados:\n' + response.data);
selectedRow.value = null; // Resetea la selección cuando cambia la lista
} catch (error) {
console.error('Error al cargar el listado de proyectores.', error);
}
};
const listadoComandos = ref([]);
// Función para cargar los comandos de un proyector seleccionados
const cargaComandosProyector = async (proyector) => {
console.log('Recuperando comandos para ' + proyector);
try {
const response = await axios.get('http://localhost:8085/commands', {
params: { modelname: proyector }
});
listadoComandos.value = response.data;
console.log('Comandos recuperados:\n' + response.data);
} catch (error) {
console.error('Error al cargar el listado de comandos.', error);
}
};
// Función para manejar la selección de un proyector en la tabla
const proyectorSeleccionado = (index, modelo) => {
console.log('Modelo del proyector:', modelo); // Log para verificar el modelo seleccionado
selectedRow.value = index; // Almacena el índice de la fila seleccionada
cargaComandosProyector(modelo);
};
</script>
<template>
<div class="container mt-3" style="width: 90%; background-color: aqua;">
<h2>Control remoto proyectores.</h2>
<!-- Caja -->
<div class="d-flex justify-content-between">
<div style="width: 49%;">
<div style="background-color: aquamarine;">
<div class="d-flex justify-content-between">
<!-- Componente hijo con el listado de opciones (Plantas) -->
<APIComboBox class="m-2" :opciones="listadoPlantasOpciones" @selectActualizado="manejarSeleccionPlantas" />
<!-- Componente hijo con el listado de opciones (Aulas) -->
<APIComboBox class="m-2" :opciones="listadoAulasPlanta" @selectActualizado="manejarSeleccionAula" :valorSeleccionado="aulaSeleccionada" />
<button type="button" class="btn btn-primary m-2" @click="manejarSeleccionAula(''), manejarSeleccionPlantas()">Reset Aula</button>
</div>
</div>
<!-- caja de la tabla de proyecotres -->
<div style="background-color: azure;">
<table class="table table-hover ml-2 mr-2" >
<thead>
<tr>
<th>Modelo</th>
<th>Aula</th>
</tr>
</thead>
<tbody>
<tr v-for="(projector, index) in listadoProyectores"
:key="index"
@click="proyectorSeleccionado(index, projector.model)"
:class="{ 'table-primary': selectedRow === index }"
class="cursor-pointer">
<td>{{ projector.model }}</td>
<td>{{ projector.classroom }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div style="width: 49%;">
<div style="background-color: bisque; min-height: 100px;">
<table class="table">
<thead>
<tr>
<th>Accion</th>
</tr>
</thead>
<tbody>
<tr v-for="(comando, index) in listadoComandos" :key="index">
<td> {{ comando.action }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</template>
<style scoped>
/* Ensure cursor changes to pointer */
.cursor-pointer {
cursor: pointer;
}
</style>
<script setup>
// Importa las funciones necesarias de Vue
import { defineProps, defineEmits, ref } from 'vue';
// Recibe las opciones como props
const props = defineProps({
opciones: {
type: Array,
required: true, // El listado de opciones es obligatorio
},
});
// Declara una variable reactiva para almacenar el valor seleccionado
const valorSeleccionado = ref(''); // Valor por defecto: cadena vacía
// Define un emisor para comunicar el valor seleccionado al componente padre
const emit = defineEmits(['selectActualizado']);
// Función para emitir el valor seleccionado hacia el componente padre
const emitirSelectActualizado = () => {
emit('selectActualizado', valorSeleccionado.value);
};
</script>
<template>
<div>
<!-- Dropdown para seleccionar el valor -->
<select
v-model="valorSeleccionado"
@change="emitirSelectActualizado"
class="p-2 border border-gray-300 rounded-md">
<!-- Opción predeterminada cuando no hay un valor seleccionado -->
<option value="" selected >Seleccione un valor.</option>
<!-- Genera las opciones dinámicamente desde las props -->
<option
v-for="opcion in props.opciones"
:key="`${opcion}`"
:value="`${opcion}`">
{{ opcion }}
</option>
</select>
</div>
</template>
<style scoped>
</style>
I have tried adjusting the timing of the selected value update by moving it from one function to another. Also, I attempted to introduce a prop attribute to let the parent component specify the selected item. However, this approach did not work either so I backtracked.
I have seen other people having the same problem but their solutions did not work for me.
First of all, let me mention that my knowledge of JavaScript and Vue is quite limited as I am still a student. These are not taught in my classes, so if you notice any significant mistakes in my code, please know that I consider it to be expected. I am not yet familiar with best practices or other nuances.
I've encountered an issue while trying to create a dependent combobox.
The first combobox is supposed to update the values in the second one. Although the values in the second combobox get updated, the default value is not "selected", it does not render the default option text.
To provide more context: I am trying to implement a feature where a user selects a floor, which contains several classrooms. When switching from one floor to another, I would like the second combobox to display "select a classroom" as its default value.
This is the code I currently have.
<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';
import APIComboBox from './components/APIComboBox.vue';
// Llamar a la función al montar el componente
onMounted(() => {
cargaListadoPlantas();
});
// Definir las variables reactivas
const plantaSeleccionada = ref('');
const listadoPlantasOpciones = ref([]);
// Función para cargar los datos de la API
const cargaListadoPlantas = async () => {
console.log("Cargando listado plantas.");
try {
const response = await axios.get('http://localhost:8085/floors');
listadoPlantasOpciones.value = response.data;
console.log("Listado obtenido.\n" + response.data);
} catch (error) {
console.error('Error al cargar el listado de valores', error);
}
};
// Función para manejar la selección de plantas
const manejarSeleccionPlantas = (nuevoValor) => {
console.log("Cambios en selección de plantas.");
plantaSeleccionada.value = nuevoValor;
console.log('Valor seleccionado en combo plantas:', nuevoValor);
// Resetea el aula seleccionada y carga el listado de aulas
cargarAulasServidor(plantaSeleccionada.value);
};
const aulaSeleccionada = ref('');
const listadoAulasPlanta = ref([]);
// Función para cargar los datos de la API (Aulas)
const cargarAulasServidor = async (plantaParam) => {
console.log('Recuperando aulas para ' + plantaParam);
try {
const response = await axios.get('http://localhost:8085/classrooms', {
params: { floor: plantaParam }
});
listadoAulasPlanta.value = response.data;
console.log('Aulas recuperadas:\n' + response.data);
aulaSeleccionada.value = '';
} catch (error) {
console.error('Error al cargar el listado de aulas', error);
}
};
// Función para manejar la selección de aula
const manejarSeleccionAula = (nuevoValorAula) => {
console.log("Cambios en selección de aulas.");
aulaSeleccionada.value = nuevoValorAula;
console.log('Valor seleccionado en combobox aulas:', aulaSeleccionada.value);
cargarProyectoresAulas(aulaSeleccionada.value);
};
const listadoProyectores = ref([]);
const selectedRow = ref(null); // Variable para almacenar la fila seleccionada
// Función para cargar los proyectores de un aula específica
const cargarProyectoresAulas = async (aulaParam) => {
console.log('Recuperando proyectores para ' + aulaParam);
try {
const response = await axios.get('http://localhost:8085/classroom-projectors', {
params: { classroom: aulaParam }
});
listadoProyectores.value = response.data;
console.log('Proyectores recuperados:\n' + response.data);
selectedRow.value = null; // Resetea la selección cuando cambia la lista
} catch (error) {
console.error('Error al cargar el listado de proyectores.', error);
}
};
const listadoComandos = ref([]);
// Función para cargar los comandos de un proyector seleccionados
const cargaComandosProyector = async (proyector) => {
console.log('Recuperando comandos para ' + proyector);
try {
const response = await axios.get('http://localhost:8085/commands', {
params: { modelname: proyector }
});
listadoComandos.value = response.data;
console.log('Comandos recuperados:\n' + response.data);
} catch (error) {
console.error('Error al cargar el listado de comandos.', error);
}
};
// Función para manejar la selección de un proyector en la tabla
const proyectorSeleccionado = (index, modelo) => {
console.log('Modelo del proyector:', modelo); // Log para verificar el modelo seleccionado
selectedRow.value = index; // Almacena el índice de la fila seleccionada
cargaComandosProyector(modelo);
};
</script>
<template>
<div class="container mt-3" style="width: 90%; background-color: aqua;">
<h2>Control remoto proyectores.</h2>
<!-- Caja -->
<div class="d-flex justify-content-between">
<div style="width: 49%;">
<div style="background-color: aquamarine;">
<div class="d-flex justify-content-between">
<!-- Componente hijo con el listado de opciones (Plantas) -->
<APIComboBox class="m-2" :opciones="listadoPlantasOpciones" @selectActualizado="manejarSeleccionPlantas" />
<!-- Componente hijo con el listado de opciones (Aulas) -->
<APIComboBox class="m-2" :opciones="listadoAulasPlanta" @selectActualizado="manejarSeleccionAula" :valorSeleccionado="aulaSeleccionada" />
<button type="button" class="btn btn-primary m-2" @click="manejarSeleccionAula(''), manejarSeleccionPlantas()">Reset Aula</button>
</div>
</div>
<!-- caja de la tabla de proyecotres -->
<div style="background-color: azure;">
<table class="table table-hover ml-2 mr-2" >
<thead>
<tr>
<th>Modelo</th>
<th>Aula</th>
</tr>
</thead>
<tbody>
<tr v-for="(projector, index) in listadoProyectores"
:key="index"
@click="proyectorSeleccionado(index, projector.model)"
:class="{ 'table-primary': selectedRow === index }"
class="cursor-pointer">
<td>{{ projector.model }}</td>
<td>{{ projector.classroom }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div style="width: 49%;">
<div style="background-color: bisque; min-height: 100px;">
<table class="table">
<thead>
<tr>
<th>Accion</th>
</tr>
</thead>
<tbody>
<tr v-for="(comando, index) in listadoComandos" :key="index">
<td> {{ comando.action }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</template>
<style scoped>
/* Ensure cursor changes to pointer */
.cursor-pointer {
cursor: pointer;
}
</style>
<script setup>
// Importa las funciones necesarias de Vue
import { defineProps, defineEmits, ref } from 'vue';
// Recibe las opciones como props
const props = defineProps({
opciones: {
type: Array,
required: true, // El listado de opciones es obligatorio
},
});
// Declara una variable reactiva para almacenar el valor seleccionado
const valorSeleccionado = ref(''); // Valor por defecto: cadena vacía
// Define un emisor para comunicar el valor seleccionado al componente padre
const emit = defineEmits(['selectActualizado']);
// Función para emitir el valor seleccionado hacia el componente padre
const emitirSelectActualizado = () => {
emit('selectActualizado', valorSeleccionado.value);
};
</script>
<template>
<div>
<!-- Dropdown para seleccionar el valor -->
<select
v-model="valorSeleccionado"
@change="emitirSelectActualizado"
class="p-2 border border-gray-300 rounded-md">
<!-- Opción predeterminada cuando no hay un valor seleccionado -->
<option value="" selected >Seleccione un valor.</option>
<!-- Genera las opciones dinámicamente desde las props -->
<option
v-for="opcion in props.opciones"
:key="`${opcion}`"
:value="`${opcion}`">
{{ opcion }}
</option>
</select>
</div>
</template>
<style scoped>
</style>
I have tried adjusting the timing of the selected value update by moving it from one function to another. Also, I attempted to introduce a prop attribute to let the parent component specify the selected item. However, this approach did not work either so I backtracked.
I have seen other people having the same problem but their solutions did not work for me.
Share Improve this question asked 2 days ago david giandavid gian 1 New contributor david gian is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.1 Answer
Reset to default 0I found the issue.
You tried to pass a prop named valorSeleccionado
in this line:
<APIComboBox class="m-2" :opciones="listadoAulasPlanta" @selectActualizado="manejarSeleccionAula" :valorSeleccionado="aulaSeleccionada" />
However, you have never declared this prop in your APIComboBox
component.
The correct way to declare the prop in your APIComboBox component is:
const props = defineProps({
opciones: {
type: Array,
required: true, // List of options is mandatory
},
valorSeleccionado: {
type: [String, Number], // The selected value passed from the parent
default: '' // Default value is an empty string
}
});
This ensures that the valorSeleccionado prop is properly received by the APIComboBox component and that its value is bound correctly.