![JAR search and dependency download from the Maven repository](/logo.png)
com.github.bordertech.wcomponents.examples.repeater.RepeaterExampleWithStaticIDs Maven / Gradle / Ivy
package com.github.bordertech.wcomponents.examples.repeater;
import com.github.bordertech.wcomponents.Action;
import com.github.bordertech.wcomponents.ActionEvent;
import com.github.bordertech.wcomponents.AjaxTarget;
import com.github.bordertech.wcomponents.HeadingLevel;
import com.github.bordertech.wcomponents.Margin;
import com.github.bordertech.wcomponents.Request;
import com.github.bordertech.wcomponents.Size;
import com.github.bordertech.wcomponents.UIContext;
import com.github.bordertech.wcomponents.UIContextHolder;
import com.github.bordertech.wcomponents.WAjaxControl;
import com.github.bordertech.wcomponents.WButton;
import com.github.bordertech.wcomponents.WCheckBoxSelect;
import com.github.bordertech.wcomponents.WContainer;
import com.github.bordertech.wcomponents.WDataRenderer;
import com.github.bordertech.wcomponents.WDecoratedLabel;
import com.github.bordertech.wcomponents.WFieldLayout;
import com.github.bordertech.wcomponents.WHeading;
import com.github.bordertech.wcomponents.WLabel;
import com.github.bordertech.wcomponents.WNamingContext;
import com.github.bordertech.wcomponents.WPanel;
import com.github.bordertech.wcomponents.WPhoneNumberField;
import com.github.bordertech.wcomponents.WRepeater;
import com.github.bordertech.wcomponents.WText;
import com.github.bordertech.wcomponents.WTextArea;
import com.github.bordertech.wcomponents.WTextField;
import com.github.bordertech.wcomponents.WebUtilities;
import com.github.bordertech.wcomponents.layout.BorderLayout;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
/**
*
* An example demonstrating a WRepeater with editable fields with static IDs. There are a few aspects of the use of
* static IDs with repeated components we are highlighting here:
*
* - Setting a naming context's ID on the WRepeater;
* - Setting a custom row identifier on the WRepeater;
* - Setting a custom ID on the repeated component - this is important to show the effect of repetition on a static
* ID.
*
*
* NOTE: We also find the parent naming context for the examples content tab and prevent this from being a naming
* context. This to prevent the naming context ID from being pre-pended to all of the IDs we are really
* interested in. This is both dangerous and unnecessary and should NEVER be done in a real
* application.
*
* @author Martin Shevchenko
* @author Mark Reeves
* @since 1.0.0
*/
public class RepeaterExampleWithStaticIDs extends WContainer {
/**
* The ID to set on the contact list.
*/
private static final String ID_LIST = "Contacts_List";
/**
* The static ID of the roles WCheckBoxSelect.
*/
private static final String ID_ROLE = "roles";
/**
* The static ID of the phone number WPhoneNumberField.
*/
private static final String ID_PHONE = "phone_number";
/**
* The repeater which is used to display the data.
*/
private final WRepeater repeater;
/**
* A text field used to enter in a new contact name.
*/
private final WTextField newNameField;
/**
* Used to display a text-only view of the data when the "print" button is pressed.
*/
private final WTextArea printOutput;
/**
* Creates a RepeaterExampleWithEditableRows.
*/
public RepeaterExampleWithStaticIDs() {
repeater = new WRepeater() {
@Override
protected String getRowIdName(final Object rowBean, final Object contact) {
ContactDetails bean = (ContactDetails) contact;
return "Contact_id_" + String.valueOf(bean.getUid());
}
};
repeater.setIdName(ID_LIST);
repeater.setRepeatedComponent(new ContactContainer());
newNameField = new WTextField();
printOutput = new WTextArea();
printOutput.setColumns(60);
printOutput.setRows(5);
createUI();
}
/**
* Creates the example UI.
*/
private void createUI() {
add(new WHeading(HeadingLevel.H2, "Contacts"));
add(repeater);
createButtonBar();
createAddContactSubForm();
createPrintContactsSubForm();
}
/**
* Create the UI artefacts for the update and reset buttons.
*/
private void createButtonBar() {
// Update and reset controls for the repeater.
WPanel buttonPanel = new WPanel(WPanel.Type.FEATURE);
buttonPanel.setMargin(new Margin(Size.MEDIUM, null, Size.LARGE, null));
buttonPanel.setLayout(new BorderLayout());
WButton updateButton = new WButton("Update");
updateButton.setImage("/image/document-save-5.png");
updateButton.setImagePosition(WButton.ImagePosition.EAST);
buttonPanel.add(updateButton, BorderLayout.EAST);
WButton resetButton = new WButton("Reset");
resetButton.setImage("/image/edit-undo-8.png");
resetButton.setImagePosition(WButton.ImagePosition.WEST);
resetButton.setAction(new Action() {
@Override
public void execute(final ActionEvent event) {
repeater.setData(fetchDataList());
}
});
buttonPanel.add(resetButton, BorderLayout.WEST);
add(buttonPanel);
add(new WAjaxControl(updateButton, repeater));
add(new WAjaxControl(resetButton, repeater));
}
/**
* Create the UI artefacts for the "Add contact" sub form.
*/
private void createAddContactSubForm() {
add(new WHeading(HeadingLevel.H3, "Add a new contact"));
WButton addBtn = new WButton("Add");
addBtn.setAction(new Action() {
@Override
public void execute(final ActionEvent event) {
addNewContact();
}
});
addBtn.setImage("/image/address-book-new.png");
newNameField.setDefaultSubmitButton(addBtn);
WContainer container = new WContainer();
container.add(newNameField);
container.add(addBtn);
WFieldLayout layout = new WFieldLayout();
add(layout);
layout.addField("New contact name", container);
add(new WAjaxControl(addBtn, new AjaxTarget[]{repeater, newNameField}));
}
/**
* Create the UI artefacts for the "Print contacts" sub form.
*/
private void createPrintContactsSubForm() {
add(new WHeading(HeadingLevel.H3, "Print to CSV"));
WButton printBtn = new WButton("Print");
printBtn.setAction(new Action() {
@Override
public void execute(final ActionEvent event) {
printDetails();
}
});
printBtn.setImage("/image/document-print.png");
printBtn.setImagePosition(WButton.ImagePosition.EAST);
WFieldLayout layout = new WFieldLayout();
add(layout);
layout.setMargin(new Margin(Size.LARGE, null, null, null));
layout.addField("Print output", printOutput);
layout.addField((WLabel) null, printBtn);
add(new WAjaxControl(printBtn, printOutput));
}
/**
* Adds a new contact to the list of contacts. The contact's name is obtained from {@link newNameField}.
*/
private void addNewContact() {
String name = newNameField.getText();
if (name != null && !"".equals(name)) {
List list = new ArrayList(repeater.getBeanList());
list.add(new ContactDetails(name, null, new String[0]));
repeater.setBeanList(list);
}
newNameField.setText("");
}
/**
* Write the list of contacts into the WTextArea printOutput.
*/
private void printDetails() {
StringBuilder builder = new StringBuilder("\"Name\",\"Phone\",\"Roles\",\"Identifier\"\n");
for (Object contact : repeater.getBeanList()) {
builder.append(contact).append('\n');
}
printOutput.setText(builder.toString());
}
/**
* Override to initialise some data the first time through.
*
* @param request The request being responded to.
*/
@Override
public void preparePaintComponent(final Request request) {
if (!this.isInitialised()) {
// Give the repeater the list of data to display.
repeater.setData(fetchDataList());
// THIS IS THE BIT YOUSHOULD NEVER EVER DO SO LOOK AWAY NOW...
WNamingContext nc = (WNamingContext) WebUtilities.getAncestorOfClass(WNamingContext.class, this);
if (null != nc) {
nc.setNamingContext(false);
}
// OK, WE ARE SAFE AGAIN
// Remember that we've done the initialisation.
this.setInitialised(true);
}
}
/**
* The component to be used to render one row. Note that this component remembers the given data object and keeps it
* up to date. The component static IDs are purely for demonstration purposes.
*
* @author Martin Shevchenko
* @author Mark Reeves
*/
public class ContactContainer extends WDataRenderer {
/**
* Used to display/modify the contact's phone number.
*/
private final WPhoneNumberField phoneNumField = new WPhoneNumberField();
/**
* Used to display/modify the contact's roles.
*/
private final WCheckBoxSelect roleSelect = new WCheckBoxSelect(new String[]{"a", "b", "c"});
/**
* A button to delete a contact if we don't like them any more.
*/
private final WButton deleteButton = new WButton("Delete");
/**
* Creates a ContactContainer.
*/
public ContactContainer() {
roleSelect.setButtonLayout(WCheckBoxSelect.LAYOUT_FLAT);
roleSelect.setFrameless(true);
roleSelect.setIdName(ID_ROLE);
phoneNumField.setIdName(ID_PHONE);
deleteButton.setRenderAsLink(true);
deleteButton.setAction(new Action() {
@Override
public void execute(final ActionEvent event) {
removeRow();
}
});
deleteButton.setMessage("Are you really sure?");
deleteButton.setImage("/image/remove.png");
createUI();
}
/**
* Creates the UI artefacts for the ContactContainer.
*/
private void createUI() {
WText headingText = new WText();
WHeading contactName = new WHeading(HeadingLevel.H3, new WDecoratedLabel(null, headingText, deleteButton));
headingText.setBeanProperty("name");
add(contactName);
WFieldLayout fieldLayout = new WFieldLayout();
fieldLayout.addField("Phone", phoneNumField);
fieldLayout.addField("Roles", roleSelect);
add(fieldLayout);
add(new WAjaxControl(deleteButton, repeater));
}
/**
* Remove a contact from the list.
*/
private void removeRow() {
UIContext uic = UIContextHolder.getCurrent();
if (!(uic instanceof WRepeater.SubUIContext)) {
return;
}
List list = new ArrayList(repeater.getBeanList());
list.remove((ContactDetails) repeater.getRowBeanForSubcontext((WRepeater.SubUIContext) uic));
repeater.setData(list);
}
@Override
protected void preparePaintComponent(final Request request) {
super.preparePaintComponent(request);
if (!isInitialised()) {
setInitialised(true);
UIContext uic = UIContextHolder.getCurrent();
if (!(uic instanceof WRepeater.SubUIContext)) {
return;
}
WRepeater.SubUIContext subUic = (WRepeater.SubUIContext) uic;
}
}
/**
* {@inheritDoc}
*/
@Override
public void updateData(final Object data) {
ContactDetails details = (ContactDetails) data;
details.setPhoneNumber(phoneNumField.getText());
details.setRoles((List) roleSelect.getSelected());
}
/**
* {@inheritDoc}
*/
@Override
public void updateComponent(final Object data) {
ContactDetails details = (ContactDetails) data;
phoneNumField.setText(details.getPhoneNumber());
roleSelect.setSelected(details.getRoles());
}
}
/**
* Retrieves dummy data used by this example.
*
* @return the list of data for this example.
*/
private static List fetchDataList() {
List list = new ArrayList<>();
list.add(new ContactDetails("David", "1234", new String[]{"a", "b"}));
list.add(new ContactDetails("Jun", "1111", new String[]{"c"}));
list.add(new ContactDetails("Martin", null, new String[]{"b"}));
return list;
}
/**
* A simple data object.
*
* @author Martin Shevchenko
* @author Mark Reeves
*/
public static class ContactDetails implements Serializable {
/**
* The contact name.
*/
private String name;
/**
* The contact phone number.
*/
private String phoneNumber;
/**
* The contact roles.
*/
private List roles;
/**
* The contact unique id of the contact.
*/
private final int uid;
/**
* Creates a ContactDetails.
*
* @param name the contact name.
* @param phoneNumber the contact phone number.
* @param roles the contact roles.
*/
public ContactDetails(final String name, final String phoneNumber, final String[] roles) {
this.name = name;
this.phoneNumber = phoneNumber;
this.roles = new ArrayList<>(Arrays.asList(roles));
// This would normally be something unique and sensible in your data source like a record identifier,
// database unique key etc.
// The mucking about with sign is just because I am using UUID because I am LAZY.
int i = UUID.randomUUID().hashCode();
i = i > 0 ? i : i * -1;
this.uid = i;
}
/**
* @return the contact name
*/
public String getName() {
return name;
}
/**
* Sets the contact name.
*
* @param name the contact name.
*/
public void setName(final String name) {
this.name = name;
}
/**
* @return the contact phone number.
*/
public String getPhoneNumber() {
return phoneNumber;
}
/**
* @return the contact's unique id.
*/
public int getUid() {
return uid;
}
/**
* Sets the contact phone number.
*
* @param phoneNumber the contact phone number.
*/
public void setPhoneNumber(final String phoneNumber) {
this.phoneNumber = phoneNumber;
}
/**
* @return the contact roles.
*/
public List getRoles() {
return roles;
}
/**
* Sets the contact roles.
*
* @param roles the contact roles.
*/
public void setRoles(final List roles) {
this.roles = roles;
}
/**
* @return a textual representation of this Contact.
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder("\"");
builder.append(name);
builder.append("\",\"");
builder.append(phoneNumber == null ? "" : phoneNumber);
builder.append("\",\"");
for (int i = 0; i < roles.size(); i++) {
if (i > 0) {
builder.append(',');
}
builder.append(roles.get(i));
}
builder.append("\",\"");
builder.append(String.valueOf(uid));
builder.append("\"");
return builder.toString();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy