2013-06-17 20 views
10

Ich benutze ein Vaadin-Textfeld und ich möchte es auf nur darin enthaltene Nummern beschränken. Ich habe versucht, setValue() zu überschreiben und ohne Aufruf von Super zurückzukehren. setValue() wenn Text keine Nummer ist. Aber es scheint nicht zu funktionieren. Wie kann ich das korrigieren? Ich benutze Vaadin 7. Und ich denke, es unterstützt auch NumberField nicht.Wie erstelle ich ein Textfeld, das nur Zahlen in Vaadin unterstützt

Antwort

16

Wenn ich verstehe Sie Frage richtig, möchten Sie ein Feld, das alle Eingaben ignoriert, die keine Zahl sind und nicht nur das Feld als ungültig markieren. Die Vaadins-Architektur sieht vor, dass jedes Feld im Browser auf dem Server dargestellt wird. Meiner Meinung nach wäre der sauberste Weg, dies zu erreichen, ein Browserfeld zu haben, das die Eingabe von Buchstaben und anderen falschen Zeichen erlaubt. Ich konnte ein solches Feld in Vaadin 7 nicht finden. Es scheint ein Add-on für Vaadin 6 zu geben, genannt Number Field dafür, aber ich habe es nicht getestet.
Sie haben mehrere Möglichkeiten:

  1. Hafen dieses Add-on zu Vaadin 7 oder den Autor fragen, es zu tun

  2. Ihr eigenes Feld schreiben. Vielleicht VTextField und TextFieldConnector erstreckt

  3. alles auf der Server-Seite zu tun und die Verzögerungen und den Verkehr (IMHO hässlich)

akzeptieren Da ich 3 denken Option ist nicht der Weg zu gehen, ich wahrscheinlich sollte diesen Code nicht anzeigen, aber es ist der schnellste Weg, dies zu implementieren.

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

danke Kumpel. Es funktioniert gut. Ich fügte einen Null-Check und einen Leer-Check hinzu und behandelte sie. –

+0

Funktioniert, aber wenn Sie viele Zeichen schnell eingeben, können Sie immer noch unerwünschten Inhalt eingeben – Eyal

+1

Es wird allgemein als schlechte Praxis angesehen, Ausnahmen für den Kontrollfluss zu verwenden. Siehe http://c2.com/cgi/wiki?DontUseExceptionsForFlowControl, http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so -why oder http://stackoverflow.com/questions/729379/why-not-use-exceptions-als-regular-flow-of-control. –

2

Eine TextField ist eine Komponente, die immer einen Wert vom Typ String hat. Wenn eine Eigenschaft eines anderen Typs an ein Textfeld gebunden wird, wird der Wert automatisch konvertiert, wenn die Konvertierung zwischen den beiden Typen unterstützt wird.

public class MyBean { 
    private int value; 

    public int getValue() { 
     return value; 
    } 

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

Die Eigenschaft mit dem Namen „Wert“ von einem BeanItem von MyBean aufgebauten Integer vom Typ sein. Wenn die Eigenschaft an TextField gebunden wird, wird die Validierung für Texte, die nicht in eine Ganzzahl konvertiert werden können, automatisch fehlschlagen.

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); 

Mit diesem Beispiel eine Anzahl und Drücken der Taste Eingabe des Wert der TextField bewirkt ein String, der Wert der Eigenschaft zu sein, wird eine Integer sein, den gleichen Wert, und den Wert in der Bohne darstellt, wird das gleiche sein, int. Wenn z.B. ein Buchstabe wird in das Feld eingegeben und die Schaltfläche wird gedrückt, die Validierung schlägt fehl. Dies bewirkt, dass eine Benachrichtigung für das Feld angezeigt wird. Der Feldwert wird weiterhin aktualisiert, aber der Eigenschaftswert und der Bean-Wert werden auf ihren vorherigen Werten beibehalten.

+0

Ich möchte den Feldwert nicht aktualisieren. –

12

Vaadin 7 erlaubt thier eingebauten Widgets zu erweitern (wenn Sie möchten auf diese mehr Wissen habe ich das wirklich post empfehlen) hier eine Lösung ist, die das Verfahren verwendet.

Es besteht aus zwei Klassen: Connector und Extension

  1. Die Erweiterung

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

    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(); 
    } 
    } 
    

den Code ein verwenden bove Sie müssen es zu Ihrem aktuellen Widget-Set hinzufügen. Danach wird die Verwendung dieser ist wie folgt:

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

Um sie zum Widgetset hinzuzufügen, sollte die Connector-Klasse in einem Ordner namens "client" auf derselben Ebene wie die benutzerdefinierte widgetset-Datei (z. B. MyWigetSet.gwt.xml) sein. Um ein benutzerdefiniertes Widgetset zu verwenden, muss dies im Servlet als init-param deklariert werden. – enkara

2

In Vaadin 7 können Sie ein Textfield verwenden und einen Validator gesetzt nur Nummern erlauben:

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

ändern die Regex an Ihre Bedürfnisse anzupassen. Denken Sie daran, dass nach wie vor Strings ist der Umgang und deshalb müssen Sie noch die Rückkehr Wert des TextField- konvertieren:

Long.parseLong(textField.getValue()) 
2

Dies ist ein Update (2017 mit Vaadin 8) für @raffael Antwort:

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); 
    } 

} 

Voilà!