Fetch data from server on scrolling in celltable gwt - gwt

I need to implement a feature in GWT which is already existing in smartgwt. In smartgwt, we can set a maximum limit of records in a grid is 75. When the record count reaches 75 while scrolling, it again requests the server and fetches another 75 records. Similar functionality I have to implement in GWT. ie, while scrolling, i have to fetch records from server for every 75 records. Is it possible?? Please assist.

You can use the ScrollPanel for check when the user reache the end of the scoll.
You can try this example of code, and adapt it to your case :
String loremIpsum = "a long text..."; // add a long text here for test
ScrollPanel sPanelTest = new ScrollPanel(loremIpsum);
sPanelTest.addScrollHandler(new ScrollHandler() {
#Override
public void onScroll(ScrollEvent event) {
int maxPosition = sPanelTest.getMaximumVerticalScrollPosition();
int currentPosition = sPanelTest.getVerticalScrollPosition();
if(currentPosition == maxPosition)
Window.alert("Tadam !"); // end of the scroll
}
});
Doc of ScrollPanel.
Another example of use.

Related

Change value of widget inside GWT flex table when other widget's value changes?

Ok, so I have a pretty specific and to me quite complicated issue, as I'm a GWT newbie.
I have a GWT flex table, which I use to dynamically add rows, whose cells contain GWT widgets. The row number changes, but the number of columns in static, always 6. Each row contains a cell with a remove button and five cells each with their own textbox.
What I need to do is somehow code a kind of relationship between the textbox in cell 6 of one row and the textbox in cell 5 in the next row (and vice versa).
To illustrate: when something changes in the textbox at [1,6] the content of textbox at [2,5] needs to be overwritten with the same value. If the textbox at [2,5] changes the textbox at [1,6] needs to change as well. I cannot use a button to commit the changes, it needs to happen via onValueChange or Blur or something similar, which doesn't require the user to perform a specific action.
My problem stems mostly from trying to figure out how to address specific cells in the flex table and their content. For the remove button the solution was easy enough with a click event handler, but for this issue I just can't seem to be able to come up with a solution.
Sadly I also cannot provide any of the code which I have up until now, since it's a business secret. I can only give a broad description of the problem like the one above.
EDIT:
Actually, it's probably more a problem of not having much code in terms of this specific problem.
What I have is a flex table, which has initially only the header row. Upon clicking a button below this table the addNewField() method is called, which just contains the creation, setting of default values and adding of the text fields into a new row.
addNewField() {
int rows = flextable.getRowCount();
Button removeBtn = new Button("x");
removeBtn.getElement().setId(Integer.toString(rows));
//then the button's event handler
TextBox name = new TextBox();
name.setText("something");
flextable.setWidget(rows, 0, "name");
//repeat 4 more times with incrementing columns for the other widgets
}
This way I add entire rows of editable TextBoxes. What I need is a way to influence the values of the 6th column TextBox of a chosen row and the 5th column TextBox of chosen row + 1.
EDIT2: I've tried the dirty option just to see how it would go and somehow the compare inside the if breaks the app. The compiler detects a nullpointerexception and I can't even debug it with breakpoints because it fails to compile and won't start. I can't figure out why though. I threw the code directly into the event for testing purposes, so pardon the ugliness.
TextBox bis = new TextBox();
bis.setText(rows + ":10:00");
subs.setWidget(rows, 5, bis);
bis.addValueChangeHandler(new ValueChangeHandler<String>()
{
#Override
public void onValueChange(ValueChangeEvent<String> event)
{
allRows: for (int i = 0; i < subs.getRowCount(); i++)
{
for (int j = 0; j < subs.getCellCount(i); j++)
{
if ( subs.getWidget(i, j) == bis )
{
TextBox widgetAtColumnSix = ((TextBox) subs.getWidget(i, 5));
String text = widgetAtColumnSix.getText();
TextBox widgetAtColumnFiveRowPlusOne = ((TextBox) subs.getWidget(i + 1, 4));
widgetAtColumnFiveRowPlusOne.setText(text);
break allRows;
}
}
}
}
});
EDIT: Since you edited your question and you dont want to use EventBus you could iterate over your FlexTable and set your TextBox value depending on your current rowIndex and cellIndex... Its not nice but it should work:
public class CellWidget extends Composite {
private TextBox nameBox;
public CellWidget() {
FlowPanel flowPanel = new FlowPanel();
Button deleteButton = new Button("x");
nameBox = new TextBox();
nameBox.addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
notifiyTextBox(CellWidget.this, event.getValue());
}
});
flowPanel.add(nameBox);
flowPanel.add(deleteButton);
initWidget(flowPanel);
}
public void setText(String text) {
nameBox.setText(text);
}
}
public void notifiyTextBox(CellWidget source, String string) {
rows: for (int i = 0; i < flextable.getRowCount(); i++) {
columns: for (int j = 0; j < flextable.getCellCount(i); j++) {
if (flextable.getWidget(i, j) == source) {
CellWidget widgetAtColumnSix = ((CellWidget) flextable.getWidget(i, 5));
widgetAtColumnSix.setText(string);
CellWidget widgetAtColumnFiveRowPlusOne = ((CellWidget) flextable.getWidget(i + 1, 4));
widgetAtColumnFiveRowPlusOne.setText(string);
break rows;
}
}
}
}
I still would recommend using an eventbus. To make it even more convenient there is the GWT Event Binder lib, which makes using events a breeze.
So when you change a value in your textbox[2,5] it also fires your CustomEvent. All Widgets, that need to change their textbox value just need to catch...

GWT CellTable rebuilding rows unnecessarily

I have found an interesting issue, and I am wondering if I am misusing or overlooking something. I have a large CellTable that is vertically scrollable. I want to show all the rows at once instead of traditional pagination. So at the bottom of my table I have a row that the user can click to load 50 more rows. I have provided the table with a custom table builder (setTableBuilder(new Builder());). When the user clicks "load more" I query the data, add to the ListDataProvider and call table.setVisibleRange(0, dataProvider.getList().size());.
I put a log statement in the
#Override
public void buildRowImpl(Object rowValue, int absRowIndex) {
}
method to see when it was building rows. I notice that it would build 0-dataProvider.getList().size() (all the rows), then it would build oldLength-dataProvider.getList().size() (the new rows). For instance, if I have 100 rows and then load 50 more it would build 0-150, and then rebuild 100-50. What I want is for it to only build the new rows, obviously.
So I start debugging to see why it is rebuilding the whole table each time. What I found was in com.google.gwt.user.cellview.client.HasDataPresenter it would set the "redrawRequired" flag to true at line 1325:
else if (range1 == null && range0 != null && range0.getStart() == pageStart
&& (replaceDiff >= oldRowDataCount || replaceDiff > oldPageSize)) {
// Redraw if the new data completely overlaps the old data.
redrawRequired = true;
}
So my question is why does it think that the new data completely overlaps the old data?
Am I using something incorrectly, is there a better way? This gets to be quite a slow down when it has to redraw thousands of rows that don't need to be redrawn.
Thanks,
Will
I think that, in this situation, the only way a CellTable can react to the call of the setVisibleRange() method is to redraw all rows.
You have just informed a CellTable that now it has to display new range (0-150 rows) instead of last (0-100 rows). There is no information that rows 0-100 remain unchanged and there is no need to redraw them.
The interesting thing is that you found the new rows are updated (rebuild) twice:
For instance, if I have 100 rows and then load 50 more it would build 0-150, and then rebuild 100-50
I've tried to reproduce this behavior in the smallest example:
public class ListDataProviderTest implements EntryPoint {
private static final int ADD_COUNT = 10;
private int nextVal = 0;
public void onModuleLoad() {
final CellTable<Integer> cellTable = new CellTable<Integer>();
cellTable.addColumn(new TextColumn<Integer>() {
#Override
public String getValue(Integer object) {
return object.toString();
}});
final ListDataProvider<Integer> listDataProvider = new ListDataProvider<Integer>();
listDataProvider.addDataDisplay(cellTable);
RootPanel.get().add(cellTable);
RootPanel.get().add(new Button("Add more...", new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
List<Integer> list = listDataProvider.getList();
for(int i = 0; i < ADD_COUNT; i++)
list.add(nextVal++);
cellTable.setVisibleRange(0, list.size());
}
}));
}
}
But I get all the rows updated once.
Can you confirm that this example reproduces the issue or provide one that is more accurate?
AFAIK a CellTable always redraws all cells.
This is how the renderer from the CellTable works. Although it always redraws all cells, it is in most times still faster than using a FlexTable and only updating a few cells.

How to create an accordion in wicket

I am using wicket 1.4.17.I went through quite a few posts on this but couldn't understand it clearly. How can I make an accordion in wicket?
Basically what I am looking for is kind of a table with 1 column and multiple rows where each row can be expanded or collapsed, and each row on expansion shows another table of data.
The following code example should help you get started.
Feel free to ask questions if something seems unclear. Of course you could go even deeper in your DetailPanel (that's why I would suggest that approach)
AbstractRepeater exampleView = new ListView<Object>("exampleView", myList) {
#Override
protected void populateItem(ListItem<Object> item) {
//you can use a own panel, fragment, etc to illustrate your detail view here
//you could also use one WebMarkupContainer for visibility - but I'd assume this will get very messy, very soon
final DetailPanel detailPanel = new DetailPanel("detailPanel", item.getModel());
detailPanel.setVisible(false);
detailPanel.setOutputMarkupPlaceholderTag(true);
item.add(detailPanel);
//add AjaxLink to switch between the visibilty of the detailView
AjaxLink<Void> detailLink = new AjaxLink<Void>("detailLink") {
#Override
public void onClick(AjaxRequestTarget target) {
detailPanel.setVisible(!detailPanel.isVisible());
target.addComponent(detailPanel);
}
};
item.add(detailLink);
}
};
add(exampleView);

GWT SimplePager LastButton issue

I am facing problem with lastButton of SimplePager.
I have 3 pages in celltable, Page size=11 (1 empty record + 10 records(with value)), Total record=26.
I used CustomerPager by extending SimplePager.
In 1st attempt 1+10 records display in celltable : Next & Last page button is enabled (First & Prev button disabled) which is correct.
But LastPage button not working... :( Dont know whats the issue... (event not fires)
Strange behavior:
#1 Last page button is working only when I visit to last page(3 page in my case).
#2 Assume I am on 1st page n I moved to 2nd page(Total 3 pages in celltable). that time all buttons are enabled which is correct.
In this case Last button is working but behave like Next Button
My GWT application integrated into one of our product so cant debug it from client side.
May be index value is improper in setPage(int index) method from AbstractPager
Code flow is as follows for Last button
//From SimplePager
lastPage.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
lastPage();
}
});
#Override
public void lastPage() {
super.lastPage();
}
// From AbstractPager
/**
* Go to the last page.
*/
protected void lastPage() {
setPage(getPageCount() - 1);
}
protected void setPage(int index) {
if (display != null && (!isRangeLimited || !display.isRowCountExact() || hasPage(index))) {
// We don't use the local version of setPageStart because it would
// constrain the index, but the user probably wants to use absolute page
// indexes.
int pageSize = getPageSize();
display.setVisibleRange(pageSize * index, pageSize);
}
}
or may be some conditions false from above code(from setPage())
actual record = 26 and 3 Empty record (1st Empty record/page)
May b problem with dataSize :|
How I can check number of pages based on the data size?
?
How can I solve this problem?
edit: I found out that the default constructor of the pager doesn't give you a "last" button, but a "fast forward 1000 lines" button instead (horrible, right?) .
call the following constructor like so, and see your problem solved:
SimplePager.Resources resources = GWT.create(SimplePager.Resources.class);
SimplePager simplePager = new SimplePager(TextLocation.CENTER, resources , false, 1000, true);
the first "false" flag turns off the "fastforward button" and the last "true" flag turns on the "last" button.
also the last button will work only if the pager knows the total amount of records you have.
you can call the table's setRowCount function to update the total like so:
int totalRecordsSize = 26; //the total amount of records you have
boolean isTotalExact = true; //is it an estimate or an exact match
table.setRowCount(totalRecordsSize , isTotalExact); //sets the table's total and updates the pager (assuming you called pager.setDisplay(table) before)
if you are working with an attached DataProvider, than all it's updateRowCount method instead (same usage).
Without seeing more of your code, this is a hard question to answer as there could be multiple places where things are going wrong.
I would make sure you call setDisplay(...) on your SimplePager so it has the data it needs calculate its ranges.
If you can't run in devmode, I recommend setting up some GWT logging in the browser (write the logs to a popup panel or something, see this discussion for an example).
I think the problem is related with condition in the setPage(). Try putting SOP before if condition or debug the code
Only added cellTable.setRowCount(int size, boolean isExact) in OnRange change method AsyncDataProvider. My problem is solved :)
protected void onRangeChanged(HasData<RecordVO> display) {
//----- Some code --------
cellTable.setRowCount(searchRecordCount, false);
//----- Some code --------
}

GWT 2.1 CellTable Shows Only Loading Bar

Following both the example from the GWT Showcase and the example found at GWT, I implemented a CellTable. The CellTable displays the first 15 results but subsequent pages only displays the loading bar. Attempting to return to the first 15 results shows only the loading bar as well. No errors in the JavaScript console or within the GWT developer console are raised.
Any help or insight that anyone can give would be greatly appreciated.
Further, I tried the following and it too suffered from the same thing happening:
List<String> stringsList = new ArrayList<String>();
for( int i = 0; i < 60; i++){
stringsList.add("" + i);
}
CellTable<String> cellTable = new CellTable();
TextColumn<String> nameColumn = new TextColumn<String>(){
#Override
public String getValue(String string){
return string;
}
};
SimplePager.Resources pagerResources = GWT.create(SimplePager.Resources.class);
SimplePager pager = new SimplePager(TextLocation.CENTER, pagerResources, false, 0, true);
pager.setDisplay(cellTable);
cellTable.addColumn(nameColumn, "App Name");
cellTable.setRowCount(stringsList.size(), true);
cellTable.setRowData(0, stringsList);
RootLayoutPanel.get().add(cellTable);
RootLayoutPanel.get().add(pager);
Why don't use a DataProvider and setList to fill the Table? Somewhere I read that this is the recommended approach and setRowData shouldn't be used (because it can cause some weird behaviour)
I think you need a data provider to push data into the cell table. Add the next code and it should work.
ListDataProvider dataProvider = new ListDataProvider();
dataProvider.setList(stringsList );
dataProvider.addDataDisplay(cellTable);
This happens when there's some problem with setVisibleRange or a similar method. I get this a lot when a list backing the data provider doesn't have enough values, or something. I recommend you trace your program to the point at which you're changing the visible range and check all the values that are going into your methods there.