There is a <p:selectOneListbox> with about 20 items. The first 5 items can be viewed in the list and then the remaining can be scrolled to and selected. The list is ajaxified. When the item numbers greater than 5 is selected (after scrolling to it) the scrollbar does not remain at its place; it moves to the top position. This makes the selected item (for example item 9) invisible. The program uses a ajax listener. The app uses PrimeFaces 5.0.
But, when the ajax listener is removed the selected (item 9) is visible and the scroller does not move to top (remove the p:ajax tag's listener attribute in the below JSF page).
I would like to know how to make the scrollbar not move when any item is selected while using the ajax listener.
The JSF page:
<p:selectOneListbox id="list"
scrollHeight="100"
value="#{bean.todo}">
<f:selectItems value="#{bean.data}"
var="t"
itemLabel="#{t.name}"
itemValue="#{t.name}"/>
<p:ajax process="#this"
update="#this msg"
listener="#{bean.valueChanged}" />
</p:selectOneListbox>
<br /><h:outputText id="msg" value="#{bean.message}" />
The bean's code:
import javax.faces.bean.*;
import java.io.Serializable;
import java.util.*;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.component.UIOutput;
#ManagedBean(name="bean")
#SessionScoped
public class TodosBean implements Serializable {
private List<Todo> data;
private String todo; // selected item value
private String msg;
public TodosBean() {
loadData();
if (data.size() == 0) {
return;
}
Todo t = data.get(0);
String name = t.getName();
setTodo(name); // select the first item in the list
setMessage(name);
}
private void loadData() {
data = new ArrayList<>();
data.add(new Todo("1first", "1"));
data.add(new Todo("2second", "2"));
data.add(new Todo("3third", "3"));
data.add(new Todo("4fourth", "4"));
data.add(new Todo("5fifth", "5"));
data.add(new Todo("6sixth", "6"));
data.add(new Todo("7seventh", "7"));
data.add(new Todo("8eighth", "8"));
}
public List<Todo> getData() {
return data;
}
public void setMessage(String msg) {
this.msg = msg;
}
public String getMessage() {
return msg;
}
public String getTodo() {
return todo;
}
public void setTodo(String t) {
todo = t;
}
public void valueChanged(AjaxBehaviorEvent e) {
String name = (String) ((UIOutput) e.getSource()).getValue();
setMessage(name + " selected.");
}
}
public class Todo {
private String name;
private String desc;
public Todo() {}
public Todo(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
#Override
public String toString() {
return this.name;
}
}
Remove the update="#this will solve it. Updating a control will move it to a default state. It might also be that in a newer version of PF this default state is improved and it still is at the correct position
Related
I've a dataTable within a dataTable. The initial dataTable has a list of components that appear on the page. One of these components will be a list of strings which can have elements added or deleted. When I change a string in this list, I expect the value to show up in the bean and it is not.
Below I have an example of my problem. The page renders a text input field for the first component then three text input fields to represent the second component which is a list of three input fields.
I have valueChange listener on all the input fields. The listener, is in the InnerBean class, prints out the source and the value that changed.
For the standalone input field, the listener correctly prints out the changed value and shows that the bean has been updated with this value. For any of the input fields from the list, the listener prints out the previous value of the input field and the bean has not been updated. On the ajax update of the inner datatable, the changed value is replace with the original value.
Since the valueChange listener is called, it appears that Primefaces knows that the value has changed. The code just doesn't seem to record the changed value.
Any help is appreciated.
I'm using Primefaces 8.0 and JSF 2.2.20.
Here is the xhtml:
<p:panel id="testPanel" header="#{myController.outerBean.name}" toggleable="true" collapsed="false" >
<p:dataTable id="testTable" value="#{myController.outerBean.innerBeanList}" var="bean">
<p:column >
<!-- TEXT COMPONENT-->
<h:panelGroup rendered="#{bean.type eq 'text'}" >
<p:inputText id="textfield" value="#{bean.value}" style="width:100%;" >
<p:ajax event="valueChange" listener="#{bean.textListListener}" update="testTable" />
</p:inputText>
</h:panelGroup>
<!-- LIST COMPONENT -->
<h:panelGroup rendered="#{bean.type eq 'textlist'}" >
<p:dataTable id="testListTable" styleClass="datatableWithoutBorder" style="width:320px"
var="textAddition" value="#{bean.list}" rowIndexVar="rowIndex" >
<p:column >
<p:inputText id="textAdd" value="#{textAddition}" style="width: 100%;">
<p:ajax event="valueChange" listener="#{bean.textListListener}" update="testListTable"/>
</p:inputText>
</p:column>
</p:dataTable>
</h:panelGroup>
</p:column>
</p:dataTable>
<h:panelGrid columns="1" style="width:100%;">
<h:panelGroup style="float:right">
<p:commandButton id="submitBtn" value="Submit"
action="#{dummyController.submit}"
update="messages #this"
icon="fa fa-save"/>
</h:panelGroup>
</h:panelGrid>
</p:panel>
My controller code:
public class MyController {
private OuterBean outerBean;
public MyController() {
System.out.println("MyController instantiated");
setOuterBean(new OuterBean());
}
public void submit() {
for (InnerBean ab: outerBean.getInnerBeanList()) {
System.out.println(ab.getLabel() + ": " + ab.getValue() + ":" + ab.getList() );
}
}
public void clear() {
// TODO
}
// Getter/Setter methods
public OuterBean getOuterBean() {
return outerBean;
}
public void setOuterBean(OuterBean outerBean) {
this.outerBean = outerBean;
}
}
My OuterBean with the list of components:
public class OuterBean implements Serializable {
private String name;
private String value;
private List<InnerBean> innerBeanList;
public OuterBean() {
name = "Entry Panel #1";
value = "";
innerBeanList = new ArrayList<InnerBean>();
InnerBean ab1 = new InnerBean();
ab1.setLabel("First Component");
ab1.setType("text");
ab1.setValue("Input text");
innerBeanList.add(ab1);
InnerBean ab2 = new InnerBean();
ab2.setLabel("Second Component");
ab2.setType("textlist");
ArrayList<String> list = new ArrayList<String>();
list.add("Item 1");
list.add("Item 2");
list.add("Item 3");
ab2.setList(list);
innerBeanList.add(ab2);
}
//
// Getter/Setters
//
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public List<InnerBean> getInnerBeanList() {
return innerBeanList;
}
public void setInnerBeanList(List<InnerBean> innerBeanList) {
this.innerBeanList = innerBeanList;
}
}
My InnerBean which represents a component to be render. One of which can be a list of strings:
public class InnerBean implements Serializable {
// Type of component
public static final String TEXT = "text";
public static final String TEXTLIST = "textlist";
private String label;
private String type; // If TEXT, use value; if TEXTLIST, use list.
private String value;
private List<String> list = new ArrayList<String>();
public InnerBean() {
}
public void textListListener(AjaxBehaviorEvent event) {
System.out.println("Listener called");
System.out.println(" Source: " + event.getSource().toString());
System.out.println(" Value: " + ((UIInput)event.getSource()).getValue());
System.out.println(" List: " + list.toString());
System.out.println(" Event: " + event.toString());
}
//
// Setters and getters
//
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
}
I'm attempting to implement lazy loading into my application with sorting, but am having little issues with sorting and paginator. SortBy does work so like Paginator single but when i click on sort on first column with page > 0, the LazyDataModel#load is called with "first" parameter = 0!
Then instead of sorting data of page 1 return on page 0
Here is my managed bean class code:
#ViewScoped
#ManagedBean
public class PlayerMB implements Serializable {
private static final long serialVersionUID = 1L;
private LazyDataModel<Player> players = null;
private int sizePlayer;
private Player player;
public LazyDataModel<Player> getAllPlayers() {
if (players == null) {
players = new PlayerLazyList();
}
setSizePlayer(players.getRowCount());
return players;
}
public Player getPlayer() {
if(player == null){
player = new Player();
}
return player;
}
public void setPlayer(Player player) {
this.player = player;
}
public int getSizePlayer()
{
return sizePlayer;
}
public void setSizePlayer(int sizePlayer) {
this.sizePlayer = sizePlayer;
}
}
Player class code:
public class Player implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
#Override
public int hashCode() {
return getId();
}
#Override
public boolean equals(Object obj) {
if(obj instanceof Player){
Player player = (Player) obj;
return player.getId() == getId();
}
return false;
}
/*public int sortByModel(Object player1, Object player2)
{
return ((Player) player1).getName().compareTo(((Player) player2).getName());
}*/
}
dataTable.xhtml:
<f:view>
<h:form>
<p:dataTable id="lazyDataTable"
value="#{playerMB.allPlayers}"
var="player" paginator="true"
rows="10"
selection="#{playerMB.player}"
selectionMode="single"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15"
style="width: 80%;margin-left: 10%;
margin-right: 10%;"
lazy="true">
<f:facet name="header">List of players</f:facet>
<p:ajax event="rowSelect" update=":playerDialogForm" oncomplete="PF('playerDetails').show();" />
<p:ajax event="page"
listener="#{playerMB.casePage}"/>
<p:column sortBy="#{player.name}" headerText="Name" > <!-- sortBy does not work with lazyDataTable but more work occurs-->
<h:outputText value="#{player.name}" />
</p:column>
<p:column sortBy="#{player.age}" headerText="Age">
<h:outputText value="#{player.age}" />
</p:column>
<f:facet name="footer">tot: #{playerMB.sizePlayer}</f:facet>
</p:dataTable>
</h:form>
PlayerLazyList class code who extends LazyDataModel
public class PlayerLazyList extends LazyDataModel<Player> {
//private int pagina;
#Override
public List<Player> load(int first, int pageSize, String sortField,
SortOrder sortOrder, Map<String, Object> filters) {
List<Player> allplayers = CreatePlayers.players; //here load all Player
System.out.println("first =" + first + "; pagesize =" + pageSize + "; sortField = " + sortField);
players = CreatePlayers.getPlayers(first, pageSize,allplayers.size()); //here load player from "first" for "max" element
if (sortField != null && sortField.equals("name") && sortOrder.name().equals("ASCENDING"))
Collections.sort(players, new NamePlayerComparatorAsc());
if (sortField != null && sortField.equals("name") && sortOrder.name().equals("DESCENDING"))
Collections.sort(players, new NamePlayerComparatorDesc());
System.out.println("size dopo" + players.size());
// set the total of players
if(getRowCount() <= 0){
//setRowCount(playerDAO.countPlayersTotal());
setRowCount(allplayers.size());
}
// set the page dize
setPageSize(pageSize);
return players;
}
private static final long serialVersionUID = 1L;
private List<Player> players;
//private MyTransaction transaction;
#Override
public Object getRowKey(Player player) {
return player.getId();
}
#Override
public Player getRowData(String playerId) {
Integer id = Integer.valueOf(playerId);
for (Player player : players) {
if(id.equals(player.getId())){
return player;
}
}
return null;
}
}
Primefaces 5.2, Wildfly 8.2.0, Mojarra 2.2.8
You seem to expect it sorts just the page you are on. That is just not how it works. It works perfectly and as designed and as expected by (almost) everybody (that is everybody but you). It sorts the full possible resultset. All items that were on page 0 will now most likely be spread over several other pages. So staying on the newly populalted page 1 totally does not make any sense.
The behaviour you describe can be seen in the showcase to iirc
I have a TabPane where users enter/edit data on each tab and can freely switch between tabs without having to save changes before switching to a new tab. One tab has a TableView, and I'd like to prevent users from leaving that tab if they enter invalid data. My original approach was along the same lines as this question, which does not quite work - the tab is not reliably changed back. I liked James_D's answer and tried to implement something similar. However, most of the time the data being entered into a table is optional, so disabling other tabs until a user enters data is not an option.
What I ultimately did was extend TableColumn to add a BooleanProperty 'invalid' which I then bind to Tab's disableProperty. In that column's commit event, I validate the new value and, if it doesn't pass, set invalid = true, which disables the appropriate tab. This also does not quite work. I have custom table cells that commit edits on loss of focus. If focus is lost to clicking a different tab, the commit event is too late - the tab is first selected, then disabled. I've been wracking my brain for a workaround, but am out of ideas. If anyone has any suggestions, I would really appreciate it!
Short example (clear out any last name and click Tab 2):
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TabPaneTableTest extends Application {
#Override
public void start(Stage primaryStage) {
TableView<Person> table = new TableView<>();
ObservableList<Person> data = FXCollections.observableArrayList();
table.setEditable(true);
MyTableColumn<Person, String> firstNameCol = new MyTableColumn<>("First Name");
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
MyTableColumn<Person, String> lastNameCol = new MyTableColumn<>("Last Name");
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
Callback<TableColumn<Person, String>, TableCell<Person, String>> cellFactory = (TableColumn<Person, String> p) -> new MyEditingCell<Person>();
firstNameCol.setCellFactory(cellFactory);
lastNameCol.setCellFactory(cellFactory);
firstNameCol.setOnEditCommit((CellEditEvent<Person, String> event) -> {
event.getRowValue().setFirstName(event.getNewValue());
});
lastNameCol.setOnEditCommit((CellEditEvent<Person, String> event) -> {
if(event.getNewValue().trim().isEmpty()) {
new Alert(AlertType.ERROR, "Last name must be filled out!", ButtonType.OK).showAndWait();
lastNameCol.setInvalid(true);
}
else {
event.getRowValue().setLastName(event.getNewValue());
lastNameCol.setInvalid(false);
}
});
table.getColumns().addAll(firstNameCol, lastNameCol);
table.setItems(data);
data.add(new Person("Luke", "Skywalker"));
data.add(new Person("Han", "Solo"));
data.add(new Person("R2", "D2"));
TabPane tabPane = new TabPane();
Tab tab1 = new Tab("Tab 1");
tab1.setClosable(false);
tab1.setContent(table);
Tab tab2 = new Tab("Tab 2");
tab2.setClosable(false);
tab2.disableProperty().bind(lastNameCol.invalidProperty());
tabPane.getTabs().addAll(tab1, tab2);
Scene scene = new Scene(tabPane, 400, 200);
primaryStage.setTitle("Tab Pane Table Validation Test");
primaryStage.setScene(scene);
primaryStage.show();
}
public class MyEditingCell<S> extends TableCell<S, String> {
private TextField editingField;
private void createEditingField() {
editingField = new TextField(getString());
editingField.focusedProperty().addListener((ov, oldValue, newValue) -> {
if(!newValue) {
commitEdit(editingField.getText());
}
});
}
#Override
public void startEdit() {
super.startEdit();
createEditingField();
setText(null);
setGraphic(editingField);
Platform.runLater(() -> {
editingField.requestFocus();
editingField.selectAll();
});
}
#Override
public void cancelEdit() {
super.cancelEdit();
setText((String)getItem());
setGraphic(null);
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if(empty) {
setText(null);
setGraphic(null);
}
else {
if(isEditing()) {
if(editingField != null) {
editingField.setText(getString());
}
setText(null);
setGraphic(editingField);
}
else {
setText(getString());
setGraphic(null);
}
}
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
}
public class MyTableColumn<S, T> extends TableColumn<S, T> {
private BooleanProperty invalid = new SimpleBooleanProperty(false);
public MyTableColumn(String header) {
super(header);
setEditable(true);
}
public BooleanProperty invalidProperty() {
return invalid;
}
public boolean getInvalid() {
return invalid.get();
}
public void setInvalid(boolean value) {
invalid.set(value);
}
}
public class Person {
private StringProperty firstName;
private StringProperty lastName;
public Person(String first, String last) {
firstName = new SimpleStringProperty(this, "firstName", first);
lastName = new SimpleStringProperty(this, "lastName", last);
}
public void setFirstName(String value) {
firstNameProperty().set(value);
}
public String getFirstName() {
return firstNameProperty().get();
}
public StringProperty firstNameProperty() {
if(firstName == null)
firstName = new SimpleStringProperty(this, "firstName", "First");
return firstName;
}
public void setLastName(String value) {
lastNameProperty().set(value);
}
public String getLastName() {
return lastNameProperty().get();
}
public StringProperty lastNameProperty() {
if(lastName == null)
lastName = new SimpleStringProperty(this, "lastName", "Last");
return lastName;
}
}
public static void main(String[] args) {
launch(args);
}
}
If you create your observable list with an extractor, for example:
ObservableList<Person> data = FXCollections.observableArrayList(person ->
new Observable[] { person.lastNameProperty() });
then the list will fire update notifications any time any of the specified properties change in any of the elements (in this case, any time the lastName changes on anything in the list).
So now you can create a binding for invalid:
BooleanBinding invalid = Bindings.createBooleanBinding(
() -> data.stream().anyMatch(person -> person.getLastName().isEmpty()),
data);
And then you can just observe that binding:
invalid.addListener((obs, wasInvalid, isNowInvalid) -> {
if (isNowInvalid) {
// show alert, etc...
}
});
or disable a node by binding to it:
someNode.disableProperty().bind(invalid);
You could similarly bind this invalid property in your TableColumn subclass (if you still need that) to this binding.
I do have a page, where I have a list of rich:collapsiblePanel that hold input elements. These collapsiblePanels themselves store their expanded/collapsed state within a backing bean.
Now I have the use case to Open/Close all of these collapsiblePanels at once, with one mouse click. So I have tried to achieve this with the two commandButtons over the list. These use the attached actionListener to iterate over all backing beans of the collapsiblePanels and set the expanded flag to true/false.
This seems to work, unless you Open or Close one of the collapsiblePanels on their own. As soon as that happens clicking the buttons does not do anything anymore.
<h:form prependId="false">
<a4j:commandButton value="Open All" actionListener="#{viewBean.doOpenAll}" render="c" />
<a4j:commandButton value="Close All" actionListener="#{viewBean.doCloseAll}" render="c" style="margin-left: 10px;" />
<a4j:outputPanel id="c">
<a4j:repeat id="repeat" value="#{viewBean.items}" var="item">
<rich:collapsiblePanel id="panel" expanded="#{item.expanded}">
<h:outputLabel id="text_lbl" value="text" />
<h:inputText id="text" value="#{item.text}" />
</rich:collapsiblePanel>
</a4j:repeat>
</a4j:outputPanel>
</h:form>
I have published a project on github so that you can try around with the code.
For completeness here are the two backing beans
#ViewScoped
#ManagedBean
public class ViewBean implements Serializable {
static final Logger LOG = LoggerFactory.getLogger(ViewBean.class);
private static final long serialVersionUID = -6239437588285327644L;
private List<ListItem> items;
public ViewBean() {
items = new ArrayList<ListItem>(10);
for (int i = 0; i < 10; i++) {
items.add(new ListItem("item " + i));
}
}
public void doOpenAll() {
LOG.debug("open all");
for (ListItem item : items) {
item.setExpanded(true);
}
}
public void doCloseAll() {
LOG.debug("close all");
for (ListItem item : items) {
item.setExpanded(false);
}
}
public List<ListItem> getItems() {
return items;
}
}
public class ListItem {
private boolean expanded;
private String text;
public ListItem(String text) {
super();
this.text = text;
}
public boolean isExpanded() {
return expanded;
}
public void setExpanded(boolean expanded) {
this.expanded = expanded;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
This may be related to this RichFaces bug?!: https://issues.jboss.org/browse/RF-11546
Hi I'm trying to retrieve a linkedhashset from the Google datastore but nothing seems to happen. I want to display the results in a Grid using GWT on a page. I have put system.out.println() in all the classes to see where I go wrong but it only shows one and I don't recieve any errors. I use 6 classes 2 in the server package(ContactDAOJdo/ContactServiceImpl) and 4 in the client package(ContactService/ContactServiceAsync/ContactListDelegate/ContactListGui). I hope someone can explain why this isn't worken and point me in the right direction.
public class ContactDAOJdo implements ContactDAO {
#SuppressWarnings("unchecked")
#Override
public LinkedHashSet<Contact> listContacts() {
PersistenceManager pm = PmfSingleton.get().getPersistenceManager();
String query = "select from " + Contact.class.getName();
System.out.print("ContactDAOJdo: ");
return (LinkedHashSet<Contact>) pm.newQuery(query).execute();
}
}
public class ContactServiceImpl extends RemoteServiceServlet implements ContactService{
private static final long serialVersionUID = 1L;
private ContactDAO contactDAO = new ContactDAOJdo() {
#Override
public LinkedHashSet<Contact> listContacts() {
LinkedHashSet<Contact> contacts = contactDAO.listContacts();
System.out.println("service imp "+contacts);
return contacts;
}
}
#RemoteServiceRelativePath("contact")
public interface ContactService extends RemoteService {
LinkedHashSet<Contact> listContacts();
}
public interface ContactServiceAsync {
void listContacts(AsyncCallback<LinkedHashSet <Contact>> callback);
}
public class ListContactDelegate {
private ContactServiceAsync contactService = GWT.create(ContactService.class);
ListContactGUI gui;
void listContacts(){
contactService.listContacts(new AsyncCallback<LinkedHashSet<Contact>> () {
public void onFailure(Throwable caught) {
gui.service_eventListContactenFailed(caught);
System.out.println("delegate "+caught);
}
public void onSuccess(LinkedHashSet<Contact> result) {
gui.service_eventListRetrievedFromService(result);
System.out.println("delegate "+result);
}
});
}
}
public class ListContactGUI {
protected Grid contactlijst;
protected ListContactDelegate listContactService;
private Label status;
public void init() {
status = new Label();
contactlijst = new Grid();
contactlijst.setVisible(false);
status.setText("Contact list is being retrieved");
placeWidgets();
}
public void service_eventListRetrievedFromService(LinkedHashSet<Contact> result){
System.out.println("1 service eventListRetreivedFromService "+result);
status.setText("Retrieved contactlist list");
contactlijst.setVisible(true);
this.contactlijst.clear();
this.contactlijst.resizeRows(1 + result.size());
int row = 1;
this.contactlijst.setWidget(0, 0, new Label ("Voornaam"));
this.contactlijst.setWidget(0, 1, new Label ("Achternaam"));
for(Contact contact: result) {
this.contactlijst.setWidget(row, 0, new Label (contact.getVoornaam()));
this.contactlijst.setWidget(row, 1, new Label (contact.getVoornaam()));
row++;
System.out.println("voornaam: "+contact.getVoornaam());
}
System.out.println("2 service eventListRetreivedFromService "+result);
}
public void placeWidgets() {
System.out.println("placewidget inside listcontactgui" + contactlijst);
RootPanel.get("status").add(status);
RootPanel.get("contactlijst").add(contactlijst);
}
public void service_eventListContactenFailed(Throwable caught) {
status.setText("Unable to retrieve contact list from database.");
}
}
It could be the query returns a lazy list. Which means not all values are in the list at the moment the list is send to the client. I used a trick to just call size() on the list (not sure how I got to that solution, but seems to work):
public LinkedHashSet<Contact> listContacts() {
final PersistenceManager pm = PmfSingleton.get().getPersistenceManager();
try {
final LinkedHashSet<Contact> contacts =
(LinkedHashSet<Contact>) pm.newQuery(Contact.class).execute();
contacts.size(); // this triggers to get all values.
return contacts;
} finally {
pm.close();
}
}
But I'm not sure if this is the best practice...