Put component into Grid cell

Hi!

In my project I need put some advanced HTML structure (like toggle menu) in a table (I mean Grid class). That structure should be dependent on row (I wanna bind some listeners with this structure). Is it possible to make something like this?

Thanks for help.

Kind of - using a Renderer.
https://vaadin.com/book/-/page/clientsidewidgets.grid.html

Ok, but how I should use this Renderers? I’m trying to make something usable (extend HtmlRenderer, extend ButtonRenderer etc.), but cannot bind grid item with component. Can You show me some simple examples?

As you’re trying to display Widgets like a ToogleMenu you should probably extend WidgetRenderer as you can define exactly what kind of Widget you want to display and how to handle its events.
This is not a trivial task though but it is doable. There also aren’t really any good example. The only thing I know is a bit of code i made to display TextFields in a Grid that store the new Values on ValueChange. Code can be found here:
https://vaadin.com/forum#!/thread/10495424/10511744

@Marius: Thanks for help. I tried to make something like you in that post, but my custom renderer cannot be applied by column’s setRenderer() method. Adding “implements Renderer” to it are not solving problem (I have java.lang.NullPointerException on my console when I’m trying to run subpage with my grid).

Any ideas what is wrong?

class MenuRenderer extends WidgetRenderer<String, MyMenu> implements Renderer {

@Override
public MyMenu createWidget() {
return new MyMenu();
}

@Override
public void render(RendererCellReference rendererCellReference, String s, MyMenu myMenu) {

}

@Override
public Class getPresentationType() {
return null;
}

@Override
public JsonValue encode(Object o) {
return null;
}

@Override
public void remove() {

}

@Override
public void setParent(ClientConnector clientConnector) {

}

@Override
public void addAttachListener(AttachListener attachListener) {

}

@Override
public void removeAttachListener(AttachListener attachListener) {

}

@Override
public void addDetachListener(DetachListener detachListener) {

}

@Override
public void removeDetachListener(DetachListener detachListener) {

}

@Override
public List<ClientMethodInvocation> retrievePendingRpcCalls() {
return null;
}

@Override
public boolean isConnectorEnabled() {
return false;
}

@Override
public Class<? extends SharedState> getStateType() {
return null;
}

@Override
public String getConnectorId() {
return null;
}

@Override
public ClientConnector getParent() {
return null;
}

@Override
public void requestRepaint() {

}

@Override
public void markAsDirty() {

}

@Override
public void requestRepaintAll() {

}

@Override
public void markAsDirtyRecursive() {

}

@Override
public boolean isAttached() {
return false;
}

@Override
public void attach() {

}

@Override
public void detach() {

}

@Override
public Collection<Extension> getExtensions() {
return null;
}

@Override
public void removeExtension(Extension extension) {

}

@Override
public UI getUI() {
return null;
}

@Override
public void beforeClientResponse(boolean b) {

}

@Override
public JsonObject encodeState() {
return null;
}

@Override
public boolean handleConnectorRequest(VaadinRequest vaadinRequest, VaadinResponse vaadinResponse, String s) throws IOException {
return false;
}

@Override
public ServerRpcManager<?> getRpcManager(String s) {
return null;
}

@Override
public ErrorHandler getErrorHandler() {
return null;
}

@Override
public void setErrorHandler(ErrorHandler errorHandler) {

}
}

class MyMenu extends Widget {

MyMenu () {
super();

final MenuBar settings = new MenuBar();
settings.addStyleName("user-menu");

settingsItem = settings.addItem("", null, null);

settingsItem.addItem("Profil", new MenuBar.Command() {
@Override
public void menuSelected(final MenuBar.MenuItem selectedItem) {
//ProfilePreferencesWindow.open(user, false);
}
});
settingsItem.addItem("Ustawienia", new MenuBar.Command() {
@Override
public void menuSelected(final MenuBar.MenuItem selectedItem) {
//ProfilePreferencesWindow.open(user, true);
}
});
settingsItem.addSeparator();
settingsItem.addItem("Wylogowanie", new MenuBar.Command() {
@Override
public void menuSelected(final MenuBar.MenuItem selectedItem) {
DashboardEventBus.post(new DashboardEvent.UserLoggedOutEvent());
}
});

setContent(settings);
}

EDIT: ok, nullPointerException was casted in getPresentationType() method. But - how to set correct presentation type?

implements Renderer is not necessary here. As are most of the @Overrides that you have in there.
The problem here probably is that you’re trying to use server-side components while the Renderer should be defined with client-side/GWT widgets. See that i used TextBox instead of TextField in my example Renderer (TextField being the Vaadin server-side component and TextBox being the GWT “equivalent”)

The client-side widgets of Vaadin component are normally called “V”+the components name so it would be something like VMenuBar for your example though i’m not entirely sure that it’ll work as you expect it.

Also to get events back to the server-side you have to use a ServerRPC (look in the Vaadin 7 wiki for examples on that). Your EventBus will probably not work on the client-side if its defined on the server.

Additional note: Client-side classes have to be in the client package below the widgetset so if you have your widgetset.gwt.xml in com.example.widgetset your client side classes (such as the WidgetRenderer and the connector) need to be in com.example.widgetset.client .