Loader for SimpleComboBox - GXT - gwt

I want to create a Dynamic ComboBox i.e it fetches data from DB
On pressing some buttons(on other Panels) I want to reload the ComboBox.
ComboBox Store Datatype : List
I created an RPC call(RPCProxy) which fetches List
However I cannot create a Loader to map it to my ComboBox Store, as Loader is mapped only to a Store that Extends BeanModel instance.
So I can fetch data only once while loading, but I cant refetch data, as I cant use a loader.
Here is some part of Code:
SimpleComboBox myCombo = new SimpleComboBox();
List myStore = new ArrayList();
XX.getService().getMyDD(userData.getId(), weekOffset, new AsyncCallback<List<String>>() {
public void onFailure(
Throwable caught) {
MessageBox.alert(UIConstants.ERROR,caught.getMessage(),
null);
}
public void onSuccess(List<String> result) {
for(String str: result)
{
myStore.add(str);
}
myCombo.removeAll();
myCombo.add(myStore);
myCombo.setSimpleValue(UIConstants.ALL);
}
});
RpcProxy<List<String>> userTypeProxy = new RpcProxy<List<String>>() {
#Override
protected void load(Object loadConfig,
AsyncCallback<List<String>> callback) {
try {
System.out.println("In Loader: my: "+my);
XX.getService().getMyDD(userData.getId(), weekOffset,
callback);
} catch (Exception e) {
MessageBox.alert(UIConstants.ERROR,
UIConstants.ERROR_USER_RETRIEVED, null);
}
}
};
Please let me know if I can implement any type of loader for my ComboBox, like ListLoader etc.
I highly appreciate your help in advance.

Related

Parse query always returns an empty list

I have the following problem:
I have two Android apps: In one app I add data to Mongo DB via Parse and in the other app I want to retrieve the information added from the first app.
The problem is that in the second app everytime I try to query the DB, I get an empty list. I`ve checked with the API KEY, with the keys from the Mongo DB, and everything seems ok in my app.
Here is the code for the second app to retrieve information in a RecyclerView
public class ParseDb extends Application {
#Override
public void onCreate() {
super.onCreate();
// Enable Local Datastore.
Parse.enableLocalDatastore(this);
// Add your initialization code here
Parse.initialize(new Parse.Configuration.Builder(getApplicationContext())
.applicationId(API_KEY)
.server("http://injuriesandsuspensions.herokuapp.com/parse/")
.build()
);
ParseUser.enableAutomaticUser();
ParseACL defaultACL = new ParseACL();
// Optionally enable public read access.
defaultACL.setPublicReadAccess(true);
ParseACL.setDefaultACL(defaultACL, true);
}
public class MainActivity extends Activity {
private List<AboutTeams> aboutTeamsList = new ArrayList<AboutTeams>();
private RecyclerView recyclerView;
private GamesAdapter gamesAdapter;
public void retrieveGamesFromDatabase(){
ParseQuery<ParseObject> query = ParseQuery.getQuery("InjuriesAndSuspensions");
query.whereEqualTo("score", "none");
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> gamesList, ParseException e) {
if (e == null) {
Log.d("score", "Retrieved " + gamesList.size() + " scores");
for(int i = 0; i < gamesList.size(); i++){
AboutTeams aboutTeams = new AboutTeams();
aboutTeams.setId(String.valueOf(gamesList.get(i).getObjectId()));
aboutTeams.setScore(String.valueOf(gamesList.get(i).get("score")));
aboutTeams.setHomeTeam(String.valueOf(gamesList.get(i).get("homeTeam")));
aboutTeams.setHomeTeamMissing(String.valueOf(gamesList.get(i).get("homeTeamMissingPlayers")));
aboutTeams.setAwayTeam(String.valueOf(gamesList.get(i).get("awayTeam")));
aboutTeams.setAwayTeamMissing(String.valueOf(gamesList.get(i).get("awayTeamMissingPlayers")));
aboutTeams.setDate(String.valueOf(gamesList.get(i).get("gameDate")));
Log.d("About Teams " , aboutTeams.toString());
aboutTeamsList.add(aboutTeams);
gamesAdapter.notifyDataSetChanged();
}
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_listview);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
gamesAdapter = new GamesAdapter(aboutTeamsList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(gamesAdapter);
retrieveGamesFromDatabase();
}
Please help as I`ve been struggling with this thing for almost 3 days.
When I was adding info to the Collection DB,the ParseObject I was using didn`t have this line added where I was initializing Parse in my application:
defaultACL.setPublicReadAccess(true);
Complete code on how to initialize Parse:
public class AddToDB extends Application {
#Override
public void onCreate() {
super.onCreate();
// Enable Local Datastore.
Parse.enableLocalDatastore(this);
// Add your initialization code here
Parse.initialize(new Parse.Configuration.Builder(getApplicationContext())
.applicationId(API_KEY)
.server(SERVER_URL)
.build()
);
ParseUser.enableAutomaticUser();
ParseACL defaultACL = new ParseACL();
// Optionally enable public read access.
**defaultACL.setPublicReadAccess(true);**
ParseACL.setDefaultACL(defaultACL, true);
}
}

Dynamic DataGrid in GWT

I am trying to construct a DataGrid in GWT that will show an arbitrary dataset taken from an rpc method.
I have done some progress as I get the fields from a method and the data from another.
I have managed to construct the Datagrid and add the columns from the rpc.getFields() method and fill the table using an AsyncDataProvider.
The problem is that when I refresh the browser, it duplicates all the columns at the Datagrid. I cannot figure out what to do. I tried to remove first all the columns but no luck.
I attach the code if anyone have an idea.
public class MyCallBack implements AsyncCallback<List<Field>> {
DataGrid<Record> dg;
public MyCallBack(DataGrid<Record> dgrid) {
this.dg=dgrid;
}
public void onFailure(Throwable caught) {
Window.alert(caught.getMessage());
}
public void onSuccess(List<Field> result) {
for (int i=0;i<=result.size();i++) {
IndexedColumn ic = new IndexedColumn(i);
dg.addColumn(ic, result.get(i).getLabel());
}
}
public AsyncCallback<List<Field>> getCb() {
return this;
}
public void onModuleLoad() {
final DataGrid<Record> dg = new DataGrid<Record>();
MyCallBack mcb = new MyCallBack(dg);
DataProvider dp = new DataProvider();
DBConnectionAsync rpcService = (DBConnectionAsync) GWT.create(DBConnection.class);
ServiceDefTarget target = (ServiceDefTarget) rpcService;
String moduleRelativeURL = GWT.getModuleBaseURL() + "MySQLConnection";
target.setServiceEntryPoint(moduleRelativeURL);
rpcService.getFields(mcb.getCb());
dp.addDataDisplay(dg);
dg.setVisibleRange(0, 200);
SplitLayoutPanel slp = new SplitLayoutPanel();
slp.setHeight("700px");
slp.setWidth("1500px");
slp.addWest(dg, 770);
RootPanel.get().add(slp);
}
When you refresh a browser, all UI is lost. There is no difference between (a) show the UI for the first time or (b) show the UI after browser refresh.
Your comment "Only if I restart tomcat it works" suggests that the problem is on the server side. Most likely, you return twice the number of data points on a second call.
Try clearing the table before filling it like this:
public void onSuccess(List<Field> result) {
clearTable();
for (int i=0;i<=result.size();i++) {
IndexedColumn ic = new IndexedColumn(i);
dg.addColumn(ic, result.get(i).getLabel());
}
}
private void clearTable(){
while (dg.getColumnCount() > 0) {
db.removeColumn(0);
}
}

Gwt Simple pager issues with a column sort handler

I have set up an AsyncDataProvider for my CellTable and added it to a SimplePager. I have hooked up a ListHandler to take care of sorting based on a column.
When I click the header of that column, the data doesn't change but on going to the next/previous page within the pager the data is then sorted. Also before the column is clicked there is no visual indicator on the column that would indicate that it is meant to be sortable.
How can I get the data to update when I click the header of the Column?
Here's my code snippet
service.getHosts(environment, new AsyncCallback<Set<String>>() {
#Override
public void onSuccess(final Set<String> hosts) {
final List<String> hostList = new ArrayList<String>(hosts);
//Populate the table
CellTable<String> hostTable = new CellTable<String>();
TextColumn<String> hostNameColumn = new TextColumn<String>(){
#Override
public String getValue(String string){
return string;
}
};
NumberCell numberCell = new NumberCell();
Column<String, Number> lengthColumn = new Column<String, Number>(numberCell){
#Override
public Number getValue(String string) {
return new Integer(string.length());
}
};
AsyncDataProvider<String> dataProvider = new AsyncDataProvider<String>() {
#Override
protected void onRangeChanged(HasData<String> data) {
int start = data.getVisibleRange().getStart();
int end = start + data.getVisibleRange().getLength();
List<String> subList = hostList.subList(start, end);
updateRowData(start, subList);
}
};
// Hooking up sorting
ListHandler<String> columnSortHandler = new ListHandler<String>(hostList);
columnSortHandler.setComparator(lengthColumn, new Comparator<String>(){
#Override
public int compare(String arg0, String arg1) {
return new Integer(arg0.length()).compareTo(arg1.length());
}
});
hostTable.setPageSize(10);
hostTable.addColumnSortHandler(columnSortHandler);
hostTable.addColumn(hostNameColumn,"Host Name");
lengthColumn.setSortable(true);
hostTable.addColumn(lengthColumn, "Length");
VerticalPanel verticalPanel = new VerticalPanel();
SimplePager pager = new SimplePager();
pager.setDisplay(hostTable);
dataProvider.addDataDisplay(hostTable);
dataProvider.updateRowCount(hosts.size(), true);
verticalPanel.add(hostTable);
verticalPanel.add(pager);
RootPanel.get().add(verticalPanel);
}
#Override
public void onFailure(Throwable throwable) {
Window.alert(throwable.getMessage());
}
});
I'm not sure how to make sure that the list is shared by both the table and the Pager. Before adding the pager I was using
ListDataProvider<String> dataProvider = new ListDataProvider<String>();
ListHandler<String> columnSortHandler = new ListHandler<String>(dataProvider.getList());
The AsyncDataProvider doesn't have the method getList.
To summarize I want the data to be sorted as soon as the column is clicked and not after I move forward/backward with the pager controls.
As per the suggestion I have changed the code for the AsyncDataProvider to
AsyncDataProvider<String> dataProvider = new AsyncDataProvider<String>() {
#Override
protected void onRangeChanged(HasData<String> data) {
int start = data.getVisibleRange().getStart();
int end = start + data.getVisibleRange().getLength();
List<String> subList = hostList.subList(start, end);
// Hooking up sorting
ListHandler<String> columnSortHandler = new ListHandler<String>(hostList);
hostTable.addColumnSortHandler(columnSortHandler);
columnSortHandler.setComparator(lengthColumn, new Comparator<String>(){
#Override
public int compare(String v0, String v1) {
return new Integer(v0.length).compareTo(v1.length);
}
});
updateRowData(start, subList);
}
};
But there is no change in the behavior even after that. Can someone please explain the process. The GWT showcase app seems to have this functionality but how they've done it isn't all that clear.
When using an AsyncDataProvider both pagination and sorting are meant to be done on the server side. You will need an AsyncHandler to go with your AsyncDataProvider:
AsyncHandler columnSortHandler = new AsyncHandler(dataGrid) {
#Override
public void onColumnSort(ColumnSortEvent event) {
#SuppressWarnings("unchecked")
int sortIndex = dataGrid.getColumnIndex((Column<Entry, ?>) event.getColumn());
boolean isAscending = event.isSortAscending();
service.getPage(0, sortIndex, isAscending, new AsyncCallback<List<Entry>>() {
public void onFailure(Throwable caught) {
}
public void onSuccess(List<Entry> result) {
pager.setPage(0);
provider.updateRowData(0, result);
}
});
}
};
dataGrid.addColumnSortHandler(columnSortHandler);
Clicking on a column header will then fire a columnSortEvent. Then you have to get the column clicked. I am overloading my servlet to provide both sorting and pagination, so I pass a -1 for the column index when only pagination is desired.
provider = new AsyncDataProvider<Entry>() {
#Override
protected void onRangeChanged(HasData<Entry> display) {
final int start = display.getVisibleRange().getStart();
service.getPage(start, -1, true, new AsyncCallback<List<Entry>>() {
#Override
public void onFailure(Throwable caught) {
}
#Override
public void onSuccess(List<Entry> result) {
provider.updateRowData(start, result);
}
});
}
};
provider.addDataDisplay(dataGrid);
provider.updateRowCount(0, true);
Then your servlet implementation of getPage performs the sorting and pagination. The whole thing is much easier to follow with separate event handlers.
I think the problem is with the ListHandler initialization. You are passing hostList as a parameter to List Handler and in onRangeChange method you are calling updateRowData with a different list (sublist).
Make sure you use the same list in both the places.
or
Move your ListHander initialization and cellTable.addColumnSortHandler method call to onRangeChange method after updateRowData call.

GWT new EntityProxy in #OneToOne with another EntityProxy from server

I am just creating a new Proxy:
LayoutExampleRequest r = requestFactory.employeeRequest();
DepartmentProxy d = r.create(DepartmentProxy.class);
r.save(d);
departmentEditor.editProxy(d, r);
Then pass the Proxy and the Request(LayoutExampleRequest ) to my editor
driver.edit(proxy, request);
Until here ! everything works as espected. I can save Department objects with null EmployeeProxy. Now iam getting with a suggest box Proxys of EmployeeProxy from the server.
search = new SuggestBox(new SuggestOracle() {
#Override
public void requestSuggestions(final Request request,final Callback callback) {
System.out.println(request.getQuery());
//ignore less than 3
if(request.getQuery().length() > 3){
requestFactory.employeeRequest().search(request.getQuery()).fire(new Receiver<List<EmployeeProxy>>(){
#Override
public void onSuccess(List<EmployeeProxy> response) {
List<MySuggestion<EmployeeProxy>> suggestions = new ArrayList<MySuggestion<EmployeeProxy>>();
for(EmployeeProxy e:response){
MySuggestion<EmployeeProxy> suggestion = new MySuggestion<EmployeeProxy>();
suggestion.setModel(e,e.getFirstName(),e.getFirstName()+" "+e.getLastName());
suggestions.add(suggestion);
}
callback.onSuggestionsReady(request, new Response(suggestions));
}
});
}
}
});
MySuggestion is a wrapper class to handle the EmployeeProxy.
Now i want to add this EmployeeProxy to my DeparmentProxy since i have a #OneToOne on JPA.
search.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>() {
#Override
public void onSelection(SelectionEvent<Suggestion> event) {
MySuggestion<EmployeeProxy> s = (MySuggestion<EmployeeProxy>)event.getSelectedItem();
proxy.setSupervisor(s.getModel());
}
});
proxy is the EntityProxy for Department (I sent to my editor) driver.edit(proxy, request);
then i fire the driver:
departmentEditor.getDriver().flush().fire(new Receiver<Void>() {
#Override
public void onSuccess(Void response) {
Window.alert("Success");
// refresh the datagrid
Range range = dataGrid.getVisibleRange();
dataGrid.setVisibleRangeAndClearData(range, true); //1st way
// create a new DepartmentProxy to bind to the Editor.
createProxy();
// change button text
updateButton.setText("Save");
}
#Override
public void onConstraintViolation(Set<ConstraintViolation<?>> violations) {
for(ConstraintViolation v :violations){
Window.alert(v.getMessage()+" "+v.getPropertyPath());
}
}
#Override
public void onFailure(ServerFailure error) {
Window.alert(error.getMessage());
}
});
The problem is iam getting ConstraintViolations from the EmployeeProxy, is like the driver atach the EmployeeProxy but with null values.
(Iam validating my Entityes with JSR-330 )
Dont know how to make a relationship with a new Proxy with other taked from the server. in a #OneToOne relationship
Any help would be nice!
Thank you
/* UPDATE */
Something like this but with editor
final LayoutExampleRequest r = requestFactory.employeeRequest();
final DepartmentProxy d = r.create(DepartmentProxy.class);
d.setName("Name");
d.setService(Service.CONTRACT_MANAGMENT);
// get some random employee
requestFactory.employeeRequest().findById(1).fire(new Receiver<EmployeeProxy>() {
#Override
public void onSuccess(EmployeeProxy response) {
d.setSupervisor(response);
r.save(d).fire(new Receiver<DepartmentProxy>() {
#Override
public void onSuccess(DepartmentProxy response) {
Window.alert("Kidding me! why editor cant get it work =p?");
}
});
}
});
The problem was i put on my editor properties of the EmployeeProxy so when a user select the employeproxy would see information about it, so i delete them and then do the same and now works.
Is like GWT when detects properties from another proxy on the editor thinks you will fill it. And the line:
proxy.setSupervisor(s.getModel());
doesn't works.

How to reload data rows in GXT grid?

Assuming that data retrieves from DataStore using RPCproxy, populate to grid using ListStore upon opening the page.
Then, there's a form to add an entity and after modification it will reflect the new list in GXT grid with the new added row.
How can reload the grid? I tried .reconfigure() method in Grid but didn't work.
grid.getStore().getLoader().load();
update:
First of all you must extract Grid before your Proxy, and the second thing is to change your RPC callback:
public class PagingBeanModelGridExample extends LayoutContainer {
//put grid Class outside a method or declare it as a final on the begin of a method
Grid grid = null;
protected void onRender(Element parent, int index) {
super.onRender(parent, index);
RpcProxy> proxy = new RpcProxy>() {
#Override
public void load(Object loadConfig, final AsyncCallback> callback) {
//modification here - look that callback is overriden not passed through!!
service.getBeanPosts((PagingLoadConfig) loadConfig, new AsyncCallback>() {
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
public void onSuccess(PagingLoadResult result) {
callback.onSuccess(result);
//here you are reloading store
grid.getStore().getLoader().load();
}
});
}
};
// loader
final BasePagingLoader> loader = new BasePagingLoader>(proxy, new BeanModelReader());
ListStore store = new ListStore(loader);
List columns = new ArrayList();
//...
ColumnModel cm = new ColumnModel(columns);
grid = new Grid(store, cm);
add(grid);
}
}
To display the new data to grid do you really need to reload the grid?
You can create a new model object with the new data and add this to the ListStore.
Suppose you have a CommentModel which extends the BaseModel and a ListStore of Comment model commentStore.
final ListStore<Commentmodel> commentStore = new ListStore<Commentmodel>();
//now call a rpc to load all available comments and add this to the commentStore.
commentService.getAllComment(new AsyncCallback<List<Commentmodel>>() {
#Override
public void onFailure(Throwable caught) {
lbError.setText("data loading failure");
}
#Override
public void onSuccess(List<Commentmodel> result) {
commentStore.add(result);
}
});
commentService is an AsyncService.
Now if a user post a comment, just create a new CommentModel object with the new data
CommentModel newData = new CommentModel('user name', 'message','date');
And add this to the commentStore.
commentStore.add(newData);
Hope this will serve you purpose.
But if you really need to reload the whole set of data, call the service again. In the onSuccess method first clear the commentStore then add result. Remember this is more more time consuming that the 1st approach.