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

Tomcat Cluster en Debian 7 (Wheezy)

Pues nos hemos animado a crear un cluster de tomcat. La verdad es muy sencillo hacerlo, simplemente habilitas unas opciones que ya vienen en tomcat y configuras mod_jk en apache para que administre el cluster y haga el balanceo de cargas. Muy, muy fácil, el detalle está en que no tienes alta disponibilidad, razón por la que puse el cluster en primer lugar. ¿Y entonces? Pues me puse a investigar, ya probé LiveRebel, y funciona de maravilla, pero igual te cobran... Así que busqué un poco más y di con mod_cluster de RedHat. Esta herramienta te permite lo mismo que mod_jk, pero le agrega alta disponibilidad, ¿a qué me refiero con alta disponibilidad? Al hecho de que cuando hay que hacer un redeploy de la aplicación si estas con mod_jk, apache no va a darse cuenta y te va a seguir enviando al tomcat que está haciendo el redeploy, y el cliente recibe el error de que no hay nada ahí, lo que sí hace mod_jk es notar que una instancia de tomcat ha sido dada de baja, entonces para lograr alta d...

Opensolaris vs Ubuntu vs Windows 7

Pues como ya les había mencionado, estuve probando OpenSolaris 2008/11... No puedo decir que ha sido una mala experiencia, simplemente no puedo producir tanto como produzco en windows como ubuntu. Ahora bien, es una plataforma sólida con todo lo que tienen los servidores que están en producción en muchas empresas, y con una interfaz gráfica bastante útil y fácil de usar si has usado Gnome antes. La cuestión está que todavía no es tan rápido como windows y menos como ubuntu. Le falta todavía en el área de multimedia y en la usabilidad de ciertas cosas, por ejemplo el trackpad, no toma los puntos donde puedes hacer scroll, no puedes utilizar la cámara, no tiene suspender ni hibernación. Además le toma un buen iniciar, no tanto como el 2008/5, pero igual, le toma mucho... Dadas esas circunstancias terminé en Windows 7... pero igual, carece de un ambiente al que ya me acostumbré bastante, las "ventanas" donde puedes agrupar el trabajo... Mejoró en su barra de tareas, donde se ase...

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...