2013-06-17 42 views
10

Tôi đang sử dụng trường văn bản Vaadin và tôi muốn hạn chế trường văn bản chỉ hỗ trợ các số trong đó. Tôi đã cố gắng ghi đè lên số setValue() và trả lại mà không cần gọi điện thoại siêu. setValue() nếu văn bản không phải là số. Nhưng nó dường như không hoạt động. Làm thế nào tôi có thể sửa lỗi này? Tôi đang sử dụng Vaadin 7. Và tôi nghĩ nó cũng không hỗ trợ NumberField.làm cách nào để tạo một trường văn bản chỉ hỗ trợ số điện thoại trong vaadin

Trả lời

16

Nếu tôi hiểu câu hỏi của bạn đúng, bạn muốn có một trường bỏ qua tất cả các đầu vào không phải là số và không chỉ đánh dấu trường là không hợp lệ. Kiến trúc của Vaadins được thiết kế để mọi trường trong trình duyệt có biểu diễn trên máy chủ. Theo tôi, cách sạch nhất để đạt được điều này là có một trường trình duyệt, cho phép nhập các chữ cái và các ký tự sai khác. Tôi không thể tìm thấy một lĩnh vực như vậy trong Vaadin 7. Có vẻ như là một add-on cho vaadin 6 được gọi là Number Field cho điều đó, nhưng tôi đã không thử nghiệm nó.
Bạn có nhiều lựa chọn:

  1. Cảng add-on để vaadin 7 hoặc yêu cầu tác giả để làm điều đó

  2. Viết lĩnh vực riêng của mình này. Có lẽ mở rộng VTextField và TextFieldConnector

  3. làm tất cả mọi thứ ở phía máy chủ và chấp nhận sự chậm trễ và giao thông (IMHO xấu xí)

Vì tôi nghĩ rằng lựa chọn 3 là không con đường để đi, tôi có lẽ không nên hiển thị mã này, nhưng đó là cách nhanh nhất để triển khai mã này.

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

cảm ơn anh chàng. Nó hoạt động tốt. Tôi đã thêm một số kiểm tra rỗng và kiểm tra trống và xử lý chúng. –

+0

Làm việc nhưng khi gõ nhiều ký tự một cách nhanh chóng, bạn vẫn có thể nhập nội dung không mong muốn – Eyal

+1

Thực tiễn thường được coi là xấu để sử dụng ngoại lệ cho luồng điều khiển. Xem http://c2.com/cgi/wiki?DontUseExceptionsForFlowControl, http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so -why hoặc http://stackoverflow.com/questions/729379/why-not-use-exceptions-as-regular-flow-of-control. –

2

A TextField là thành phần luôn có giá trị loại String. Khi liên kết thuộc tính của một loại khác với trường văn bản, giá trị được tự động chuyển đổi nếu chuyển đổi giữa hai loại được hỗ trợ.

public class MyBean { 
    private int value; 

    public int getValue() { 
     return value; 
    } 

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

Thuộc tính tên là "giá trị" từ một BeanItem xây dựng từ MyBean sẽ loại Integer. Việc gắn kết thuộc tính với một TextField sẽ tự động thực hiện xác thực không thành công đối với các văn bản không thể được chuyển đổi thành một số nguyên.

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

Với ví dụ này, nhập một số và nhấn nút này khiến giá trị của TextField là một String, giá trị tài sản sẽ là một Integer đại diện cho các giá trị như nhau và giá trị trong đậu sẽ giống nhau int. Nếu ví dụ: một lá thư được nhập vào trường và nút được nhấn, việc xác thực sẽ thất bại. Điều này làm cho một thông báo được hiển thị cho trường. Giá trị trường vẫn được cập nhật, nhưng giá trị thuộc tính và giá trị bean được giữ ở giá trị trước đó của chúng.

+0

Tôi không muốn cập nhật giá trị trường. –

12

Vaadin 7 cho phép mở rộng xây dựng của họ trong các widget (nếu bạn muốn có thêm kiến ​​thức về vấn đề này tôi thực sự khuyên này post) đây là một giải pháp trong đó sử dụng cơ chế.

Nó bao gồm hai lớp: kết nối và mở rộng

  1. Việc mở rộng

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

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

Để sử dụng mã một bove bạn cần phải thêm nó vào bộ widget hiện tại của bạn. Sau đó việc sử dụng của việc này là như sau:

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

Để thêm nó vào tiện ích con, lớp Trình kết nối phải nằm trong một thư mục có tên "khách hàng" ở cùng cấp với tệp widgetset tùy chỉnh (ví dụ MyWigetSet.gwt.xml). Để sử dụng một widgetset tùy chỉnh, điều này phải được khai báo như một init-param trong servlet. – enkara

2

Trong Vaadin 7, bạn có thể sử dụng một TextField và thiết lập một validator để chỉ cho phép số:

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

Thay đổi regex để phù hợp với nhu cầu của bạn. Hãy nhớ rằng vẫn là xử lý Strings và do đó bạn vẫn cần phải chuyển đổi các giá trị trở lại của TextField:

Long.parseLong(textField.getValue()) 
2

Đây là một bản cập nhật (2017 với vaadin 8) cho @raffael câu trả lời:

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

Các vấn đề liên quan