Ir al contenido principal

Encadenamiento de Selects en Grails

Pues la integración de acegi security a la aplicación de Grails, la verdad fue una maravilla hacerlo, no cuesta absolútamente nada de trabajo... ahora configurar el encadenamiento de unos selects en Grails es otra historia, pero bueno, nada que no pueda ser resuelto...

Primero necesitas agregar en el head de tu gsp, luego agregar los selects a encadenar en mi caso estoy encadenando 3 (bueno 2, el 3ro depende del 2do y el 2do del primero, algo bastante obvio, pero bueno uno nunca sabe, jeje)

<tr class="prop">
<td valign="top" class="name"><label for="organization.name">Organización:</label></td>
<td valign="top" class="value">
<g:select
optionKey="id"
optionValue="name"
name="organizationId"
id="organizationId"
from="${Organization.list()}"
onchange="${remoteFunction(
controller:'organization',
action:'ajaxGetCompanies',
params:'\'id=\' + escape(this.value)',
onComplete:'updateCompany(e)'
)}"
value="${person?.warehouse?.company?.organization?.id}"
>
</g:select>
<g:select
optionKey="id"
optionValue="name"
name="companyId"
id="companyId"
onchange="${remoteFunction(
controller:'company',
action:'ajaxGetWarehouses',
params:'\'id=\' + escape(this.value)',
onComplete:'updateWarehouse(e)'
)}"
value="${person?.warehouse?.company?.id}"
></g:select>
<g:select id="warehouseId" name="warehouse.id" value="${person?.warehouse?.id}"></g:select>
</td>
</tr>


Y luego un script al final para poder hacer la carga de los elementos que resulta de las búsquedas

<script>
function updateCompany(e) { // The response comes back as a bunch-o-JSON
var companies = eval("(" + e.responseText + ")") // evaluate JSON

if (companies) {
var rselect = document.getElementById('companyId')

// Clear all previous options
var l = rselect.length

while (l > 0) {
l--
rselect.remove(l)
}

// Rebuild the select
for (var i=0; i < companies.length; i++) {
var company = companies[i]
var opt = document.createElement('option');
opt.text = company.name
opt.value = company.id
try {
rselect.add(opt, null) // standards compliant; doesn't work in IE
} catch(ex) {
rselect.add(opt) // IE only
}
}
}

var cselect = document.getElementById('companyId')
var copt = cselect.options[cselect.selectedIndex]
${remoteFunction(controller:'company',action:'ajaxGetWarehouses',params:'\'id=\' + copt.value',onComplete:'updateWarehouse(e)')}
}

function updateWarehouse(e) { // The response comes back as a bunch-o-JSON
var warehouses = eval("(" + e.responseText + ")") // evaluate JSON

if (warehouses) {

var rselect = document.getElementById('warehouseId')

// Clear all previous options
var l = rselect.length

while (l > 0) {
l--
rselect.remove(l)
}

// Rebuild the select
for (var i=0; i < warehouses.length; i++) {
var warehouse = warehouses[i]
var opt = document.createElement('option');
opt.text = warehouse.name
opt.value = warehouse.id
try {
rselect.add(opt, null) // standards compliant; doesn't work in IE
} catch(ex) {
rselect.add(opt) // IE only
}
}
}
}

// This is called when the page loads to initialize company
var zselect = document.getElementById('organizationId')
var zopt = zselect.options[zselect.selectedIndex]
${remoteFunction(controller:'organization', action:'ajaxGetCompanies', params:'\'id=\' + zopt.value', onComplete:'updateCompany(e)')}

</script>


La tienes que poner al final para que carge el remoteFunction del final en el que busca las empresas y este a su vez manda llamar la búsqueda de almacenes... si solo necesitas dos quitas la segunda funcion (updateWarehouse) y el llamado a la misma desde la primera funcion (y el select) y lo puedes dejar como el último select, no es necesario que tenga tanta información. Regresando al ejemplo, aun nos falta hacer la búsqueda, tienes que ir al controlador de organizacion y crear sus cierres (o metodos para que atienda las peticiones ajax), y lo mismo con el controlador de empresa.

def ajaxGetCompanies = {
def org = Organization.get(params.id)
render org?.companies as JSON
}

Solo que para que esto funciona necesitas realizar un import al inicio de la clase

import grails.converters.*

class OrganizationController {

No necesitas lo de class Organiz... solo es un ejemplo de donde va... Y listo... debe de funcionar...

Nota: Si quieres copiar el código, lo vas a necesitar convertir, para esto lo copias... lo llevas a http://www.centricle.com/tools/html-entities/ y lo decodificas

Comentarios

Entradas más populares de este blog

OpenSolaris, Clúster de Glassfish y Sun Java Web Server Loadbalancer

Pues estuve necesitando un clúster de Glassfish V2U2 para lo cual encontré rápidamente mucha información en Internet, el que más me gustó fue un blog de Ryan Wilson , pero también necesitaba poner el balanceador de cargas ( loadbalancer ) asi que para eso utilicé la documentación de Glassfish . Aquí el resúmen: Instalar OpenSolaris 200805 y despues realizar lo que les sugieren en los Release Notes , en donde te dicen que actualices su herramienta para instalar paquetes. NOTA: Antes de hacer esto, asegurarse de tener todas las máquinas que van a participar dentro del cluster mapeadas con un DNS, de no ser esto posible sus archivos de hosts deben de tener la información suya y de cada una de las máquinas que van a participar. (Gracias a equipo Telcel) Despues de esto seguir las instrucciones de Ryan . Con esto vas a tener el cluster de glassfish funcionando. Solo que en la configuración del segundo servidor puedes hacer lo siguiente para evitar los pasos 4 al 6 (lo siguiente todo en una...

Reporte Excel con JasperReports

Pues no funcionó el reporte con Jasper, pude hacer que evitara paginar con estas opciones ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); JRXlsExporter exporterXLS = new JRXlsExporter(); exporterXLS.setParameter(JRXlsExporterParameter.JASPER_PRINT, jasperPrint); // exporterXLS.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE); exporterXLS.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE); exporterXLS.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE); exporterXLS.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_COLUMNS, Boolean.TRUE); exporterXLS.setParameter(JRXlsExporterParameter.IS_COLLAPSE_ROW_SPAN, Boolean.TRUE); exporterXLS.setParameter(JRXlsExporterParameter.IGNORE_PAGE_MARGINS, Boolean.TRUE); exporterXLS.s...

JQuery Image Upload en Spring MVC

Utilizar el jQuery File Upload de blueimp  en Grails es una delicia. Pero necesito hacer una aplicación grande y no sé lo suficiente como para mantenerla óptima dentro de Grails, así que decidí portarla a Spring MVC, pero no encontré una implementación de esta herramienta en Java que hiciera lo que hace el plugin, que simplemente implementa lo que la herramienta ya hace en otras plataformas. Así que me puse a implementarla y ya quedó. La pueden encontrar en github ... Sólo necesitan clonarla, y ejecutarla con maven: mvn tomcat7:run