martedì 10 luglio 2012

Wicket - Property Column con variazione valore

Diciamo che avete un Property Column legato ad una proprietà di un POJO che viene riempito da DB. Nella  tabella però volete manipolare la resa visiva modificando quindi il valore dentro la proprietà.

Per esempio state stampando un elenco di messaggi e volete stampare solo i primi 100 caratteri del corpo che altrimenti sarebbe troppo lungo.

Per farlo occorre sovrascrivere il metodo PopulateItem della property column come segue:

PropertyColumn colonnaCorpo = new PropertyColumn<Messaggio>(new Model<String>("Corpo"), "corpo"){
    @Override
    public void populateItem(Item<ICellPopulator<Messaggio>> item,
            String componentId, IModel<Messaggio> rowModel) {
        String corpoModel = rowModel.getObject().getCorpo();
        item.add(new Label(componentId,corpoModel.substring(0, Math.min(50,corpoModel.length()))));
    }                
};

Il nostro POJO di partenza si chiama Messaggio e ha dentro una proprietà stringa chiamata corpo.
Sovrascrivendo la populateItem, andiamo a sovrascrivere il modo in cui il componente viene stampato.

item: rappresenta l'oggetto colonna;
componentId: rappresenta l'id del singolo componente (in questo caso dinamico dato che è una cella di una tabella);
rowModel: rappresenta il modello del POJO di cui questo componente sta per stampare una proprietà;

Nell'esempio recuperiamo il testo del corpo dal modello richiamando prima l'oggetto Messaggio dal Modello e quindi richiamando la getCorpo().

A questo punto aggiungo alla item, una Label con lo stesso ID e come stringa la sottostringa del corpo facendo in modo che Java non si incavoli se chiedo più caratteri di quanto la stringa sia effettivamente lunga (leggasi, aggiungo il MIN).

Questo barbatrucco è molto comodo quando dovete ridefinire il modo in cui il componente stampa il valore. Le potenzialità sono multiple. Potete per esempio inserire un TextField dentro la cella, o un Panel con dentro altra roba ecc...

mercoledì 4 luglio 2012

Wicket - Input Text con Autocomplete

Prima o poi ti chiedono anche di fare un input text con i suggerimenti alla Google. Wicket ci permette di farlo in pochi passi.

final AutoCompleteTextField destinatario = new AutoCompleteTextField("destinatario", new PropertyModel<String>(email,"userNameDestinatario"))
 {
      protected Iterator getChoices(String input)
      {
          if (Strings.isEmpty(input))
          {
              return Collections.EMPTY_LIST.iterator();
          }
          
          List<String> elencoFittizio = new ArrayList<String>();
          elencoFittizio.add("Pippo");
          elencoFittizio.add("Pluto");
          elencoFittizio.add("Paperino");
          elencoFittizio.add("Minnie");
          elencoFittizio.add("Paperone");
          elencoFittizio.add("Nonna Papera");
          
          List<String> elencoPulito = new ArrayList<String>();
          
          for (String nome : elencoFittizio){
              nome = nome.toLowerCase();
              String probe = input.toLowerCase();
              if (nome.contains(probe)){
                  elencoPulito.add(nome);
              }
          }
          return  elencoPulito.iterator();
       }
 };

Per farlo usiamo il componente AutoCompleteTextField che aggancieremo ad un tag HTML classico di tipo INPUT TEXT.

Come vedete il costruttore è piuttosto classico. Si definisce il wicket:id (destinatario) e nel mio caso il PropertyModel così da riempire direttamente la proprietà userNameDestinatario dentro l'oggetto email.

A questo punto occorre implementare il metodo che gestisce cosa farci vedere. Come vedete ci viene dato in ingresso una stringa input che rappresenta ciò che l'utente sta inserendo.

Il metodo richiede in uscita un Iterator ovvero l'oggetto che permette a Java di scorrere le Collections ovvero qualsiasi oggetti che rappresenta un elenco di qualcosa.

Se la stringa è vuota, creo una Collections vuota e ritorno l'iterator.

Negli altri casi, devo ritornare l'iterator della lista pulita ovvero della lista risultante dal controllo con l'input inserito.

Nel codice sopra ho mokkato il codice inserendo una lista finta. E' ipotizzabile che qui agganciate un metodo che vada su DB a fare la query e ritorni una lista di cui poi ritornerete l'iterator.

Per farvi capire bene però, nell'esempio ho una lista completa che poi vado a sfoltire sulla base della stringa in ingresso. Nel caso sopra creo una nuova lista con gli elementi della prima che contengono la stringa in input.

Se invece avessi voluto l'aggancio ad un eventuale DB tramite un manager, avrei avuto:


final AutoCompleteTextField destinatario = new AutoCompleteTextField("destinatario", new PropertyModel<String>(email,"userNameDestinatario"))
 {
      protected Iterator getChoices(String input)
      {
          if (Strings.isEmpty(input))
          {
              return Collections.EMPTY_LIST.iterator();
          }
          
          List<String> utentiFiltrati = getManager().cercaUtentiLike(input);
          return  utentiFiltrati.iterator();
       }
 };

Come vedete non mi interessa cosa faccia la cercaUtentiLike, mi interessa solo che mi ritorni una Lista di Stringhe, probabilmente filtrate in fase di interrogazione al DB.

martedì 3 luglio 2012

Wicket - Triggerare il feedback Panel di una Pagina indipendentemente dalla profondità

Un titolo lungo per qualcosa di assolutamente semplice ma potente.

Avevo una situazione di questo tipo:

Pagina con dentro un Panel con dentro una Modale con dentro un Panel. Premendo un tasto di SAVE, dovevo chiudere la modale e mostrare nel feedback panel della pagina, un messaggio di avvertimento all'utente che l'operazione era andata a buon fine.

Per farlo serve un metodo getFeedBackPanel() da dare alla Page e che ritorna l'oggetto.
A questo punto usiamo questo codice:

FeedbackPanel feedbackPadre = ((ProtectedPage) findPage()).getFeedBackPanel();
feedbackPadre.info("Scrivo qualcosa");
target.addComponent(feedbackPadre);

Come vediamo, uso findPage() per trovare un oggetto di tipo Page  (o suo figli) a ritroso nella gerarchia indipendentemente dalla profondità. La devo ovviamente castare alla pagina effettiva che mi aspetto (nel mio caso ProtectedPage) e quindi richiamare il nostro FeedbackPanel.

Poi in maniera classica, ci scrivo qualcosa dentro e quindi lo aggancio all'evento Ajax.