I am using MVP pattern. In my View, I am using TextBox named uiTextBox in which I have added my enum class Message Status using following code in the method initStaticContent.
private void initStaticContent() {
for (MessageStatus status : EnumSet.allOf(MessageStatus.class))
uiTextStatus.setText(status.name());
updateUiWithPermissions();
}
My Enum Class is:
public enum MessageStatus {
SENDING, SENT, FAILED;
}
And in my updateUiWithModel() I am performing following steps :
private void updateUiWithModel() {
if (model == null)
throw new IllegalStateException("A model must be defined to update the ui.");
uiTextCreatedOn.setText(model.createdOn);
uiTextBusinessName.setText(model.businessName);
uiTextSenderStaffFirstName.setText(model.senderStaffFirstName);
selectStatus(model.status);
case SEND:{
uiTextRecipientEmail.setVisible(true);
uiTextRecipientSms.setVisible(false);
uiTextRecipientVoice.setVisible(false);
}break;
case SENDING:{
uiTextRecipientEmail.setVisible(false);
uiTextRecipientSms.setVisible(true);
uiTextRecipientVoice.setVisible(false);
}break;
case SENT:{
uiTextRecipientEmail.setVisible(false);
uiTextRecipientSms.setVisible(false);
uiTextRecipientVoice.setVisible(true);
}break;
}
public void selectStatus(MessageStatus status) {
if(status == null){
uiTextStatus.setText("");
return;
}
for(int i=0; i < uiTextStatus.getMaxLength(); i++){
String currentStatus = (uiTextStatus.getText(i));
if (currentStatus == status.name()) {
uiListBoxMethod.setSelectedIndex(i);
break;
}
}
}
Firstly, I want to know how to iterate in for each over uiTextBox and count the items in the textbox.
Secondly, if I use Listbox instead of TextBox and I want to have switch case in the Listbox how can I do it in method updateUiWithModel.
Well you can create a TextFieldStatusManipulator class that sets text and visibility state.
class TextFieldStatusManipulator {
private final Function<Model,String> extractString;
private final Predicate<Status> setVisible;
private final TextBox textBox;
public TextFieldStatusManipulator(TextBox box, Function<Model,String> ex, Predicate<Status> sv) {
textBox = box; extractString = ex; setVisible = sv;
}
public void statusChange(Model model) {
textBox.setText(extractString.apply(model));
textBox.setVisible(setVisible.test(model.status));
}
}
Then you create one for each TextField, like so
TextFieldStatusManipulator createdOnManip = new TextFieldStatusManipulator (uiTextCreatedOn, Model::getCreatedOn, s -> s == Status.SEND);
Then you add them to a list and iterate the list on status changes.
manipulatorList.forEach(m -> m.statusChange(model));
Related
I am trying to add a ComboBox into the TableView but for some reason I cannot make the conversion. Behind the scenes, I want to make the conversation if the value is
0 then it should display 'free' if the value is 1 then it will say 'taken' in the ComboBox, and once the user changes the value in the ComboBox
it will save its integer value.
I am not sure how to add the converter and it gives the following error at event.getNewValue():
cant convert int to string.
Any help where I am doing wrong?
private final IntegerProperty mode;
public int getMode() {
return mode.get();
}
public void setMode(int mode) {
this.mode.set(mode);
}
public IntegerProperty modeProperty() {
return mode;
}
Set<String> modeList = new HashSet<>();
modeList.add("Free");
modeList.add("Taken");
var converter=modeConverter();
TableColumn<Review, String> modeCombo = new TableColumn("Mode");
modeCombo.setCellValueFactory(new PropertyValueFactory("mode"));
modeCombo.setCellFactory(ComboBoxTableCell.forTableColumn(converter); //How to apply the converter.
modeCombo.setCellFactory(ComboBoxTableCell.forTableColumn(FXCollections.observableList(modeList))));
modeCombo.setOnEditCommit(event -> {
mode.setOperationMode(event.getNewValue()); //Method cannot be applied java.lang.String. But I already make the conversatin via modeConverter
});
...
private StringConverter modeConverter() {
return new StringConverter<Integer>() {
#Override
public String toString(Integer object) {
if (object == 0) {
return "FREE";
} else {
return "Taken";
}
}
#Override
public Integer fromString(String string) {
if (string.equalsIgnoreCase("free")) {
return 0;
} else {
return 1;
}
}
};
}
You need to use the overloaded method:
forTableColumn(StringConverter converter,
ObservableList items)
Please note that ComboBox backing list should contain 0, 1 instead of Free, Taken. The converter is responsible for displaying 0 as Free and 1 as Taken.
Also, the TableColumn should be of type <Review, Integer> instead of <Review, String>.
In your code, you can do something as follows:
ObservableList<Integer> modeList = FXCollections.observableList(0, 1);
TableColumn<Review, Integer> modeCombo = new TableColumn("Mode");
modeCombo.setCellValueFactory(new PropertyValueFactory("mode"));
modeCombo.setCellFactory(ComboBoxTableCell.forTableColumn(converter, modeList)));
Once your basic type is fixed, the following should work:
modeCombo.setOnEditCommit(event -> {
mode.setOperationMode(event.getNewValue());
});
The ClassChoice control inherits CheckBoxMultipleChoice. It is a common control used on multiple pages with selections persisted in the session. The available choices are obtained from the database. An "All" checkbox is added when there is more than one data item. On some pages a selection change causes the page to be refreshed with new data. On other page the selections should change without a refresh.
My problem is that I need to control the "All" checkbox when other checkboxes change and to change all of the checkboxes when the "All" checkbox changes.
I tried to call updateModel() to force a change but that did not work. How can I change the selections (the model parameter) without refreshing the page?
This edited code does not show page refreshing.
public class ClassChoice<T> extends CheckBoxMultipleChoice
{
private static final long serialVersionUID = 1L;
#SpringBean
private ClassService classService;
List<EntityClassModel> selection;
EntityClassModel ecmAll;
static List<EntityClassModel> availableClasses;
public ClassChoice(..)
{
super("classcheckboxes");
setSuffix(" "); // sets checkbox separator and ensures inline display
ecmAll = (EntityClassModel) modelFactory.getNewClassModel();
ecmAll.setClassname("All");
// List of all classes associated with user
availableClasses = classService.getListOfClasses(..);
setClassChoices();
add( new AjaxFormChoiceComponentUpdatingBehavior()
{
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget target)
{
List<Integer> previousIDs = UserSession.get().getSelectedClassIDs();
if ((previousIDs.size() > 0) && ((previousIDs.size() + 1) >= availableClasses.size()))
{
// Was previously Select All
if (selection.get(selection.size() - 1) == ecmAll)
{
// Select All still selected, remove it
selection.remove(selection.size() - 1);
}
else
{
// Remove all selections
selection.clear();
}
}
else if (selection.size() > 0)
{
// Was none or some selected
if (selection.get(selection.size() - 1) == ecmAll)
{
// Select All, select all available
selection.clear();
selection.addAll(availableClasses);
}
else if ((selection.size() + 1) >= availableClasses.size())
{
// Is now full, add Select All
selection.add(ecmAll);
}
// else change but no special handling required
}
// else none are currently selected
UserSession.get().setSelectedClasses(selection);
// Generate a list of selected class IDs, excluding All
List<Integer> selectedIDs = new ArrayList<Integer>();
int copysize = selection.size();
if ((copysize > 0) && (selection.get(copysize - 1) == ecmAll))
{
copysize--;
}
for (int index = 0; index < copysize; index++)
{
selectedIDs.add(selection.get(index).getId());
}
UserSession.get().setSelectedClassIDs(selectedIDs);
// Update the selections on the page
updateModel();
}
});
Initialize();
}
#SuppressWarnings("unchecked")
protected void Initialize()
{
// Grabs already selected classes from UserSession
List<Integer> selectedIDs = UserSession.get().getSelectedClassIDs();
selection = classService.getClassesByClassIDs(selectedIDs);
if (selectedIDs.size() > 1)
{
if ((selectedIDs.size() + 1) >= availableClasses.size())
{
selection.add(ecmAll);
}
}
setModel(Model.ofList(selection));
// Configure the data and display
setChoiceRenderer(new ChoiceRenderer<EntityClassModel>("classname", "id"));
setOutputMarkupId(true);
}
#SuppressWarnings("unchecked")
public void setClassChoices()
{
// Adds 'All' option when there is more than one class
if (availableClasses.size() > 1)
{
availableClasses.add(ecmAll);
}
setChoices(availableClasses);
}
public List<EntityClassModel> getSelection()
{
return selection;
}
}
You have to use the AjaxRequestTarget to update the HTML element on the browser side. By adding/removing elements to selection you change the model of ClassChoice at the server side. At the bottom of AjaxFormChoiceComponentUpdatingBehavior#onUpdate() you should do target.add(this) to tell Wicket to repaint this ClassChoice instance with its new selection/model.
Make sure you call setOutputMarkupId(true) in its constructor because otherwise you won't be able to update it with Ajax.
I try to write an application to create PDF files, it uses the JavaServer Faces. I struggle with a problem when I give the value of the text box from bean to factory class, the values are lost. I wonder why this happens, already tried many solutions, but they will cause expansion of the code and do not help.
Bean code:
#ManagedBean
#ViewScoped
public class PanelInneBean extends AbstractPanel implements Serializable {
private static final long serialVersionUID = 1L;
private final int CODE = 4;
private boolean use;
private String tytul, opis;
private PdfFactory pdf = PdfFactory.getPdfObject();
public PanelInneBean() {
use = false;
}
public boolean getUse() {
return use;
}
public String getTytul() {
return tytul;
}
public void setTytul(String tytul) {
this.tytul = tytul;
}
public String getOpis() {
return opis;
}
public void setOpis(String opis) {
this.opis = opis;
}
public int getCode() {
return CODE;
}
private void add() {
use = true;
}
public void addBean() {
add();
pdf.addElement(this);
System.out.println("InnePanel after pdf.addElement() this.opis:" + this.opis);
// This sysout prints the correct value after give object to factory
}
}
Factory piece of code:
public int addElement(PdfElement element) {
pdfType = true;
if (element.getUse()) {
elementList.add(element);
return 1;
}
return 0;
}
public void prepare() {
for (PdfElement element : elementList) {
System.out.println("element.code:" + element.getCode());
switch (element.getCode()) {
case 0:
if (nF != null)
break;
nF = new NaglowekFactory(element, Counter.getNumber());
break;
case 1:
if (pF != null)
break;
pF = new ProduktyFactory(element, Counter.getNumber());
prodSum = pF.getProdukty().getSuma();
euroData = pF.getProdukty().getEuroData();
break;
case 2:
if (mF != null)
break;
mF = new MontazFactory(element, Counter.getNumber());
servSum = mF.getMontaz().getSuma();
break;
case 3:
if (uF != null)
break;
uF = new UslugiFactory(element, Counter.getNumber());
asmSum = uF.getUslugi().getSuma();
break;
case 4:
if (iF != null)
break;
iF = new InneFactory(element, Counter.getNumber());
//here Opis value is empty
break;
}
}
System.out.println("factory.prepare() ->");
}
Constructor of InneFactory:
PanelInneBean inne;
public InneFactory(PdfElement element, int order) {
inne = (PanelInneBean) element;
System.out.println("innerFactory constructor, inne.getTytul(): "
+ inne.getTytul());
//here values are empty
this.order = order;
list = new ArrayList<Element>();
}
public int getOrder() {
return order;
}
what I'm doing wrong?
I think you are running into a common misconception about how #ViewScoped beans really work. The bean object itself is created on every Faces request and destroyed after every Faces response.
After the bean is re created however JSF will enter the first lifecycle phase RestoreView. During this phase it will fetch the last good values for this bean from the View State and apply them to the beans Managed Properties.
Basically what is happening is that you are invoking an action, which generates a seperate request than the one that loaded the page, and at this point the reference you added to the PdfFactory is now lost because the PdfFactory in the last object was destroyed!
The best way to resolve this would be to make PdfFactory a Managed Bean. You can initialize the factory in the #PostConstruct method and you can inject other Managed Beans into your PdfFactory bean using the #ManagedProperty annotation.
#ManagedBean
#RequestScoped
public PdfFactory extends ... implements Serializable {
#ManagedProperty("#{myViewBean}")
private MyViewBean viewBean;
#PostConstruct
public initializeFactory() {
//Do stuff
}
public void prepare() {
// prepare stuff
}
}
I would like to search into my tree only if the user type 3 character at least.
How i can catch "doSelect" event to do this?
If i add a keylistener on the text field to check its value, the handler is invoked after the doSelect.
Can anyone help me?
This is an example...
filterText = new StoreFilterField<ModelData>() {
#Override
protected boolean doSelect(Store<ModelData> store,
ModelData parent, ModelData record, String property,
String filter) {
String name = record.get("name");
name = name.toLowerCase();
if (name.startsWith(filter.toLowerCase()))
return true;
else
return false;
}
};
KeyListener keyListener = new KeyListener() {
public void componentKeyUp(ComponentEvent event) {
loadingImage.setVisible(false);
if(filterText.isValid() && filterText.getRawValue().length()>=FILTER_MIN_SIZE) {
filterText.bind(store);
} else {
filterText.unbind(store);
}
}
};
filterText.setMinLength(FILTER_MIN_SIZE);
filterText.bind(store);
(Appears to be GXT 2, let me know if you are actually using GXT 3)
StoreFilterField relies on the applyFilters method to actually apply all of these. It has a check already that the text has at least one character:
protected void applyFilters(Store<M> store) {
if (getRawValue().length() > 0) {
store.addFilter(filter);
store.applyFilters(property);
} else {
store.removeFilter(filter);
}
}
The easiest way I see to override this would be to subclass StoreFilterField and redefine this method:
filterText = new StoreFilterField<ModelData>() {
#Override
protected void applyFilters(Store<M> store) {
if (getRawValue().length() > 3) {
store.addFilter(filter);
store.applyFilters(getProperty());
} else {
store.removeFilter(filter);
}
}
}
Is there any way to add clickHandlers (or any type of handler) to the headers of the columns in a CellTable? I want to add some sorting functionality to my CellTable and I dont see any methods in the Column or Header classes that will allow this. I used this post to figure out how to use the CellTable.
Workaround for click events:
Header<String> columnHeader = new Header<String>(new ClickableTextCell()) {
#Override
public String getValue() {
return columnName;
}
};
columnHeader.setUpdater(new ValueUpdater<String>() {
#Override
public void update(String value) {
Window.alert("Header clicked!");
}
});
table.addColumn(column, columnHeader);
There is no out of the box way of supporting sort as yet on the CellTable. However there is a manual workaround involving a lot of code drudgery. Refer the classes SortableHeader and SortableColumn in the bike shed under expenses sample. You will find the usage in com.google.gwt.sample.expenses.gwt.client.ExpenseDetails. You can use this until something concrete comes out in the next release.
check out directory: http://google-web-toolkit.googlecode.com/svn/trunk/bikeshed
With the final release of GWT 2.1, has there been any support for sortable columns added to the CellTable? Or is it still a roll your own solution after looking at the bikeshed example?
CellTable<Contact> table = new CellTable<Contact>();
// Create name column.
final TextColumn<Contact> nameColumn = new TextColumn<Contact>() {
#Override
public String getValue(Contact contact) {
return contact.name;
}
};
// Create a data provider.
ListDataProvider<Contact> dataProvider = new ListDataProvider<Contact>();
// Connect the table to the data provider.
dataProvider.addDataDisplay(table);
final List<Contact> list = dataProvider.getList();
for (Contact contact : CONTACTS) {
list.add(contact);
}
final ListHandler<Contact> columnSortHandler = new ListHandler<Contact>(
list);
Header<String> columnHeader = new Header<String>(new ClickableTextCell()) {
#Override
public String getValue() {
return "Name";
}
};
columnHeader.setUpdater(new ValueUpdater<String>() {
#Override
public void update(String value) {
if (Window.confirm("Want to do?")){
nameColumn.setSortable(true);
columnSortHandler.setComparator(nameColumn,
new Comparator<Contact>() {
public int compare(Contact o1, Contact o2) {
if (o1 == o2) {
return 0;
}
// Compare the name columns.
if (o1 != null) {
return (o2 != null) ? o1.name.compareTo(o2.name) : 1;
}
return -1;
}
});
} else nameColumn.setSortable(false);
}
});
// Make the name column sortable.
nameColumn.setSortable(false);
// Create address column.
TextColumn<Contact> addressColumn = new TextColumn<Contact>() {
#Override
public String getValue(Contact contact) {
return contact.address;
}
};
// Add the columns.
table.addColumn(nameColumn, columnHeader);
table.addColumn(addressColumn, "Address");
// Add the data to the data provider, which automatically pushes it to the
// widget.
// Add a ColumnSortEvent.ListHandler to connect sorting to the
// java.util.List.
//------------------ Code to add --------------------------------//
VerticalPanel vp = new VerticalPanel();
table.addColumnSortHandler(columnSortHandler);
//------------------ Code end --------------------------------//
// We know that the data is sorted alphabetically by default.
table.getColumnSortList().push(nameColumn);
// Add it to the root panel.
vp.add(table);
RootPanel.get().add(vp);