2013-06-17 10 views

risposta

16

Se ho capito la domanda corretta, si desidera avere un campo che ignora tutti gli input che non sono un numero e non solo contrassegnare il campo come non valido. L'architettura di Vaadins è progettata in modo che ogni campo nel browser abbia la sua rappresentazione sul server. A mio parere, il modo più pulito per ottenere ciò sarebbe avere un campo browser, che permetta l'inserimento di lettere e altri caratteri errati. Non sono riuscito a trovare un campo simile in Vaadin 7. Sembra che ci sia un add-on per vaadin 6 chiamato Number Field per quello, ma non l'ho provato.
si dispone di più opzioni:

  1. Port questo add-on per Vaadin 7 o chiedere all'autore di farlo

  2. Scrivi la tua campo. Forse si estende VTextField e TextFieldConnector

  3. Fare tutto sul lato server e di accettare i ritardi e il traffico (IMHO brutto)

Dal momento penso opzione 3 è non la strada da percorrere, probabilmente non dovrebbe mostrare questo codice, ma è il modo più veloce per implementarlo.

public class IntegerField extends TextField implements TextChangeListener { 
String lastValue; 

public IntegerField() { 
    setImmediate(true); 
    setTextChangeEventMode(TextChangeEventMode.EAGER); 
    addTextChangeListener(this); 
} 

@Override 
public void textChange(TextChangeEvent event) { 
    String text = event.getText(); 
    try { 
     new Integer(text); 
     lastValue = text; 
    } catch (NumberFormatException e) { 
     setValue(lastValue); 
    } 
} 
} 
+0

grazie amico. Funziona bene. Ho aggiunto alcuni assegni nulli e controlli vuoti e li ho gestiti. –

+0

Lavorando, ma quando si digita velocemente un sacco di caratteri, è ancora possibile immettere contenuto indesiderato – Eyal

+1

In genere si considera una cattiva pratica l'utilizzo di eccezioni per il controllo del flusso. Vedi http://c2.com/cgi/wiki?DontUseExceptionsForFlowControl, http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so -perché o http://stackoverflow.com/questions/729379/why-not-use-exceptions-as-regular-flow-of-control. –

2

A TextField è un componente che ha sempre un valore di tipo String. Quando si associa una proprietà di un altro tipo a un campo di testo, il valore viene automaticamente convertito se è supportata la conversione tra i due tipi.

public class MyBean { 
    private int value; 

    public int getValue() { 
     return value; 
    } 

    public void setValue(int integer) { 
     value = integer; 
    } 
} 

la proprietà denominata "valore" da un BeanItem costruito da MyBean sarà di tipo Integer. Associando la proprietà a TextField si verificherà automaticamente un errore di convalida per i testi che non possono essere convertiti in un numero intero.

final MyBean myBean = new MyBean(); 

BeanItem<MyBean> beanItem = new BeanItem<MyBean>(myBean); 

final Property<Integer> integerProperty = (Property<Integer>) beanItem 
     .getItemProperty("value"); 
final TextField textField = new TextField("Text field", integerProperty); 

Button submitButton = new Button("Submit value", new ClickListener() { 
    public void buttonClick(ClickEvent event) { 
     String uiValue = textField.getValue(); 
     Integer propertyValue = integerProperty.getValue(); 
     int dataModelValue = myBean.getValue(); 

     Notification.show("UI value (String): " + uiValue 
       + "\nProperty value (Integer): " + propertyValue 
       + "\nData model value (int): " + dataModelValue); 
    } 
}); 

addComponent(new Label("Text field type: " + textField.getType())); 
addComponent(new Label("Text field type: " + integerProperty.getType())); 
addComponent(textField); 
addComponent(submitButton); 

Con questo esempio, inserendo un numero e premendo il pulsante provoca il valore della TextField essere un String, il valore della proprietà sarà un Integer rappresenta lo stesso valore e il valore nel bean sarà lo stesso Int. Se ad es. una lettera viene inserita nel campo e il pulsante viene premuto, la convalida fallirà. Questo fa sì che venga visualizzato un avviso per il campo. Il valore del campo è ancora aggiornato, ma il valore della proprietà e il valore del bean sono mantenuti ai valori precedenti.

+0

Desidero non aggiornare il valore del campo. –

12

Vaadin 7 permette di estendere thier costruito nel widget (se si desidera avere maggiori conoscenze su questo ho davvero consiglio questo post) ecco una soluzione che utilizza tale meccanismo.

E 'composto da due classi: connettore e l'estensione

  1. L'estensione

    package com.infosystem.widgets.vaadin; 
    import com.vaadin.server.AbstractClientConnector; 
    import com.vaadin.server.AbstractExtension; 
    import com.vaadin.ui.TextField; 
    
    public class NumberField extends AbstractExtension { 
    
         public static void extend(TextField field) { 
          new NumberField().extend((AbstractClientConnector) field); 
         } 
    } 
    
  2. connettore:

    package com.infosystem.widgets.vaadin.client.numberField; 
    import com.google.gwt.event.dom.client.KeyCodes; 
    import com.google.gwt.event.dom.client.KeyPressEvent; 
    import com.google.gwt.event.dom.client.KeyPressHandler; 
    import com.infosystem.widgets.vaadin.NumberField; 
    import com.vaadin.client.ComponentConnector; 
    import com.vaadin.client.ServerConnector; 
    import com.vaadin.client.extensions.AbstractExtensionConnector; 
    import com.vaadin.client.ui.VTextField; 
    import com.vaadin.shared.ui.Connect; 
    
    @Connect(NumberField.class) 
    public class NumberFieldConnector extends AbstractExtensionConnector { 
          private static final long serialVersionUID = -737765038361894693L; 
    
    private VTextField textField; 
    private KeyPressHandler keyPressHandler = new KeyPressHandler() { 
        @Override 
        public void onKeyPress(KeyPressEvent event) { 
         if (textField.isReadOnly() || !textField.isEnabled()) { 
          return; 
         } 
         int keyCode = event.getNativeEvent().getKeyCode(); 
         switch (keyCode) { 
         case KeyCodes.KEY_LEFT: 
         case KeyCodes.KEY_RIGHT: 
         case KeyCodes.KEY_BACKSPACE: 
         case KeyCodes.KEY_DELETE: 
         case KeyCodes.KEY_TAB: 
         case KeyCodes.KEY_UP: 
         case KeyCodes.KEY_DOWN: 
         case KeyCodes.KEY_SHIFT: 
          return; 
         } 
         if (!isValueValid(event)) { 
          textField.cancelKey(); 
         } 
        } 
    }; 
    
    @Override 
    protected void extend(ServerConnector target) { 
        textField = (VTextField) ((ComponentConnector) target).getWidget(); 
        textField.addKeyPressHandler(keyPressHandler); 
    } 
    
    private boolean isValueValid(KeyPressEvent event) { 
        String newText = getFieldValueAsItWouldBeAfterKeyPress(event.getCharCode()); 
        try { 
         parseValue(newText); 
         return true; 
        } catch (Exception e) { 
         return false; 
        } 
    } 
    
    protected long parseValue(String value) { 
        return Long.valueOf(value); 
    } 
    
    private String getFieldValueAsItWouldBeAfterKeyPress(char charCode) { 
        int index = textField.getCursorPos(); 
        String previousText = textField.getText(); 
        StringBuffer buffer = new StringBuffer(); 
        buffer.append(previousText.substring(0, index)); 
        buffer.append(charCode); 
        if (textField.getSelectionLength() > 0) { 
         buffer.append(previousText.substring(index + textField.getSelectionLength(), 
           previousText.length())); 
        } else { 
         buffer.append(previousText.substring(index, previousText.length())); 
        } 
        return buffer.toString(); 
    } 
    } 
    

Per utilizzare il codice di un bove è necessario aggiungerlo al set di widget corrente. In seguito l'uso di questo è la seguente:

TextField field = new TextField(); 
    NumberField.extend(field); 
+1

Per aggiungerlo al widget widgets, la classe Connector deve trovarsi in una cartella denominata "client" allo stesso livello del file widgetset personalizzato (MyWigetSet.gwt.xml, ad esempio). Per usare un widget widgets personalizzato, questo deve essere dichiarato come init-param nel servlet. – enkara

2

In Vaadin 7, è possibile utilizzare un TextField e impostare un validatore per consentire solo numeri:

TextField textField; 
textField.addValidator(new RegexpValidator("[-]?[0-9]*\\.?,?[0-9]+"), "This is not a number!"); 

Modifica l'espressione regolare in base alle proprie esigenze. Ricorda che ancora sta gestendo le stringhe e quindi è ancora necessario convertire il valore di ritorno del TextField:

Long.parseLong(textField.getValue()) 
2

Questo è un aggiornamento (2017 Vaadin 8) per @raffael risposta:

public class DoubleField extends TextField implements ValueChangeListener<String> { 

/** 
* 
*/ 
private static final long serialVersionUID = 1L; 
public String lastValue; 

public DoubleField() { 
    setValueChangeMode(ValueChangeMode.EAGER); 
    addValueChangeListener(this); 
    lastValue=""; 
} 

@Override 
public void valueChange(ValueChangeEvent<String> event) { 
    String text = (String) event.getValue(); 
    try { 
     new Double(text); 
     lastValue = text; 
    } catch (NumberFormatException e) { 
     setValue(lastValue); 
    } 

} 

Ecco!

0

NumberField è disponibile per Vaadin 7 e 8 ormai.