Search code examples
gwtgwt2gwt-celltable

Events of multiple cells in single column


I have two buttons(edit + delete) in one column.

    ButtonCell functionButtonCell = new ButtonCell() {
    @Override
    public void render(final Context context, final SafeHtml data, final SafeHtmlBuilder sb) {
        sb.appendHtmlConstant("<button type='button' class='gwt-Button' style = 'width:60px;margin:1px;'>Edit</button>");
        sb.appendHtmlConstant("<br/>");
        sb.appendHtmlConstant("<button type='button' class='gwt-Button' style = 'width:60px;margin:1px;'>Delete</button>");
        }
    };
    functionColumn = new Column<AdminModel, String>(functionButtonCell) {
        public String getValue(final AdminModel object) {
            return object.getSeq().toString();
        }
    };

Bind event for this column in Presenter as

.........
view.getFunctionColumn().setFieldUpdater(new FieldUpdater<AdminModel, String>() {

   public void update(final int index, final AdminModel object, final String value) {
            Window.alert(index + "-" + value);
        }
    });

After clicked on edit button , alert-box has appeared , but not on delete button. When I clicked on delete button , nothing has appeared. What would be the problem ?

Addition: How can I decide which button was clicked by user (edit or delete) from my presenter ?

I would really appreciate any of your suggestions because I am troubled on it for a long times. Thanks!


Solution

  • ButtonCell filters events on the first child element only: https://gwt.googlesource.com/gwt/+/2.6.1/user/src/com/google/gwt/cell/client/ButtonCell.java This is why you don't get an event when clicking the second button (note: the goal of that code is to make sure you clicked on the button, and not on blank space around the button; see https://gwt.googlesource.com/gwt/+/a0dc88c8be7408be9554f746eb1ec93798183a28)

    The easiest way to implement a two-button cell is to use a CompositeCell; it requires that child cells are rendered into sibling elements though (uses <span>s by default, example below overrides the rendering to use <div>s so your buttons stack each on its own line).

    new CompositeCell<AdminModel>(Arrays.asList(
      // First button
      new HasCell<AdminModel, String>() {
        @Override public Cell<String> getCell() { return new ButtonCell(); }
        @Override public FieldUpdated<AdminModel, String> getFieldUpdater() {
          return new FieldUpdater<AdminModel, String>() {
            @Override public void update(int index, AdminModel object, String value) {
              Window.alert("Edit " + object.getId());
            }
          };
        }
        @Override public String getValue(AdminModel o) {
          return "Edit";
        }
      },
      // Second button
      new HasCell<AdminModel, String>() {
        @Override public Cell<String> getCell() { return new ButtonCell(); }
        @Override public FieldUpdated<AdminModel, String> getFieldUpdater() {
          return new FieldUpdater<AdminModel, String>() {
            @Override public void update(int index, AdminModel object, String value) {
              Window.alert("Delete " + object.getId());
            }
          };
        }
        @Override public String getValue(AdminModel o) {
          return "Delete";
        }
      }) {
      @Override protected <X> void render(Cell.Context context, AdminModel value, SafeHtmlBuilder sb, HasCell<String,X> hasCell) {
        // use a <div> instead of the default <span>
        Cell<X> cell = hasCell.getCell();
        sb.appendHtmlConstant("<div>");
        cell.render(context, hasCell.getValue(value), sb);
        sb.appendHtmlConstant("</div>");
      }
    };
    

    (note: in your case, because the button's text doesn't depend on the row object, maybe you should rather use an ActionCell; it would better fit "semantically" with what you're doing, but otherwise it's almost the same; with an ActionCell, you'd use HasCell<AdminModel, AdminModel>, ActionCell<AdminModel>, getFieldUpdater would return null, and thegetValueof theHasCellwould just return theAdminModel` argument as-is).

    Otherwise, implement your Cell (or AbstractCell) entirely by yourself.