2013-06-17 8 views

Odpowiedz

16

Jeśli rozumiem, że pytanie jest poprawne, chcesz mieć pole, które ignoruje wszystkie dane wejściowe, które nie są liczbą, i nie tylko oznaczyć pole jako nieprawidłowe. Architektura Vaadins została zaprojektowana tak, aby każde pole w przeglądarce miało swoją reprezentację na serwerze. Moim zdaniem najczystszym sposobem na osiągnięcie tego byłoby posiadanie pola przeglądarki, które pozwala na wprowadzanie liter i innych złych znaków. Nie mogłem znaleźć takiego pola w Vaadin 7. Wydaje się, że jest tam dodatek do vaadin 6 o nazwie Number Field, ale go nie przetestowałem.
Masz kilka opcji:

  1. Port ten dodatek do Vaadin 7 lub zapytać autora to zrobić

  2. Napisz pole. Może rozszerzenie VTextField i TextFieldConnector

  3. Czy wszystko po stronie serwera i zaakceptować opóźnień i ruch (IMHO brzydki)

Ponieważ myślę, że opcja 3 jest nie droga, pewnie nie powinien pokazywać tego kodu, ale jest to najszybszy sposób na jego wdrożenie.

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

dzięki stary. To działa dobrze. Dodałem kilka pustych czeków i pustych czeków i załatwiłem je. –

+0

Działa, ale przy szybkim wpisywaniu wielu znaków nadal można wprowadzać niepożądane treści. – Eyal

+1

Jego generalnie uważa się za złą praktykę stosowanie wyjątków do sterowania przepływem. Zobacz http://c2.com/cgi/wiki?DontUseExceptionsForFlowControl, http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so -dhy lub http://stackoverflow.com/questions/729379/why-not-use-exceptions-as-regular-flow-of-control. –

2

A TextField to komponent, który zawsze ma wartość typu String. Podczas wiązania właściwości innego typu z polem tekstowym wartość jest automatycznie konwertowana, jeśli konwersja między tymi dwoma typami jest obsługiwana.

public class MyBean { 
    private int value; 

    public int getValue() { 
     return value; 
    } 

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

Obiekt o nazwie „wartość” z BeanItem zbudowanego z MyBean będzie od rodzaju Integer. Wiązanie właściwości z TextField spowoduje automatyczne sprawdzenie poprawności tekstów, których nie można przekonwertować na liczbę całkowitą.

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

W tym przykładzie wprowadzanie numeru i naciśnięcie przycisku powoduje, że wartość TextField być String wartość właściwość będzie Integer reprezentujący tę samą wartość, a wartość w ziarnach będzie taka sama int. Jeśli np. do pola zostanie wprowadzona litera, a przycisk zostanie naciśnięty, sprawdzanie poprawności zakończy się niepowodzeniem. Powoduje to wyświetlenie powiadomienia dla pola. Wartość pola jest nadal aktualizowana, ale wartość właściwości i wartość komponentu bean są przechowywane w ich poprzednich wartościach.

+0

Nie chcę aktualizować wartości pola. –

12

Vaadin 7 pozwala przedłużyć thier wybudowany w widgetach (jeśli chcesz mieć większą wiedzę na ten temat naprawdę polecam ten post) Tutaj jest rozwiązanie, które używa tego mechanizmu.

Składa się on z dwóch klas: Connector oraz rozszerzenie

  1. Extension

    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. Złącze:

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

Aby użyć kodu do A bove musisz dodać go do bieżącego zestawu widgetów. Następnie korzystanie z tego jest następujący:

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

Aby dodać go do zestawu widgetów, klasa Connector powinna znajdować się w folderze o nazwie "client" na tym samym poziomie co niestandardowy plik zestawu widgetów (na przykład MyWigetSet.gwt.xml). Aby użyć niestandardowego zestawu widgetów, musi on zostać zadeklarowany jako init-param w serwlecie. – enkara

2

W Vaadin 7, można użyć TextField i ustawić walidator, aby umożliwić tylko liczby:

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

Zmień regex do swoich potrzeb. Pamiętaj, że nadal obsługi łańcuchów i dlatego nadal trzeba konwertować wartości Zwrot TextField:

Long.parseLong(textField.getValue()) 
2

Jest to aktualizacja (2017 z Vaadin 8) dla @raffael odpowiedź:

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à!

Powiązane problemy