如何在GWT celltable EditTextCell中添加多行文本?

时间:2011-07-20 11:47:07

标签: gwt gwt-2.2-celltable gwt-edittext

我有一个显示数据的单元格。我想编辑单元格以提供多行信息。

实施例: 键1 =值|在下一行添加anoter键: 键2 =值|

编辑值后,当显示/重绘单元格时,信息应如上所示显示在单元格中。

4 个答案:

答案 0 :(得分:1)

我已经解决了部分问题。我正在使用CellTable和自定义TextAreaEditCell。现在我可以输入多行数据。但是当它进入数据库或者当celltable显示信息时,信息是按顺序形式的。

实施例

当我在TestAreaCell中输入这样的数据时: A B C D 在下一行中,输入efgh然后输入

显示时的输出为:

ABCDEFGH

问题:似乎没有考虑输入密钥:

我的TextAreaEditCell类如下。如果需要进行任何更正,请告诉我。

我已经解决了部分问题。我正在使用CellTable和自定义TextAreaEditCell。现在我可以输入多行数据。但是当它进入数据库或者当celltable显示信息时,信息是按顺序形式的。

实施例

当我在TestAreaCell中输入这样的数据时: A B C D 在下一行中,输入efgh然后输入

显示时的输出为:

ABCDEFGH

问题:似乎没有考虑输入密钥:

我的TestAreaEditCell类如下。如果需要进行任何更正,请告诉我。

import com.google.gwt.cell.client.AbstractEditableCell;
import com.google.gwt.cell.client.Cell.Context; 
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT; 
import com.google.gwt.dom.client.Element; 
import com.google.gwt.dom.client.EventTarget; 
import com.google.gwt.dom.client.InputElement; 
import com.google.gwt.dom.client.NativeEvent; 
import com.google.gwt.dom.client.TextAreaElement;
import com.google.gwt.event.dom.client.KeyCodes; 
import com.google.gwt.safehtml.client.SafeHtmlTemplates; 
import com.google.gwt.safehtml.shared.SafeHtml; 
import com.google.gwt.safehtml.shared.SafeHtmlBuilder; 
import com.google.gwt.text.shared.SafeHtmlRenderer; 
import com.google.gwt.text.shared.SimpleSafeHtmlRenderer; 

/** 
 * An editable text cell. Click to edit, escape to cancel, return to commit. 
 */ 
public class TextAreaEditCell  extends 
AbstractEditableCell<String, TextAreaEditCell .ViewData> { 

    interface Template extends SafeHtmlTemplates { 
        //@Template("<input type=\"text\" value=\"{0}\" tabindex=\"-1\"></input>")  
        //SafeHtml input(String value);

        //using textarea (instead of text) to add multiple lines of data in a cell.
        @Template("<textarea tabindex=\"-1\" rows=\"{1}\" cols=\"{2}\" >{0}</textarea>")
        SafeHtml input(String value, Integer rows, Integer cols); 
    } 

    /** 
     * The view data object used by this cell. We need to store both the text and 
     * the state because this cell is rendered differently in edit mode. If we did 
     * not store the edit state, refreshing the cell with view data would always 
     * put us in to edit state, rendering a text box instead of the new text 
     * string. 
     */ 
    static class ViewData { 

        private boolean isEditing; 

        /** 
         * If true, this is not the first edit. 
         */ 
        private boolean isEditingAgain; 

        /** 
         * Keep track of the original value at the start of the edit, which might be 
         * the edited value from the previous edit and NOT the actual value. 
         */ 
        private String original; 

        private String text; 

        /** 
         * Construct a new ViewData in editing mode. 
         * 
         * @param text the text to edit 
         */ 
        public ViewData(String text) { 
            this.original = text; 
            this.text = text; 
            this.isEditing = true; 
            this.isEditingAgain = false; 

        } 

        @Override 
        public boolean equals(Object o) { 
            if (o == null) { 
                return false; 
            } 
            ViewData vd = (ViewData) o; 
            return equalsOrBothNull(original, vd.original) 
            && equalsOrBothNull(text, vd.text) && isEditing == vd.isEditing 
            && isEditingAgain == vd.isEditingAgain; 
        } 

        public String getOriginal() { 
            return original; 
        } 

        public String getText() { 
            return text; 
        } 

        @Override 
        public int hashCode() { 
            return original.hashCode() + text.hashCode() 
            + Boolean.valueOf(isEditing).hashCode() * 29 
            + Boolean.valueOf(isEditingAgain).hashCode(); 
        } 

        public boolean isEditing() { 
            return isEditing; 
        } 

        public boolean isEditingAgain() { 
            return isEditingAgain; 
        } 

        public void setEditing(boolean isEditing) { 
            boolean wasEditing = this.isEditing; 
            this.isEditing = isEditing; 

            // This is a subsequent edit, so start from where we left off. 
            if (!wasEditing && isEditing) { 
                isEditingAgain = true; 
                original = text; 
            } 
        } 

        public void setText(String text) { 
            this.text = text; 
        } 

        private boolean equalsOrBothNull(Object o1, Object o2) { 
            return (o1 == null) ? o2 == null : o1.equals(o2); 
        } 
    } 

    private static Template template; 
    private int inputWidth; 
    private int inputLength;

    public int getInputWidth() { 
        return inputWidth; 
    } 

    public void setInputWidth(int inputWidth) { 
        this.inputWidth = inputWidth; 
    } 

    public int getInputLength() { 
        return inputLength; 
    } 

    public void setInputLength(int inputLength) { 
        this.inputLength = inputLength; 
    } 

    private final SafeHtmlRenderer<String> renderer; 

    /** 
     * Construct a new EditTextCell that will use a 
     * {@link SimpleSafeHtmlRenderer}. 
     */ 
    public TextAreaEditCell() {    

        this(SimpleSafeHtmlRenderer.getInstance(), 1, 20); 
        this.inputWidth = 10;
        this.inputLength =2;    
    }

    private int rows, cols;

    /** 
     * Construct a new TextAreaEditCell that will use a given {@link SafeHtmlRenderer} 
     * to render the value when not in edit mode. 
     *  
     * @param renderer a {@link SafeHtmlRenderer SafeHtmlRenderer<String>} 
     *          instance 
     */ 
    public TextAreaEditCell(SafeHtmlRenderer<String> renderer, int r, int c) { 
        super("click", "keyup", "keydown", "blur"); 
        rows = r; 
        cols = c; 


        if (template == null) { 
            template = GWT.create(Template.class); 
        } 
        if (renderer == null) { 
            throw new IllegalArgumentException("renderer == null"); 
        } 
        this.renderer = renderer; 
    } 

    @Override 
    public boolean isEditing(Context context, Element parent, String value) { 
        ViewData viewData = getViewData(context.getKey()); 
        return viewData == null ? false : viewData.isEditing(); 
    } 

    @Override 
    public void onBrowserEvent(Context context, Element parent, String value, 
            NativeEvent event, ValueUpdater<String> valueUpdater) { 

        Object key = context.getKey(); 
        ViewData viewData = getViewData(key); 
        if (viewData != null && viewData.isEditing()) { 
            // Handle the edit event. 
            editEvent(context, parent, value, viewData, event, valueUpdater); 
        } else { 
            String type = event.getType(); 
            int keyCode = event.getKeyCode(); 
            boolean enterPressed = "keyup".equals(type) ;
            //  && keyCode == KeyCodes.KEY_ENTER; 


            if ("click".equals(type) || enterPressed) { 
                // Go into edit mode. 
                if (viewData == null) { 
                    viewData = new ViewData(value); 
                    setViewData(key, viewData); 
                } else { 
                    viewData.setEditing(true); 
                } 
                edit(context, parent, value); 
            } 
        } 
    } 

    @Override 
    public void render(Context context, String value, SafeHtmlBuilder sb) { 

        // Get the view data. 
        Object key = context.getKey(); 
        ViewData viewData = getViewData(key); 
        if (viewData != null && !viewData.isEditing() && value != null 
                && value.equals(viewData.getText())) { 
            clearViewData(key); 
            viewData = null; 
        } 

        if (viewData != null) { 
            String text = viewData.getText(); 
            if (viewData.isEditing()) { 
                /* 
                 * Do not use the renderer in edit mode because the value of a text 
                 * input element is always treated as text. SafeHtml isn't valid in the 
                 * context of the value attribute. 
                 */ 
                sb.append(template.input(text, inputLength, inputWidth)); 
            } 
            else { 
                // The user pressed enter, but view data still exists. 
                sb.append(renderer.render(text)); 
            } 
        } else if (value != null) { 
            sb.append(renderer.render(value)); 
        } 
    } 

    @Override 
    public boolean resetFocus(Context context, Element parent, String value) { 

        if (isEditing(context, parent, value)) { 
            getInputElement(parent).focus(); 
            return true; 
        } 
        return false; 
    } 

    /** 
     * Convert the cell to edit mode. 
     * 
     * @param context the {@link Context} of the cell 
     * @param parent the parent element 
     * @param value the current value 
     */ 
    protected void edit(Context context, Element parent, String value) { 
        setValue(context, parent, value); 
        TextAreaElement input = getInputElement(parent); 
        input.focus(); 
        input.select(); 
    } 

    /** 
     * Convert the cell to non-edit mode. 
     *  
     * @param context the context of the cell 
     * @param parent the parent Element 
     * @param value the value associated with the cell 
     */ 
    private void cancel(Context context, Element parent, String value) { 
        clearInput(getInputElement(parent)); 
        setValue(context, parent, value); 
    } 

    /** 
     * Clear selected from the input element. Both Firefox and IE fire spurious 
     * onblur events after the input is removed from the DOM if selection is not 
     * cleared. 
     * 
     * @param input the input element 
     */ 
    private native void clearInput(Element input) /*-{ 
    if (input.selectionEnd) 
      input.selectionEnd = input.selectionStart; 
    else if ($doc.selection) 
      $doc.selection.clear(); 
  }-*/; 

    /** 
     * Commit the current value. 
     *  
     * @param context the context of the cell 
     * @param parent the parent Element 
     * @param viewData the {@link ViewData} object 
     * @param valueUpdater the {@link ValueUpdater} 
     */ 
    private void commit(Context context, Element parent, ViewData viewData, 
            ValueUpdater<String> valueUpdater) { 
        String value = updateViewData(parent, viewData, false); 
        clearInput(getInputElement(parent)); 
        setValue(context, parent, viewData.getOriginal()); 
        if (valueUpdater != null) { 
            valueUpdater.update(value); 
        } 
    } 

    private void editEvent(Context context, Element parent, String value, 
            ViewData viewData, NativeEvent event, ValueUpdater<String> valueUpdater) { 
        String type = event.getType(); 
        boolean keyUp = "keyup".equals(type); 
        boolean keyDown = "keydown".equals(type); 
        if (keyUp || keyDown) { 
            int keyCode = event.getKeyCode(); 

            /*      if (keyUp && keyCode == KeyCodes.KEY_ENTER) { 
                // Commit the change. 
                commit(context, parent, viewData, valueUpdater); 
            } 
            else*/ 
            if (keyUp && keyCode == KeyCodes.KEY_ESCAPE) { 
                // Cancel edit mode. 
                String originalText = viewData.getOriginal(); 
                if (viewData.isEditingAgain()) { 
                    viewData.setText(originalText); 
                    viewData.setEditing(false); 
                } else { 
                    setViewData(context.getKey(), null); 
                } 
                cancel(context, parent, value); 
            } else { 
                // Update the text in the view data on each key. 
                updateViewData(parent, viewData, true); 
            } 
        } else if ("blur".equals(type)) { 
            // Commit the change. Ensure that we are blurring the input element and 
            // not the parent element itself. 
            EventTarget eventTarget = event.getEventTarget(); 
            if (Element.is(eventTarget)) { 
                Element target = Element.as(eventTarget); 
                if ("textarea".equals(target.getTagName().toLowerCase())) { 
                    commit(context, parent, viewData, valueUpdater); 
                } 
            } 
        } 
    } 

    /** 
     * Get the input element in edit mode. 
     */ 
    private TextAreaElement  getInputElement(Element parent) { 
        return parent.getFirstChild().<TextAreaElement> cast(); 
    } 

    /** 
     * Update the view data based on the current value. 
     * 
     * @param parent the parent element 
     * @param viewData the {@link ViewData} object to update 
     * @param isEditing true if in edit mode 
     * @return the new value 
     */ 
    private String updateViewData(Element parent, ViewData viewData, 
            boolean isEditing) { 
        TextAreaElement input = (TextAreaElement) parent.getFirstChild();       
        String value = input.getValue(); 
        viewData.setText(value); 
        viewData.setEditing(isEditing); 
        return value; 
    } 
} 

答案 1 :(得分:0)

我做了类似的事情;虽然不完全一样。所以也许像这样的SOMETHING会起作用。

您需要提供自己的render()方法。所以在下面的render()方法中,你可以添加你想要的任何内容。

列selectCheckBoxColumn =                 new Column(new MyCheckBoxCell()){

               @Override
               public String getValue(MyJSONObject object) {
                  return object.getInternalId();
               }
            };
         MyCellTable.addColumn(selectCheckBoxColumn, "Display title");

.....
.....
.....

   private class MyCheckBoxCell extends AbstractCell<String> {

      @Override
      public void render(Context context, String value, SafeHtmlBuilder sb) {

         /*
          * Always do a null check on the value. Cell widgets can pass null to
          * cells if the underlying data contains a null, or if the data arrives
          * out of order.
          */
         if (value == null) {
            return;
         }

         sb.appendHtmlConstant("<input type='checkbox' name='" + htmlDOMId1 + "'" +
                               " id='" + htmlDOMId1 + "'" +
                               " value='" + value + "'" +
                               "></input>");

      }
   }

答案 2 :(得分:0)

您必须将换行符(\ n)转换为HTML换行符(&lt; BR&gt;)

您可以在后端保存数据时执行此操作,也可以在 TextAreaEditCell

的渲染方法中执行此操作

类似的东西:

@Override 
public void render(Context context, String value, SafeHtmlBuilder sb) { 

    // Get the view data. 
    Object key = context.getKey(); 
    ViewData viewData = getViewData(key); 
    if (viewData != null && !viewData.isEditing() && value != null 
            && value.equals(viewData.getText())) { 
        clearViewData(key); 
        viewData = null; 
    } 

    if (viewData != null) { 
        String text = viewData.getText(); 
        if (viewData.isEditing()) { 
            /* 
             * Do not use the renderer in edit mode because the value of a text 
             * input element is always treated as text. SafeHtml isn't valid in the 
             * context of the value attribute. 
             */ 
            sb.append(template.input(text, inputLength, inputWidth)); 
        } 
        else { 
            // The user pressed enter, but view data still exists. 

            String escaped_text = text.replace("\n","<BR>").replace("\r","");
            sb.append(renderer.render(escaped_text)); 
        } 
    } else if (value != null) { 
        String escaped_text = value.replace("\n","<BR>").replace("\r","");
        sb.append(renderer.render(escaped_text)); 
    } 
} 

答案 3 :(得分:0)

这是render方法的工作解决方案,它将在TextAreaEditCell中显示多行。基本上,您将基于\ n字符拆分存储的字符串,然后将它们连接起来,将该标记作为SafeBuilder的HTML常量附加。

@覆盖     public void render(Context context,String value,SafeHtmlBuilder sb){

    // Get the view data. 
    Object key = context.getKey(); 
    ViewData viewData = getViewData(key); 
    if (viewData != null && !viewData.isEditing() && value != null 
            && value.equals(viewData.getText())) { 
        clearViewData(key); 
        viewData = null; 
        /*
         * Render a blank space to force the rendered element to have a height.
         * Otherwise it is not clickable.
         */
        sb.appendHtmlConstant("\u00A0");
    } 

    if (viewData != null) { 
        String text = viewData.getText(); 
        if (viewData.isEditing()) { 
            /* 
             * Do not use the renderer in edit mode because the value of a text 
             * input element is always treated as text. SafeHtml isn't valid in the 
             * context of the value attribute. 
             */ 
            sb.append(template.input(text, inputLength, inputWidth)); 
        } 
        else { 
            // The user pressed enter, but view data still exists. 
            String[] items = text.split("\n");
            for (String item : items) {
                sb.append(renderer.render(item));
                sb.appendHtmlConstant("<br/>");
              }
            sb.appendHtmlConstant("\u00A0");

        } 
    } else if (value != null) { 
        String[] items = value.split("\n");
        for (String item : items) {
            sb.append(renderer.render(item));
            sb.appendHtmlConstant("<br/>");
          }

        /*
         * Render a blank space to force the rendered element to have a height.
         * Otherwise it is not clickable.
         */
        sb.appendHtmlConstant("\u00A0");
    }

}