PDA

View Full Version : Hyperlinks in grid rowexpander cause whole page reload



tqb_extjs
6 Feb 2010, 9:09 AM
Hi,

I'm using GWT 1.6.4 and GXT 2.1.

I'm using the GWT History class and I'm seeing links it creates behaving differently depending on which GXT component I add them to.

The idea is that I can use the History service and Hyperlink class to create links in my application that don't result in the whole page reloading when clicked. This is great because it means that I can still update the UI in response to the user clicking regular hyperlinks and these "application states" can be bookmarked in the usual way.

However, whilst I've found that they work correctly when added to a regular grid row, when added to a rowexpander they result in the whole page reloading.

The code below demonstrates both cases.



If you click link "Test Link In Row" then a message box will popup without the page reloading. This is the behaviour I want and was expecting.




If you click link "Test Link Expanded" then the whole page reloads and then the message box is displayed. I think this is incorrect and it breaks the "one page app" feel.



public class GridPluginsExample extends LayoutContainer implements ValueChangeHandler<String>
{
public GridPluginsExample()
{
setLayout(new FitLayout());
History.addValueChangeHandler(this);
History.fireCurrentHistoryState();
}

@Override
protected void onRender(Element parent, int index)
{
super.onRender(parent, index);

List<ColumnConfig> configs = new ArrayList<ColumnConfig>();

RowExpander expander = new RowExpander()
{
@Override
protected boolean beforeExpand(ModelData model, Element body, El row, int rowIndex)
{
RowExpanderEvent e = new RowExpanderEvent(this);
e.setModel(model);
e.setRowIndex(rowIndex);
e.setBodyElement(body);

if (fireEvent(Events.BeforeExpand, e))
{
body.setInnerHTML("");
Hyperlink link = new Hyperlink("Test Link Expanded", "linkExpandedToken");
new WidgetComponent(link).render(body);
return true;
}
return false;
}
};
configs.add(expander);

ColumnConfig column = new ColumnConfig();
column.setHeader("Column");
column.setWidth(200);
column.setRenderer(new GridCellRenderer<ModelData>()
{
@Override
public Object render(ModelData model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<ModelData> store, Grid<ModelData> grid)
{
return new Hyperlink("Test Link In Row", "linkToken");
}
});
configs.add(column);

ListStore<ModelData> store = new ListStore<ModelData>();
store.add(new BaseModelData());

Grid<ModelData> grid = new Grid<ModelData>(store, new ColumnModel(configs));
grid.setHeight(500);
grid.addPlugin(expander);
grid.getView().setAutoFill(true);

add(grid);
}

@Override
public void onValueChange(ValueChangeEvent<String> e)
{
MessageBox.info("History Event", "Token: " + e.getValue(), null);
}

}I suspect there is something going on with event processing but I've been unable to understand why this is happening.

I'd be grateful of any pointers or suggestions.

Cheers.

mattress10
6 Feb 2010, 9:13 AM
Thanks for the code..
B)

tqb_extjs
9 Feb 2010, 5:51 AM
..Bump..

I'm still struggling with this. I'm presuming that's because it's not a straight-forward one to answer :-?

I wonder if anyone can suggest anyway of investigating the problem further or gathering more information about what might be causing the difference in behaviour?

Cheers again..

tqb_extjs
11 Feb 2010, 12:59 AM
I've discovered that this is only a problem on Internet Explorer. Firefox works fine.

Just to recap, when the same link is placed in different locations (grid row Vs row expander panel) it results in different behaviour on Internet Explorer.

tqb_extjs
15 Feb 2010, 8:46 AM
Well the good news is that I managed to figure this out.

On the off chance that I'm not talking to myself then here's the working code...



public class GridPluginsExample extends LayoutContainer implements ValueChangeHandler<String>
{
public GridPluginsExample()
{
setLayout(new FitLayout());
History.addValueChangeHandler(this);
History.fireCurrentHistoryState();
}

@Override
protected void onRender(Element parent, int index)
{
super.onRender(parent, index);

List<ColumnConfig> configs = new ArrayList<ColumnConfig>();

RowExpander expander = new RowExpander()
{
private Set<Component> attachedComponents = new HashSet<Component>();

@Override
public void init(Component component)
{
super.init(component);

grid.addListener(Events.Detach, new Listener<GridEvent<?>>()
{
public void handleEvent(GridEvent<?> e)
{
for(Component component : attachedComponents)
{
ComponentHelper.doDetach(component);
}
}
});
}

@Override
protected boolean beforeExpand(ModelData model, Element body, El row, int rowIndex)
{
if (fireEvent(Events.BeforeExpand))
{
body.setInnerHTML("");
Hyperlink link = new Hyperlink("Test Link Expanded", "linkExpandedToken");
WidgetComponent component = new WidgetComponent(link);
component.render(body);
ComponentHelper.doAttach(component);
return true;
}
return false;
}
};
configs.add(expander);

ColumnConfig column = new ColumnConfig();
column.setHeader("Column");
column.setWidth(200);
column.setRenderer(new GridCellRenderer<ModelData>()
{
@Override
public Object render(ModelData model, String property, ColumnData config, int rowIndex, int colIndex, ListStore<ModelData> store, Grid<ModelData> grid)
{
return new Hyperlink("Test Link In Row", "linkToken");
}
});
configs.add(column);

ListStore<ModelData> store = new ListStore<ModelData>();
store.add(new BaseModelData());

Grid<ModelData> grid = new Grid<ModelData>(store, new ColumnModel(configs));
grid.setHeight(500);
grid.addPlugin(expander);
grid.getView().setAutoFill(true);

add(grid);
}

@Override
public void onValueChange(ValueChangeEvent<String> e)
{
MessageBox.info("History Event", "Token: " + e.getValue(), null);
}

}
In a nutshell I had to register this custom component to receive events. I also needed to take care to detach when done to prevent memory leaks.