Es común encontrar combos que sólo deben mostrar algunas opciones dependiendo de la selección hecha en otro combo, esto es, una selección dependiente.

En el Showcase de SmartGwt viene un ejemplo de cómo hacer esto. El problema con el ejemplo es que no nos dejará filtrar (en realidad autocompletar) los valores que contiene el combo. Esto se debe a que, en el código del ejemplo, sobreescribimos el método getPickListFilterCriteria que es utilizado cuando escribimos algún valor en el combo.

Por ejemplo, si tenemos que mostrar las Colonias que pertenecen a un Municipio -y además permitir que el usuario filtre/busque al escribir el nombre de la colonia- lo haríamos de la siguiente manera.

        SelectItem itmMunicipio = new SelectItem("municipio", "Municipio");
        itmMunicipio.addChangedHandler(new ChangedHandler() {
            @Override
            public void onChanged(ChangedEvent event) {
                ComboBoxItem item = (ComboBoxItem) frmPartes.getItem("colonia");
                item.setPickListCriteria(new Criteria("municipio", form.getValueAsString("municipio")));
                item.fetchData();
            }
        });
        itmMunicipio.setOptionDataSource(MunicipiosDS.singleton());
        itmMunicipio.setValueField("id");
        itmMunicipio.setDisplayField("nombre");
        itmMunicipio.setDefaultValue("014"); // Querétaro
        ComboBoxItem itmColonia = new ComboBoxItem("colonia", "Colonia");
        itmColonia.setOptionDataSource(ColoniasDS.singleton());
        itmColonia.setValueField("id");
        itmColonia.setDisplayField("nombre");
        itmColonia.setAddUnknownValues(false);
        itmColonia.setTextMatchStyle(TextMatchStyle.SUBSTRING);
        itmColonia.setPickListCriteria(new Criteria("municipio", "014")); // esto es para el valor inicial
        itmColonia.setDefaultToFirstOption(true);
        itmColonia.setWidth(200);
        itmColonia.setPickListWidth(300);

Fuentes:
http://www.smartclient.com/smartgwt/showcase/#dep_selectects_db_combobox_category
http://www.smartclient.com/smartgwt/showcase/#combobox_multifield_search
http://www.smartclient.com/smartgwt/javadoc/com/smartgwt/client/docs/ComboBoxFiltering.html
http://www.smartclient.com/smartgwt/javadoc/com/smartgwt/client/widgets/form/fields/ComboBoxItem.html#setTextMatchStyle(com.smartgwt.client.types.TextMatchStyle)

Anuncios

 

Normalmente cuando quieres utilizar el texto que se muestra al usuario para un parámetro, en vez del valor, utilizas la propiedad params[“parameterName”].displayText en un “dynamic text” en tu reporte. Si intentas hacer esto con un parámetro que permite la selección de múltiples valores, sólo obtendrás un valor nulo o en blanco. La opción es que utilices un script en el método onFetch del DataSet para reemplazar los valores del parámetro con los valores del campo que utilizas para mostrarlo al usuario.

Necesitas declarar una variable en el método “initialize” del reporte que contendrá las claves de los valores seleccionados, separados por una coma.

parameterSelectedValues=params["parameterName"].value.join(",");

 

después reemplazamos las claves en el método “onFetch” del DataSet

if(parameterSelectedValues.indexOf(row["id"].toString()) != null){
    parameterSelectedValues=parameterSelectedValues.replace(row["id"].toString(),row["name"].toString());
} 

 

y finalmente colocar un DynamicText en tu reporte con el valor

parameterSelectedValues;

 

El ejemplo completo lo encuentras aquí.

 

En smartgwt utilizo RPC para la comunicación etre el cliente y el servidor. El paso de errores(Excepciones) del servidor hacia el cliente no se da por sí solo. Con ello me refiero a que si tenemos un método que arroje una excepción de tipo java.lang.Exception, lo cual no es lo recomendado, no podrá ser vista (leída) en el cliente -a pesar de que implementa la interfaz Serializable-
Por ejemplo, si tenemos el siguiente código en el servidor (que comunmente usamos para conectar a la BD):

public String helloException() throws Exception{
    Connection cn=DriverManager.getConnection("non-existent-driver");
    ...
}

y lo invocamos en el cliente

service.helloException (new AsyncCallback<String> () {
          public void onFailure (Throwable caught) {
              ...
              SC.warn("Error: "+ caught.getMessage(), null);
          }
          public void onSuccess (String result) {
              ...
          }
});

si sucede algún error, caught.getMessage() nos mostrara el mensaje “The call failed on the server; see server log for details”. Lo cual no nos dice absolutamente nada, más que algo falló en el servidor. Ahora revisemos el log para ver que sucedió.

[WARN] Exception while dispatching incoming RPC call
com.google.gwt.user.client.rpc.SerializationException: Type ‘java.sql.SQLException’ was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.

Bueno, al menos ahora sabemos que ocurrió un SQLException, pero no podemos ver el detalle del mensaje.
Para ello necesitamos crear nuestra propia Excepcion serializable de la siguiente forma

public class UnknownException extends Exception implements IsSerializable {
    public UnknownException(){
    }
    public UnknownException(String message) {
        super(message);
    }
}

y modificamos el codigo en el servidor para que nos quede de la siguiente manera

public String helloException() throws UnknownException{
    try{
        Connection cn=DriverManager.getConnection("non-existent-driver");
        ...
    }catch(Exception exc){
        throw new UnknownException(exc.getMessage());
    }
}

de esta manera caught.getMessage() nos regresará el mensaje “No suitable driver found for non-existent-driver”, lo cual nos da una pista más clara de qué sucedió.
No necesariamente queremos mostrar estos mensajes al usuario, pero a la hora de debuguear nuestro código también tendremos acceso al mensaje de la excepción, cosa que antes no sucedía.

Finalmente, aunque nos requiera más trabajo, deberíamos crear nuestras propias excepciones.