Soporte

PrestaShop: el campo Estado siempre muestra A Coruña al crear o editar direcciones (solución)

En PrestaShop 9.1.3 el desplegable Estado puede quedarse en A Coruña al editar direcciones, sin error visible. Caso real, causa técnica y solución en BO y FO.

En una tienda PrestaShop 9.1.3 en España, el campo Estado (provincia) puede parecer “encantado”: eliges Madrid, Burgos o Huesca, guardas… y al volver a editar aparece A Coruña. Sin mensaje de error. Sin aviso. Solo un valor incorrecto en pantalla.

Este artículo documenta un caso real en una tienda de bricolaje (zonabrico.com), con tema PRS02045 v3.0.3 (CoderPlace), y la solución aplicada en back office y front office. Si te suena el síntoma, aquí tienes la causa técnica y los pasos para corregirlo.

Aclaración importante: en PrestaShop (y en el checkout español), Ciudad y Estado no son lo mismo. Ciudad es la localidad (texto libre). Estado es la provincia del desplegable. El bug afecta al desplegable de provincia, no al nombre de la ciudad.

Síntomas: checklist rápido

Si cumples varios de estos puntos, es muy probable que estés ante el mismo problema:

  • Al crear o editar una dirección, eliges una provincia y, al guardar o reabrir el formulario, aparece A Coruña.
  • No hay mensaje de error ni validación fallida visible.
  • En el back office, dentro del pedido, la dirección puede verse bien; al editar facturación o envío, el desplegable vuelve a A Coruña.
  • En la tienda, en Mi cuenta → Direcciones, ocurre lo mismo aunque en base de datos la provincia sea otra (por ejemplo, Burgos).
  • La tienda está en España y las provincias (estados) están activas/obligatorias.

[CAPTURA: back office — formulario de dirección mostrando A Coruña tras haber guardado Madrid]

[CAPTURA: front office — Mi cuenta → Direcciones, misma provincia incorrecta al editar]

Por qué siempre sale A Coruña

No es que PrestaShop “prefiera” Galicia. En España, la primera provincia del listado ordenado alfabéticamente suele ser A Coruña. Cuando el JavaScript vacía el <select>, recarga opciones por AJAX y no restaura el valor guardado, el navegador se queda con la primera opción disponible. De ahí el patrón tan característico.

En otras palabras: el valor correcto puede existir en base de datos, pero la interfaz lo pierde al redibujar el formulario.

[CAPTURA: desplegable Estado con A Coruña como primera opción del listado]

Causa técnica: cuatro fallos encadenados

El problema no venía de un único archivo. Eran cuatro fallos que se reforzaban entre sí: uno en el back office y tres en el front (controlador, JS del núcleo y plantilla del tema).

1. Back office — CountryStateSelectionToggler

Archivos implicados:

  • admin…/themes/new-theme/js/components/country-state-selection-toggler.ts
  • admin…/themes/new-theme/public/main.bundle.js (bundle compilado)

Al cargar el formulario de dirección, onChange() vaciaba el select de provincias, pedía de nuevo el listado por AJAX y no volvía a seleccionar el id_state original. Resultado: primera opción alfabética → A Coruña.

Idea del fix: guardar selectedStateId antes del AJAX; en la inicialización, llamar a onChange() solo si el select está vacío; si ya tiene opciones, limitar a toggle().

2. Front office — AddressController.php

El método displayAjaxAddressForm() reconstruye el formulario de dirección por AJAX cuando cambia el país. En este caso solo enviaba id_country y no reenviaba id_state. Sin ese parámetro, el HTML regenerado no puede marcar la provincia correcta.

Idea del fix: si la petición trae id_state, incluirlo en los parámetros AJAX del formulario.

3. Front office — JavaScript al cambiar país

El núcleo (themes/core.js) preservaba valores de input al refrescar el formulario, pero no los de select. Al cambiar país (o al recargar el bloque de dirección), el estado se perdía.

Importante: no conviene parchear themes/core.js a mano: se pierde en cada actualización. Mejor un JS del tema, registrado en theme.yml.

En este proyecto se añadió:

  • themes/PRS02045/assets/js/address-form-fix.js
  • Registro en themes/PRS02045/config/theme.yml (priority 500, bottom)

Ese script preserva input, select y textarea, y envía id_state en el POST del refresco.

4. Front office — plantilla Smarty del tema

Archivo: themes/PRS02045/templates/_partials/form-fields.tpl

La opción placeholder (“Por favor elige”) llevaba selected siempre, aunque el campo ya tuviera valor. En la práctica, el navegador acababa mostrando la primera provincia real del listado → otra vez A Coruña.

Idea del fix: marcar selected en el placeholder solo si $field.value está vacío; añadir un data-selected-value; y que el JS restaure el valor al cargar.

[CAPTURA: fragmento de form-fields.tpl con el placeholder selected incorrecto]

Archivos modificados

  • admin…/themes/new-theme/js/components/country-state-selection-toggler.ts — no resetear la provincia al cargar el formulario.
  • admin…/themes/new-theme/public/main.bundle.js — mismo parche en el bundle servido al navegador.
  • controllers/front/AddressController.php — pasar id_state en la respuesta/params AJAX del formulario de dirección.
  • themes/PRS02045/templates/_partials/form-fields.tpl — placeholder condicional + data-selected-value.
  • themes/PRS02045/assets/js/address-form-fix.js — preservar selects al cambiar país.
  • themes/PRS02045/config/theme.yml — registrar el JS custom.

Ruta de admin: en cada tienda el directorio puede llamarse admin416 u otro nombre aleatorio. Sustituye por el tuyo.

Solución paso a paso

Haz backup de archivos (y de base de datos si vas a corregir direcciones antiguas). Trabaja primero en staging si puedes.

Paso 1 — Parchear el toggler del back office

En el componente TypeScript (o directamente en main.bundle.js si no recompilas assets), evita forzar onChange() cuando el select ya tiene opciones:

if (this.$countryStateSelector.children('option').length === 0) {
  this.onChange();
} else {
  this.toggle();
}

Además, guarda el selectedStateId antes de vaciar/recargar por AJAX y restáuralo cuando lleguen las opciones.

Si editas el .ts, regenera el bundle del new-theme o aplica el mismo cambio en main.bundle.js (es lo que carga el navegador).

[CAPTURA: diff del country-state-selection-toggler mostrando la condición length === 0]

Paso 2 — Actualizar AddressController.php

En displayAjaxAddressForm() (o el punto donde se montan los $ajaxParams), añade:

if (Tools::getIsset('id_state')) {
    $ajaxParams['id_state'] = Tools::getValue('id_state');
}

Así el HTML regenerado puede conocer la provincia seleccionada.

Paso 3 — Corregir form-fields.tpl del tema

En el bloque del select de estado/provincia, el placeholder debe seleccionarse solo si no hay valor:

<option value="" disabled {if empty($field.value)}selected{/if}>
  {l s='Please choose' d='Shop.Forms.Labels'}
</option>

Añade también un atributo con el valor esperado (por ejemplo data-selected-value="{$field.value}" en el <select>) para que el JS pueda restaurarlo tras el pintado.

Paso 4 — Añadir address-form-fix.js y registrarlo

Crea themes/PRS02045/assets/js/address-form-fix.js con lógica que:

  1. Antes de refrescar el formulario por AJAX, lea los valores de inputs, selects y textareas.
  2. Envíe id_state en la petición cuando exista.
  3. Tras insertar el nuevo HTML, vuelva a aplicar esos valores (incluido el select de provincia).

Regístralo en themes/PRS02045/config/theme.yml con prioridad alta en el footer (por ejemplo priority 500, bottom), para que se ejecute después de los scripts base sin tocar themes/core.js.

[CAPTURA: theme.yml con el asset address-form-fix.js registrado]

Paso 5 — Subir, limpiar caché y probar

  1. Sube los archivos modificados al servidor.
  2. En PrestaShop: Parámetros avanzados → Rendimiento → Limpiar caché.
  3. Back office: recarga forzada (Ctrl+F5).
  4. Front office: ventana de incógnito (evita JS/CSS cacheados).
  5. Corrige manualmente direcciones antiguas que se hubieran guardado mal si el síntoma llegó a persistir en base de datos en algún caso.

Cómo probar que quedó resuelto

  1. Back office: edita una dirección de cliente o de un pedido. Elige Madrid (u otra provincia distinta de A Coruña), guarda, vuelve a abrir. Debe mantenerse.
  2. Pedido: abre un pedido, edita dirección de facturación/envío, cambia provincia, guarda y reabre.
  3. Front office: Mi cuenta → Direcciones → editar. Cambia provincia, guarda, edita de nuevo.
  4. Cambio de país (si aplica): si el formulario permite cambiar país y volver a España, comprueba que la provincia no se pierde al recargar el bloque.

[CAPTURA: misma dirección en BO tras guardar — provincia correcta visible]

[CAPTURA: front office tras editar — provincia correcta en el listado y al reabrir]

Notas sobre actualizaciones de PrestaShop

  • Los cambios en AddressController.php y en el new-theme del admin pueden pisarse al actualizar el core. Documenta el parche y vuelve a aplicarlo o muévelo a un override/módulo propio si quieres más durabilidad.
  • Los cambios del tema (form-fields.tpl, JS y theme.yml) suelen sobrevivir mejor a un upgrade del core, pero no a una actualización del tema PRS02045: guarda copia de tus personalizaciones.
  • No edites themes/core.js en producción como “atajo”: es de los primeros archivos que se sobrescriben.
  • Tras cada upgrade, repite el checklist de pruebas de direcciones en BO y FO antes de dar el trabajo por cerrado.

Conclusión

El “Estado siempre en A Coruña” no era un misterio de datos: era una cadena de fallos de UI/AJAX donde el valor se perdía al redibujar el formulario y el navegador caía en la primera provincia del listado. Con el parche del toggler en back office, el id_state en el AJAX del front, el JS del tema que preserva selects y el Smarty del placeholder, el comportamiento vuelve a ser el esperado.

Si tu tienda PrestaShop 9.1.3 en España muestra este síntoma en checkout o en direcciones de cliente, puedo revisar el caso y aplicar la corrección con cuidado en staging y producción.

Contactar con PrestaShop Web Design · Soporte y desarrollo PrestaShop en Madrid y remoto en toda España. También puedes escribir por WhatsApp desde la web.

Siguiente paso

¿Quieres mejorar tu PrestaShop?

Velocidad, errores, SEO o mantenimiento. Te ayudo con trato directo. Madrid y remoto en toda España.

WhatsApp Contacto