0

I inherited a project that uses GWT to create a web application. It uses a GWT wrapper for Bootstrap3 to do the styling of elements. This is working nicely for the most part. Now I hit a road block trying to add a Bootstrap3 Select to a GWT DataGrid table that currently uses a GWT SelectionCell. The problem is that a SelectionCell is not 'Bootstrap styled' and therefore doesn't match the style of the rest of web application.

Unfortunately, I cannot simply add the Select to a GWT DataGrid as the Select does not implement the GWT Cell interface nor does it extend a class that can be added to a Column that is then added to the DataGrid. Sub classing Select and implementing Cell fixes this problem. However, I cannot get the Select to render properly as it requires a JavaScript function to be executed after the Select has been attached to the DOM which it never is being wrapped by a Column in a DataGrid.

Instead, it is rendered into a SafeHtmlBuilder by the render function of Cell.

// GWTBootstrap3::Select function to render the Select
public void render() {
    if (isAttached())
        command(getElement(), SelectCommand.RENDER);
}

protected native void command(Element e, String command) /*-{
    $wnd.jQuery(e).selectpicker(command);
}-*/;

Since the Select is never attached to the DOM I need to call the selectpicker function manually. For his, I created my own native function which I need to call after the SafeHtmlBuilder has been added to the DataGrid. If my Select subclass accepts CLICK events through Cell's onBrowserEvent and calling the native function after clicking into the cell renders the Select properly.

What I cannot figure out is when to call the selectpicker function programatically to render the Select automatically after a row has been added by an RPC call. I tried to register different handlers to no avail. The handlers are called and my native function wrapping the selectpicker function is called as well but it seems like the HTML select has not yet been added to the table. Calling the above JavaScript snipped from the JavaScript console of a browser also works. So it should work find but I need to find the right place to call :(

Handlers in DataGrid that I am using:

  • addLoadingStateChangeHandler
  • addRowCountChangeHandler

I also tried to call it at different places after the calls to add to DataGrid the data have been made. Again, the HTML select doesn't seem to have been added to the table. ie. when I call the JavaScript snipped right after a call to myListDataProviderObject.getList()addAll(my data).

  • Would not it be easier to simply add Bootstrap CSS styles to your existing cell? – Andrei Volgin Aug 05 '16 at 00:54
  • The problem is that the HTML `select` is converted to something like this: `
    Text of select item
    • item1
    • itme2
    – Christian Aug 08 '16 at 12:49
  • And why is this a problem? You can still apply any CSS styles you need to this HTML. – Andrei Volgin Aug 10 '16 at 13:53
  • This is what I am doing as a fallback for now. However, adding the Bootstrap styles to the HTML `select` does not style the HTML `options` (which cannot be styled at the moment if I remember correctly). More importantly features of the Bootstrap `Select` like option groups and adding checkmarks will not work. – Christian Aug 11 '16 at 19:39

1 Answers1

0

Most likely you need to add a Scheduler call before calling your native method to make sure that the browser finished rendering the UI (e.g. your DataGrid) before this call is executed.

Community
  • 1
  • 1
Andrei Volgin
  • 40,755
  • 6
  • 49
  • 58
  • I tried to add a Scheduler as well as a Timer and got things working somewhat. Using a timer called from `DataGrid::redraw` renders the `Selects` after the data is added to the grid. Adding the Timer to the `render` function of my `Cell` implementation doesn't work even if I set the timeout of the timer to 20 seconds and the `select` is clearly added to the DOM . After selecting another drop-down the grid/cell is redrawn which removes the rendered select. I see my `render` method and the JS being called but the JS does not render the select. I stopped perssuing this for now. – Christian Aug 10 '16 at 13:34
  • Typically you use `refresh` on a DataProvider, not `redraw` on a DataGrid. Then you do not lose existing selections, etc. – Andrei Volgin Aug 10 '16 at 13:53
  • `DataGrid::redraw` is manually called only after the initial data has been added and when the `DataGrid` is shown (the page uses multiple tabs each having its own `DataGrid`). If `redraw` is not called the page will only show the row header not the data. – Christian Aug 11 '16 at 19:34
  • I'll check the `DataProvider::refresh` function, thanks for pointing this out. – Christian Aug 11 '16 at 19:35
  • DataGrid in tabs is a different issue - sometimes it gets height of 0 when tabs are switched, which is done by changing their visibility. Typically, you need another Scheduler call :). Alternatively, if you can set height on your DataGrid, you won't need to redraw it. – Andrei Volgin Aug 11 '16 at 19:46