¿Cómo hacer que se seleccionen filtros de color por defecto?

Angelicahg

Angelicahg

Gamma
Verificado
Verificación en dos pasos activada
Verificado por Whatsapp
Verificado por Binance
Hola, estoy desarrollando una página de prácticas que incluye un catálogo público y otro privado. Desde el catálogo privado puedo añadir, editar y gestionar modelos que luego se muestran en el catálogo público. Cada modelo tiene filtros asociados, como color, temática, etc. Al hacer clic en "Editar", necesito que se cargue automáticamente toda la información del modelo (nombre, precio, temática, imágenes, etc.).

Hasta ahora he logrado que todo se cargue correctamente, excepto los filtros de color. En el backend los valores sí se reflejan (como se muestra en la imagen de la derecha en la consola), pero visualmente no se seleccionan en el filtro de color. En la segunda imagen muestro cómo deberían aparecer por defecto.

Lo que está marcado en verde es el resultado que quiero lograr: que al entrar a editar un modelo, se vean seleccionados por defecto los colores que ya tiene asignados. He intentado varias soluciones, incluso con ayuda de ChatGPT, pero aún no encuentro cómo resolverlo. Creo que el problema es principalmente visual o del lado del frontend


1752421415499.webp


Lo marcado en verde quiero que salga asi cada vez que de en editar osea que se vea reflejado los colores que tiene



1752421374319.webp



Mis codigos

editar_modelo_completo.php
PHP:
document.addEventListener("DOMContentLoaded", async () => {
  const id = new URLSearchParams(window.location.search).get("id");
  const form = document.getElementById("form-editar-modelo");
  const quill = new Quill("#editor-quill", { theme: "snow" });

  const colorSelect = document.getElementById("color");
  const tematicaSelect = document.getElementById("tematica");

  let colorChoices = null;
  let tematicaChoices = null;

  try {
    const res = await fetch("controllers/catalogo/obtener_modelos.php?id=" + id);
    const data = await res.json();
    console.log("📦 Datos recibidos:", data);

    if (!data.success || !data.modelo) {
      throw new Error(data.message || "Modelo no encontrado");
    }

    const modelo = data.modelo;

    document.getElementById("modelo_id").value = modelo.id;
    document.getElementById("titulo").value = modelo.titulo;
    document.getElementById("precio").value = modelo.precio;
    document.getElementById("tipo").value = modelo.tipo || "boda";
    document.getElementById("publico").checked = modelo.publico == 1;
    quill.root.innerHTML = modelo.descripcion || "";

    if (modelo.imagen) {
      document.getElementById("preview-portada").innerHTML =
        `<img src="${modelo.imagen}" style="max-width:100%; border-radius:8px;">`;
    }

    // ✅ Inicializar Choices para Colores desde <option> en HTML
    colorChoices = new Choices(colorSelect, {
      removeItemButton: true,
      searchEnabled: false,
      itemSelectText: '',
      shouldSort: false,
    });

    // ✅ Marcar visualmente los colores seleccionados desde el modelo
    if (Array.isArray(modelo.colores)) {
      setTimeout(() => {
        colorChoices.removeActiveItems();
        modelo.colores.forEach(color => {
          colorChoices.setChoiceByValue(color.toLowerCase());
        });
      }, 100); // Espera corta para que Choices termine de inicializar
    }

    // ✅ Temática visual
    if (Array.isArray(modelo.tematicas) && modelo.tematicas.length > 0 && tematicaSelect) {
      const valor = modelo.tematicas[0];
      const option = tematicaSelect.querySelector(`option[value="${valor}"]`);
      if (option) option.selected = true;

      const instanciaTematica = (window.Choices?.instances || []).find(c => c.passedElement.element.id === "tematica");
      if (instanciaTematica) instanciaTematica.destroy();

      tematicaChoices = new Choices(tematicaSelect, {
        searchEnabled: false,
        itemSelectText: '',
        shouldSort: false,
      });
    }

    // ✅ Galería de imágenes
    const galeria = modelo.galeria || [];
    if (galeria.length > 0) {
      const contenedor = document.getElementById("galeria-existente");
      galeria.forEach(img => {
        const div = document.createElement("div");
        div.className = "item-galeria";
        div.innerHTML = `<img src="${img.imagen}" style="max-width: 120px; border-radius: 6px;">`;
        contenedor.appendChild(div);
      });
    }

    // ✅ Envío del formulario
    form.addEventListener("submit", async (e) => {
      e.preventDefault();
      const formData = new FormData(form);
      formData.set("descripcion", quill.root.innerHTML);

      // Colores seleccionados
      if (colorChoices) {
        colorChoices.getValue(true).forEach(valor => {
          formData.append("colores[]", valor);
        });
      }

      // Temática seleccionada
      if (tematicaChoices) {
        const tematica = tematicaChoices.getValue(true);
        if (tematica?.length > 0) {
          formData.append("tematicas[]", tematica[0]);
        }
      }

      if (typeof mostrarModalCargando === 'function') mostrarModalCargando("Guardando modelo...");

      try {
        const res = await fetch("controllers/catalogo/editar_modelo.php", {
          method: "POST",
          body: formData
        });
        const result = await res.json();
        console.log("✅ Respuesta al guardar:", result);

        if (typeof ocultarModalCargando === 'function') ocultarModalCargando();

        if (result.success) {
          if (typeof mostrarModal === 'function') {
            mostrarModal({
              icono: "✅",
              titulo: "¡Guardado!",
              mensaje: "El modelo fue actualizado correctamente.",
              onClose: () => window.location.href = "index.php?page=catalogo"
            });
          } else {
            alert("Modelo guardado correctamente.");
            window.location.href = "index.php?page=catalogo";
          }
        } else {
          throw new Error(result.message);
        }

      } catch (err) {
        if (typeof ocultarModalCargando === 'function') ocultarModalCargando();
        console.error("❌ Error en envío:", err);
        if (typeof mostrarModalError === 'function') {
          mostrarModalError({ titulo: "Error", mensaje: err.message || "No se pudo guardar." });
        } else {
          alert("Error al guardar modelo: " + err.message);
        }
      }
    });

  } catch (err) {
    console.error("❌ Error al cargar modelo:", err);
    if (typeof mostrarModalError === 'function') {
      mostrarModalError({
        titulo: "Error inesperado",
        mensaje: "No se pudo cargar el modelo. Intenta más tarde."
      });
    } else {
      alert("Error general al cargar.");
    }
  }
});

form-editar-modelo.php


PHP:
<?php
require_once __DIR__ . '/../../config/config.php';
require_once __DIR__ . '/../../config/db.php';

$idModelo = $_GET['id'] ?? null;
?>

<!-- PANEL EDICIÓN DE MODELO -->
<section class="panel-catalogo edicion-modelo-activa">
  <h2 class="titulo-edicion">Editar modelo</h2>

  <form id="form-editar-modelo" method="post" enctype="multipart/form-data" class="formulario-base formulario-catalogo">
    <input type="hidden" name="modelo_id" id="modelo_id">

    <!-- Vista previa portada -->
    <div>
      <label>Imagen actual:</label>
      <div id="preview-portada" class="preview-portada"></div>
    </div>

    <!-- Portada -->
    <div>
      <label for="imagen">Cambiar imagen de portada:</label>
      <div class="input-dropzone">
        Haz clic o arrastra una imagen aquí
        <input type="file" id="imagen" name="imagen" accept="image/*">
      </div>
    </div>
   
    <!-- Galería -->
    <div>
      <label for="galeria">Imágenes adicionales:</label>
      <div class="input-dropzone">
        Haz clic o arrastra aquí para subir imágenes
        <input type="file" id="galeria" name="galeria[]" multiple accept="image/*">
      </div>
      <div id="galeria-existente" class="galeria-actual"></div>
    </div>
   
    <!-- Título y precio -->
    <div class="grupo-doble">
      <div>
        <label for="titulo">Nombre del modelo:</label>
        <input type="text" id="titulo" name="titulo" required>
      </div>
      <div>
        <label for="precio">Precio:</label>
        <input type="number" id="precio" name="precio" step="0.01" required>
      </div>
    </div>

    <!-- Tipo de evento -->
    <div>
      <label for="tipo">Tipo de evento:</label>
      <select id="tipo" name="tipo" required>
        <option value="">Selecciona una opción</option>
        <option value="boda">Boda</option>
        <option value="quinceaños">Quinceaños</option>
        <option value="graduación">Graduación</option>
        <option value="aniversario">Aniversario</option>
        <option value="babyshower">BabyShower</option>
        <option value="cumpleaños">Cumpleaños</option>
        <option value="evento">Eventos</option>
      </select>
    </div>
   
    <!-- Selects múltiples -->
    <div class="grupo-doble">
      <div>
        <label for="color">Colores:</label>
        <select id="color" name="colores[]" multiple class="select-filtro" data-preservar>
          <option value="azul">Azul</option>
          <option value="rojo">Rojo</option>
          <option value="verde">Verde</option>
          <option value="dorado">Dorado</option>
          <option value="rosa">Rosa</option>
          <option value="negro">Negro</option>
          <option value="blanco">Blanco</option>
          <option value="morado">Morado</option>
          <option value="plateado">Plateado</option>
        </select>
      </div>
      <div>
        <label for="tematica">Temática visual:</label>
        <select id="tematica" name="tematicas[]" class="select-filtro" required>
          <option value="">Selecciona una opción</option>
          <option value="flores">Flores</option>
          <option value="mariposas">Mariposas</option>
          <option value="discoteca">Discoteca</option>
          <option value="princesas">Princesas</option>
          <option value="clasico">Clásico</option>
          <option value="moderno">Moderno</option>
          <option value="acuarela">Acuarela</option>
        </select>
      </div>
    </div>
    <!-- Descripción -->
    <div>
      <label for="descripcion">Descripción larga:</label>
      <div id="editor-quill"></div>
      <input type="hidden" name="descripcion" id="descripcion">
    </div>





    <!-- Visibilidad -->
    <div class="switch-contenedor">
      <label class="switch">
        <input type="checkbox" name="publico" id="publico">
        <span class="slider round"></span>
      </label>
      <span class="switch-label">Mostrar en catálogo público</span>
    </div>

    <!-- Token -->
    <input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">

    <!-- Botones -->
    <div class="fila-botones">
      <button type="submit" class="btn">
        <span class="btn-text">Guardar cambios</span>
        <span class="spinner" style="display: none;"></span>
      </button>
      <a href="index.php?page=catalogo" class="btn secundario">Volver al catálogo</a>
    </div>
  </form>
</section>

<!-- Quill -->
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
<script src="https://cdn.quilljs.com/1.3.6/quill.min.js"></script>

init_choices.js


JavaScript:
// ✅ init_choices.js - Inicialización de Choices.js con estilos personalizados y banderas

document.addEventListener('DOMContentLoaded', () => {
  const skipIds = ['codigo_pais', 'filtro-color', 'filtro-tematica', 'filtro-orden', 'tematica', 'tipo'];

  // ✅ Inicializar todos los selects genéricos (excepto los ignorados)
  document.querySelectorAll('.select-filtro').forEach(select => {
    if (skipIds.includes(select.id)) return;

    const isMultiple = select.multiple;

    const choicesInstance = new Choices(select, {
      removeItemButton: isMultiple,
      searchEnabled: false,
      itemSelectText: '',
      shouldSort: false
    });

    select.closest('.choices')?.classList.add('filtro-personalizado');
  });

  // ✅ Código país con banderas
  const codigoPaisSelect = document.getElementById('codigo_pais');
  if (codigoPaisSelect) {
    new Choices(codigoPaisSelect, {
      searchEnabled: false,
      itemSelectText: '',
      shouldSort: false,
      allowHTML: true,
      callbackOnCreateTemplates: function (template) {
        return {
          item: function (classNames, data) {
            const flag = data.customProperties?.flag || '';
            return template(`
              <div class="${classNames.item} ${classNames.itemSelectable}">
                <span class="fi fi-${flag} bandera-circle" style="margin-right: 6px;"></span>${data.label}
              </div>
            `);
          },
          choice: function (classNames, data) {
            const flag = data.customProperties?.flag || '';
            return template(`
              <div class="${classNames.item} ${classNames.itemChoice}" data-choice data-id="${data.id}" data-value="${data.value}" ${data.active ? 'aria-selected="true"' : ''}>
                <span class="fi fi-${flag} bandera-circle" style="margin-right: 6px;"></span>${data.label}
              </div>
            `);
          }
        };
      }
    });
  }

  // ✅ Plantilla con íconos HTML (para filtros públicos)
  const renderHTMLTemplate = (template) => ({
    item: (classNames, data) => {
      const icon = data.customProperties?.icon || '';
      return template(`
        <div class="${classNames.item} ${classNames.itemSelectable}">
          ${icon} ${data.label}
        </div>
      `);
    },
    choice: (classNames, data) => {
      return template(`
        <div class="${classNames.item} ${classNames.itemChoice}" data-choice data-id="${data.id}" data-value="${data.value}" ${data.active ? 'aria-selected="true"' : ''}>
          ${data.label}
        </div>
      `);
    }
  });

  // ✅ Inicializar filtros públicos con íconos
  const initPublicFilterWithIcons = (id, globalVarName) => {
    const el = document.getElementById(id);
    if (!el) return;

    const options = Array.from(el.options).map(opt => ({
      value: opt.value,
      label: opt.textContent,
      selected: opt.selected,
      disabled: opt.disabled,
      customProperties: {
        icon: opt.dataset.icon || ''
      }
    }));

    // ❌ NO borres las <option> si el select será reutilizado en modo edición
    if (!el.hasAttribute("data-preservar")) {
      el.innerHTML = '';
    }

    window[globalVarName] = new Choices(el, {
      searchEnabled: false,
      itemSelectText: '',
      shouldSort: false,
      allowHTML: true,
      callbackOnCreateTemplates: renderHTMLTemplate,
      choices: options
    });
  };

  // ✅ Filtros públicos con íconos
  initPublicFilterWithIcons('filtro-color', 'choicesColor');
  initPublicFilterWithIcons('filtro-tematica', 'choicesTematica');
  initPublicFilterWithIcons('filtro-orden', 'choicesOrden');
});

// ✅ Corrige íconos tras reinicio
function sincronizarIconoSelect(choicesInstance) {
  const selected = choicesInstance.getValue(true);
  const option = choicesInstance.config.choices.find(c => c.value === selected);
  const icon = option?.customProperties?.icon || '';

  const items = document.querySelectorAll(`#${choicesInstance.passedElement.element.id} + .choices .choices__inner .choices__item`);

  if (items.length > 0 && icon) {
    items[0].innerHTML = `${icon} ${option.label}`;
  }
}

datos_choices.js


JavaScript:
// 📁 public/js/global/datos_choices.js

export const opcionesColor = [
  { value: '', label: 'Color', selected: true, disabled: true, customProperties: { icon: '<i class="fa-solid fa-palette"></i>' } },
  { value: 'azul', label: 'Azul' },
  { value: 'rosa', label: 'Rosa' },
  { value: 'verde', label: 'Verde' },
  { value: 'dorado', label: 'Dorado' },
  { value: 'plateado', label: 'Plateado' },
  { value: 'blanco', label: 'Blanco' },
  { value: 'negro', label: 'Negro' },
  { value: 'rojo', label: 'Rojo' },
  { value: 'fucsia', label: 'Fucsia' },
  { value: 'celeste', label: 'Celeste' },
  { value: 'morado', label: 'Morado' },
  { value: 'amarillo', label: 'Amarillo' },
  { value: 'beige', label: 'Beige' }
];

export const opcionesTematica = [
  { value: '', label: 'Temática', selected: true, disabled: true, customProperties: { icon: '<i class="fa-solid fa-brush"></i>' } },
  { value: 'flores', label: 'Flores' },
  { value: 'mariposas', label: 'Mariposas' },
  { value: 'discoteca', label: 'Discoteca' },
  { value: 'princesas', label: 'Princesas' },
  { value: 'clasico', label: 'Clásico' },
  { value: 'moderno', label: 'Moderno' },
  { value: 'acuarela', label: 'Acuarela' }
];

export const opcionesOrden = [
  { value: '', label: 'Ordenar', selected: true, disabled: true, customProperties: { icon: '<i class="fa-solid fa-arrow-down-wide-short"></i>' } },
  { value: 'az', label: 'A-Z' },
  { value: 'za', label: 'Z-A' },
  { value: 'recientes', label: 'Más reciente' },
  { value: 'viejos', label: 'Más viejo' }
];

Si alguien sabe se lo agradeceria
 
Bueno por ahora ire directo al grano, donde esta la clase "Choices" es una libreria publica, privada? por lo visto es quien se encarga del efecto visual que quieres lograr. pero solo viendo sus parametros lo unico que puedo deducir es que la estes implementando incorrectamente.

como sugerencia:

aisla el problema. separalo algo como


HTML:
<div>
    <label for="color">Colores:</label>
    <select id="color" name="colores[]" multiple class="select-filtro" data-preservar>
      <option value="azul">Azul</option>
      <option value="rojo">Rojo</option>
      <option value="verde">Verde</option>
      <option value="dorado">Dorado</option>
      <option value="rosa">Rosa</option>
      <option value="negro">Negro</option>
      <option value="blanco">Blanco</option>
      <option value="morado">Morado</option>
      <option value="plateado">Plateado</option>
    </select>
</div>
<script type="text/javascript">
    const datosFake = {
        success:true,
        modelo:{
            "titulo":"zyu",
            // otros datos irrelevantes
            "colores": ["rojo","verde","fuchi"]
        }
    };
    const colorSelect = document.getElementById("color");
    let colorChoices = null;
    // ✅ Inicializar Choices para Colores desde <option> en HTML
    colorChoices = new Choices(colorSelect, {
      removeItemButton: true,
      searchEnabled: false,
      itemSelectText: '',
      shouldSort: false,
    });
    // ✅ Marcar visualmente los colores seleccionados desde el modelo
    if (Array.isArray(datosFake.modelo.colores)) {
      setTimeout(() => {
        colorChoices.removeActiveItems();
        datosFake.modelo.colores.forEach(color => {
          colorChoices.setChoiceByValue(color.toLowerCase());
          //hacemos prueba y deberia ejecutarse por que concide los colores
          console.log("✅ color " + color +" dentro del choice")
        });
      }, 100); // Espera corta para que Choices termine de inicializar
    }
</script>

recuerda javascript tiene un poderoso debugger , y puedes ver que pasa paso a paso.

Recomendaciones del mensaje:

en los foros es mejor ser directo y breve, cuando pones muchos archivos sin relacion alguna, puede asustar o hacer que sea ignorado tu mensaje por los usuarios. y en resumen disminuyes las respuestas q podrias recibir. ahora con esto de la IA se pone de moda pegar todo. pero en foros o eres breve o bien das un LINK, que lleve al repositorio del proyecto o a un servidor de pruebas que tengas. esto.


Recomendaciones de Programador:

trata de codificar con buenas practicas y recomendaciones.
javascript tambien tiene sus patrones de diseño, que suelen ser recomendados, TESTING, creeme a nadie le gusta hacer test. pero cuando te habituas, aunque sea de forma sencilla. un IF con ALERTs o CONSOLE.log bastan para saber que tu script, funciona.
y por si acaso el mundo de los CustomElements que tiene javascript. podrian simplificarte la vida. simplificar tu codigo. y acostumbrarte a modularizar y separar responsabilidades.
 
Bueno por ahora ire directo al grano, donde esta la clase "Choices" es una libreria publica, privada? por lo visto es quien se encarga del efecto visual que quieres lograr. pero solo viendo sus parametros lo unico que puedo deducir es que la estes implementando incorrectamente.

como sugerencia:

aisla el problema. separalo algo como


HTML:
<div>
    <label for="color">Colores:</label>
    <select id="color" name="colores[]" multiple class="select-filtro" data-preservar>
      <option value="azul">Azul</option>
      <option value="rojo">Rojo</option>
      <option value="verde">Verde</option>
      <option value="dorado">Dorado</option>
      <option value="rosa">Rosa</option>
      <option value="negro">Negro</option>
      <option value="blanco">Blanco</option>
      <option value="morado">Morado</option>
      <option value="plateado">Plateado</option>
    </select>
</div>
<script type="text/javascript">
    const datosFake = {
        success:true,
        modelo:{
            "titulo":"zyu",
            // otros datos irrelevantes
            "colores": ["rojo","verde","fuchi"]
        }
    };
    const colorSelect = document.getElementById("color");
    let colorChoices = null;
    // ✅ Inicializar Choices para Colores desde <option> en HTML
    colorChoices = new Choices(colorSelect, {
      removeItemButton: true,
      searchEnabled: false,
      itemSelectText: '',
      shouldSort: false,
    });
    // ✅ Marcar visualmente los colores seleccionados desde el modelo
    if (Array.isArray(datosFake.modelo.colores)) {
      setTimeout(() => {
        colorChoices.removeActiveItems();
        datosFake.modelo.colores.forEach(color => {
          colorChoices.setChoiceByValue(color.toLowerCase());
          //hacemos prueba y deberia ejecutarse por que concide los colores
          console.log("✅ color " + color +" dentro del choice")
        });
      }, 100); // Espera corta para que Choices termine de inicializar
    }
</script>

recuerda javascript tiene un poderoso debugger , y puedes ver que pasa paso a paso.

Recomendaciones del mensaje:

en los foros es mejor ser directo y breve, cuando pones muchos archivos sin relacion alguna, puede asustar o hacer que sea ignorado tu mensaje por los usuarios. y en resumen disminuyes las respuestas q podrias recibir. ahora con esto de la IA se pone de moda pegar todo. pero en foros o eres breve o bien das un LINK, que lleve al repositorio del proyecto o a un servidor de pruebas que tengas. esto.


Recomendaciones de Programador:

trata de codificar con buenas practicas y recomendaciones.
javascript tambien tiene sus patrones de diseño, que suelen ser recomendados, TESTING, creeme a nadie le gusta hacer test. pero cuando te habituas, aunque sea de forma sencilla. un IF con ALERTs o CONSOLE.log bastan para saber que tu script, funciona.
y por si acaso el mundo de los CustomElements que tiene javascript. podrian simplificarte la vida. simplificar tu codigo. y acostumbrarte a modularizar y separar responsabilidades.
Tienes razon, ya he colocado muchos debugger y carga todo bien hasta dice que se encontro el color, y que cargo y todo pero no se visualizan, pero he estado viendo y parece ser un problema comun con la libreria de choices y es muy tedioso ya que es una tonteria solo necesito que salgan las etiquetas de "X" producto al yo editar un producto para saber que etiquetas de color tiene ya y si quiero eliminar o agregar más


editar_modelo_completo.js:12 📦 Datos recibidos: {success: true, modelo: {…}}
editar_modelo_completo.js:31 📋 Colores del modelo: ['negro']
editar_modelo_completo.js:37 🔧 Inicializando Choices para colores...
choices.min.js:2 Trying to initialise Choices on element already initialised {element: select#color.select-filtro.choices__input}
e @ choices.min.js:2
(anonymous) @ editar_modelo_completo.js:38
editar_modelo_completo.js:48 ✅ Choices encontrado, asignando colores...
editar_modelo_completo.js:57 🎨 Seleccionando color: negro
editar_modelo_completo.js:61 ✅ Color reflejado visualmente: negro
editar_modelo_completo.js:85 ✅ Temática seleccionada: moderno
editar_modelo_completo.js:71 ✨ UI actualizada con colores pre-cargados

Me dice que todo esta cargado, y listo pero no se visualiza estoy que exploto, creo que tratare de hacerlo de otra forma que no sea con choices
 
He probado con todo
Pero por lo que veo tienes que crear un array con todos los valores y a los que estan seleccionados le agregas "selected: true"

Osea dejas el select html vacio y ya con js te cargara todo y los selecionados y no selecionados

HTML:
<select id="color" name="colores[]" multiple class="select-filtro" data-preservar>
</select>

JavaScript:
colorChoices = new Choices(colorSelect, {
    removeItemButton: true,
    searchEnabled: false,
    itemSelectText: '',
    shouldSort: false,
    choices: [
        { value: 'rojo', label: 'Rojo', selected: true },
        { value: 'negro', label: 'Negro'}
    ]
});
],

Aqui funciona bien: https://choices-js.github.io/Choices/
 
Pero por lo que veo tienes que crear un array con todos los valores y a los que estan seleccionados le agregas "selected: true"

Osea dejas el select html vacio y ya con js te cargara todo y los selecionados y no selecionados

HTML:
<select id="color" name="colores[]" multiple class="select-filtro" data-preservar>
</select>

JavaScript:
colorChoices = new Choices(colorSelect, {
    removeItemButton: true,
    searchEnabled: false,
    itemSelectText: '',
    shouldSort: false,
    choices: [
        { value: 'rojo', label: 'Rojo', selected: true },
        { value: 'negro', label: 'Negro'}
    ]
});
],

Aqui funciona bien: https://choices-js.github.io/Choices/
Graciasss, intentare replicarlo, busque y busque algo similar a la pagina que me enviaste y no encontraba nada asi
 
Dale, tambien veo que con setChoiceByValue funciona bien
Gracias eres un crack, el problema viene de que tengo crear_modelo.js y editar_modelo_completo.js, en donde los dos inicializaban el choices de color y creaba un bug, entonces la solucion fue colocar una instancia de que si estoy en la pagina de editar modelo, no se inicialice crear_modelo.js y a la vez tambien hice lo del setChoiceByValue, todo era una tonteria pero no se pq no lo veia antes gracias !
 
Última edición:
hum... "entonces la solucion fue colocar una instancia de que si estoy en la pagina de editar modelo, no se inicialice crear_modelo.js", eso de "colocar una instancia de que si estoy..." 🤔, le consultaba tu caso a mi jefe y él me dice: "es un caso donde se ha resuelto el problema pero sin saber bien por qué".

para ponerme a prueba, repliqué tu problema y aquí está lo que más o menos era tu página cuando no funcionaba bien:
https://wpe.oscaralderete.com/tests/forobeta895647/original.php

y aquí cuando está resuelto:
https://wpe.oscaralderete.com/tests/forobeta895647/

sugiero revisen el código y, obvio, activen el inspector van a ver algo parecido a estos screenshots:

Screenshot from 2025-07-15 11-55-10.webp


Screenshot from 2025-07-15 11-55-27.webp


tu error es que intentabas inicializar un objeto Choices la librería JavaScript que está usando para el multiselect antes de que la data que necesite se cargue. "no sé por qué cara** carga los datos usando un fetch cuando puede hacerlo directamente en la página que renderiza el form", son las palabras de mi jefe 🤣, tranquila que a mi me dice cosas peores cuando fallo. Pero es cierto, salvo que uses una API externa no tiene sentido que una vez cargada la página uses un fecth para llamar a un data feeder que está en el mismo servidor. En términos de eficiencia llamas al servidor 2 veces cuando puedes hacerlo solo 1 y si luego no entiendes que fetch() al ser asíncrono no está disponible de inmediato.

"eso pasa cuando haces copy and paste y ni siquiera entiendes lo que haces" 🤣, de nuevo son palabras de mi jefe pero tiene razón porque init_choices.js y datos_choices.js están sobrando en este caso como luego te diste cuenta pero además tienen datos que ni siquiera estás usando, al menos en esta parte.

Esto debería servir a todos los programadores, no está mal hacer copy and paste ni siquiera usar la AI. En mi caso, le pasé la imagen que la usuaria compartió y le dije que en base a eso me devuelva el json, me devolvió un json al que solo corregí en 2 partes y le dije con base a este json genérame un php que actúe como un pseudo-api y me devolvió esto:

Insertar CODE, HTML o PHP:
<?php
// pseudo-api.php

$data = [
    "success" => true,
    "modelo" => [
        "id" => 51,
        "titulo" => "XV Modelo 2",
        "precio" => 45.00,
        "tipo" => "babyshower",
        "descripcion" => "",
        "publico" => 1,
        "imagen" => "https://upload.wikimedia.org/wikipedia/commons/a/a0/Suushi_Yurei.jpg",
        "colores" => ["rojo", "verde", "rosa"],
        "tematicas" => ["discoteca"],
        "galeria" => []
    ]
];

// Set the content type header to application/json
header('Content-Type: application/json');

// Output the JSON representation of the array
echo json_encode($data);

que sirve para rápidamente emular el servicio al que el fetch() llama:
https://wpe.oscaralderete.com/tests/forobeta895647/pseudo-api.php

sugerir a los programadores que revisen el código, volviendo a la idea anterior, no está mal hacer un copy and paste, pero hay que darse un tiempo para ver qué hace ese código y tratar de entenderlo. Eso es lo que no hace la IA, y si quieres sobrevivir como programador es lo que hay que hacer.
 
hum... "entonces la solucion fue colocar una instancia de que si estoy en la pagina de editar modelo, no se inicialice crear_modelo.js", eso de "colocar una instancia de que si estoy..." 🤔, le consultaba tu caso a mi jefe y él me dice: "es un caso donde se ha resuelto el problema pero sin saber bien por qué".

para ponerme a prueba, repliqué tu problema y aquí está lo que más o menos era tu página cuando no funcionaba bien:
https://wpe.oscaralderete.com/tests/forobeta895647/original.php

y aquí cuando está resuelto:
https://wpe.oscaralderete.com/tests/forobeta895647/

sugiero revisen el código y, obvio, activen el inspector van a ver algo parecido a estos screenshots:

Ver el archivo adjunto 1484329

Ver el archivo adjunto 1484331

tu error es que intentabas inicializar un objeto Choices la librería JavaScript que está usando para el multiselect antes de que la data que necesite se cargue. "no sé por qué cara** carga los datos usando un fetch cuando puede hacerlo directamente en la página que renderiza el form", son las palabras de mi jefe 🤣, tranquila que a mi me dice cosas peores cuando fallo. Pero es cierto, salvo que uses una API externa no tiene sentido que una vez cargada la página uses un fecth para llamar a un data feeder que está en el mismo servidor. En términos de eficiencia llamas al servidor 2 veces cuando puedes hacerlo solo 1 y si luego no entiendes que fetch() al ser asíncrono no está disponible de inmediato.

"eso pasa cuando haces copy and paste y ni siquiera entiendes lo que haces" 🤣, de nuevo son palabras de mi jefe pero tiene razón porque init_choices.js y datos_choices.js están sobrando en este caso como luego te diste cuenta pero además tienen datos que ni siquiera estás usando, al menos en esta parte.

Esto debería servir a todos los programadores, no está mal hacer copy and paste ni siquiera usar la AI. En mi caso, le pasé la imagen que la usuaria compartió y le dije que en base a eso me devuelva el json, me devolvió un json al que solo corregí en 2 partes y le dije con base a este json genérame un php que actúe como un pseudo-api y me devolvió esto:

Insertar CODE, HTML o PHP:
<?php
// pseudo-api.php

$data = [
    "success" => true,
    "modelo" => [
        "id" => 51,
        "titulo" => "XV Modelo 2",
        "precio" => 45.00,
        "tipo" => "babyshower",
        "descripcion" => "",
        "publico" => 1,
        "imagen" => "https://upload.wikimedia.org/wikipedia/commons/a/a0/Suushi_Yurei.jpg",
        "colores" => ["rojo", "verde", "rosa"],
        "tematicas" => ["discoteca"],
        "galeria" => []
    ]
];

// Set the content type header to application/json
header('Content-Type: application/json');

// Output the JSON representation of the array
echo json_encode($data);

que sirve para rápidamente emular el servicio al que el fetch() llama:
https://wpe.oscaralderete.com/tests/forobeta895647/pseudo-api.php

sugerir a los programadores que revisen el código, volviendo a la idea anterior, no está mal hacer un copy and paste, pero hay que darse un tiempo para ver qué hace ese código y tratar de entenderlo. Eso es lo que no hace la IA, y si quieres sobrevivir como programador es lo que hay que hacer.
Yo no soy programadora, apenas estoy aprendiendo y si utilizo IA a veces se me hace más fácil aprender así a la inversa y tienes razón en muchas cosas, hay muchas cosas que no había notado en tu código, graciass, otra cosa init_choices.js y datos_choices.js los utilizo en otros aspectos, estoy tratando de hacer un sistema de prácticas como de compra y ventas de modelos de tarjetas, en realidad quería contratar alguien que lo hiciera, pero me puse a investigar y me termino gustando esto y bueno allí voy aprendiendo poco a poco a los coñazos como quien dice, pero lo agarre más como un proyecto para yo aprender con base a mis necesidades 🤣
 
Atrás
Arriba