I need to update a model or object immediately after select
a DropDownChoice item.
Bellow is the code that I'm working:
add(new ListView[Company]("listCompanies", listData) {
override protected def onBeforeRender() {
//
// ...
super.onBeforeRender()
}
def populateItem(item: ListItem[Company]) = {
var company = item.getModelObject()
//...
val listClients: java.util.List[Client] = clientControler.listClients
item.add(new DropDownChoice("clientSelection", listClients,new ChoiceRenderer[Client]("name")))
In the Listview with properties of Company Object,
after choose a name property of the DropDownChoice, the model
Company would be updated with the Client Name selected.
How can I achieve this?
Thanks
I think you can override onSelectionChanged. But you also need to override wantOnSelectionChangedNotifications to return true to make it work. Something like this.
DropDownChoice<Client> dropDownChoice = new DropDownChoice("clientSelection", listClients) {
#Override
protected boolean wantOnSelectionChangedNotifications() {
return true;
}
#Override
protected void onSelectionChanged(Object newSelection) {
// Do something here when selection is changed
}
};
you need to add updating behavior:
add(new DropDownChoice<Client>("clientSelection", listClients)
.add(new AjaxFormComponentUpdatingBehavior("onchange") {
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget target) {
// update your model here
// then you need to add model to target
target.add();
}
}));
I think you can use an AjaxEventBehavior on your DropDownChoice:
item.add(new DropDownChoice("clientSelection", listClients,new ChoiceRenderer[Client("name")).add(new AjaxEventBehavior("change") {
#Override
protected void onEvent(AjaxRequestTarget target) {
// TODO Auto-generated method stub
}
}))
Related
In my project, I have a TableViewer which needs to show around 3000 items and also filter them. Without SWT.VIRTUAL the table takes multiple seconds to display.
So, I implemented ILazyContentProvider and not using "ArrayContentProvider" but now I am facing issues in filtering the elements of TableViewer.
I am writing the below code for filtering but the select method is not running at all.
private static class DefaultFilterextends ViewerFilter {
private String searchText;
public void setSearchText(final String searchText) {
this.searchText = searchText;
}
#Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (this.searchText == null) {
return true;
}
return (element.toString().contains(searchText) || element.toString().equals(searchText));
}
}
The below ContentProvider, I am writting
private class LazyContentProvider implements ILazyContentProvider {
private TableViewer viewer;
private List<String> elements;
public LazyContentProvider(TableViewer viewer) {
this.viewer = viewer;
}
#Override
public void dispose() {
}
#Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
this.elements = (List<String>) newInput;
}
#Override
public void updateElement(int index) {
viewer.replace(elements.get(index), index);
}
}
Can someone please guide me how can I do the filteration of elements in TableViewer with SWT.VIRTUAL?
TableViewer does not support filtering when SWT.VIRTUAL is used. Instead you must do the filtering in the content provider.
The content provider will need to maintain a filtered list of elements. For example:
public class LazyContentProvider implements ILazyContentProvider
{
private TableViewer viewer;
private List<String> allElements;
private List<String> filteredElements;
public LazyContentProvider()
{
//
}
#Override
public void dispose()
{
//
}
#SuppressWarnings("unchecked")
#Override
public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput)
{
this.viewer = (TableViewer)viewer;
allElements = (List<String>)newInput;
filteredElements = allElements;
}
#Override
public void updateElement(final int index)
{
viewer.replace(filteredElements.get(index), index);
}
public void filter(final String searchText)
{
filteredElements = allElements.stream().filter(element -> element.contains(searchText)).toList();
viewer.setItemCount(filteredElements.size());
viewer.refresh();
}
}
Here I have added a filteredElements list that contains just the current filtered elements, this is used in updateElement.
I added a filter method which updates the filtered elements list. It also tells the table viewer about the new item count and refreshes the table.
The .toList() method in the filter stream requires Java 16, for older versions of Java use .collect(Collectors.toList()).
I would like to create breadcrump on my page, but I am unable to do it by following wicket examples.. I need to extend BreadCrumbPanel when I also need to extend WebPage..
I want breadcrumb to be visible only on this specific page, after clicking some of links on the page(they call setresponsepage with some parameters) I would like to append my breadcrumb
public final class GroupMainPage extends WebPage {
// Map<String, Group> hostGroup = PropertiesLoader.getInstance().getHostGroupMap();
List<Group> hostGroup = PropertiesLoader.getInstance().getHostGroupList();
public GroupMainPage() {
super();
HostGroupManager.getInstance();
createMainTable(hostGroup);
add(new Label("message", "OK \n ok"));
}
then I have some methods which help me create table on my page, especially this one with links where I would like to append my breadcrumb:
ListView<Component> list = new ListView<Component>("groupListElement", ((Group) component).getDependentGroups()) {
#Override
protected void populateItem(ListItem<Component> item) {
final Component c = item.getModelObject();
Link link = new Link("groupLink") {
#Override
public void onClick() {
Group g = (Group) c;
if (g.getDependentGroups() != null && g.getDependentGroups().size() > 0) {
setResponsePage(new GroupMainPage(g.getDependentGroups()));
} else {
setResponsePage(new GroupServiceListPage(g.createServicesList()));
}
}
};
link.add(new Label("linkLabel", c.getName()));
item.add(link);
How to make it possible?
I have native select of Locales implemented like that:
NativeSelect selectLang = new NativeSelect();
for (Locale locale : localeProvider.getSupportedLocales()) {
selectLang.setItemCaption(locale, localeProvider.getLabel(locale));
selectLang.addItem(locale);
}
selectLang.setValue(user.getLocale());
selectLang.setNullSelectionAllowed(false);
selectLang.addItemSetChangeListener(new ItemSetChangeListener() {
private static final long serialVersionUID = 4797561043434404341L;
#Override
public void containerItemSetChange(ItemSetChangeEvent event) {
// Locale loc = (Locale)event.getContainer().getValue();
// UI.getCurrent().setLocale(loc);
}
});
I wanted to use event.getContainer().getValue(), but method getValue() is undefined for the type Container. How can I get value of event?
You may use selectLang.getValue() if you want to get the current value of the nativeSelect in a method :
selectLang.addListener(new ValueChangeListener() {
#Override
public void valueChange(ValueChangeEvent event) {
selectLang.getValue();
}
});
Of course add "final" to your component.
SelectExample.java (dev.vaadin.com)
I have a GWT application that loads a product when the page is loaded. I am using PropertyChangeEvent on the product object (and its sub-objects) to update the values of fields, whenever a change happens.
Of course, I do not want this PropertyChangeEvent to raise when the product is loaded for the first time. For this, I am setting the raisePropertyChange value to false, but it doesn't seem to work. Please find below the code base:
// Class ProductBaseImpl
public abstract class PropChangeImpl {
// The raise property change event, should be turned off conditionally
private boolean raisePropertyChangeEvent = true;
protected boolean getRaisePropertyChangeEvent() {
return this.raisePropertyChangeEvent;
}
protected void setRaisePropertyChangeEvent(final boolean value) {
this.raisePropertyChangeEvent = value;
}
protected void raisePropertyChangeEvent(String fieldName, Object oldValue, Object newValue) {
if (this.raisePropertyChangeEvent ) {
// --> HERE IS THE PROBLEM <--
// This IF loop must not be true when loading the product first time
System.out.println("Property change event raised!");
// the update operations go here
} else {
System.out.println("Property change event not raised!");
}
}
}
// Class ProductBaseImpl
public abstract class ProductBaseImpl extends PropChangeImpl {
private static HandlerRegistration productChangeBeginRegistration;
private static HandlerRegistration productChangeEndRegistration;
protected E instance;
protected ProductBaseImpl(final E instance) {
this.instance = instance;
// Stop updates when a new product loads
if (ProductBaseImpl.productChangeBeginRegistration == null) {
ProductBaseImpl.productChangeBeginRegistration = Core.getEventBus().addHandler(ProductChangeBeginEvent.TYPE, new ProductChangeBeginEventEventHandler() {
#Override
public void onProductChangeBegin(final ProductChangeBeginEvent event) {
ProductBaseImpl.this.raisePropertyChangeEvent(false);
}
});
}
if (ProductBaseImpl.productChangeEndRegistration == null) {
ProductBaseImpl.productChangeEndRegistration = Core.getEventBus().addHandler(ProductChangeEndEvent.TYPE, new ProductChangeEndEventtHandler() {
#Override
public void onProductChangeEnd(final ProductChangeEndEvent event) {
ProductBaseImpl.this.raisePropertyChangeEvent(true);
}
});
}
}
}
// Class ProductSubObj1
public class ProductSubObj1 extends ProductBaseImpl {
public ProductSubObj1 (final E instance) {
super(instance);
// some other operations
}
}
// similar to above, I have classes ProductSubObj1, ProductSubObj2 ...
// Class ProductProvider, that fetches the product from service to UI
public class ProductProvider {
// some properties and members
public void fetchProduct(String productId) {
// Let listeners know the product is about to change
Core.getEventBus().fireEvent(new ProductChangeBeginEvent(productId));
// Call the service to get the product in Json data
// After processing the data to be available for the UI (and scheduleDeferred)
Core.getEventBus().fireEvent(new ProductChangeEndEvent(productId));
}
}
As commented inline in the code, the control always goes within the
if (this.raiseDataChangeEvent)
block which I don't want to happen when the product is loaded for the first time.
Could you please advise what am I doing wrong?
Thanks.
Can you just do this:?
protected void raisePropertyChangeEvent(String fieldName, Object oldValue, Object newValue) {
if (this.raisePropertyChangeEvent && oldValue != null /*Or whatever your default unloaded value is*/) {
// --> HERE IS THE PROBLEM <--
// This IF loop must not be true when loading the product first time
System.out.println("Property change event raised!");
// the update operations go here
} else {
System.out.println("Property change event not raised!");
}
}
I have form with dateTimeField, and ListView.
ListView looks like that:
final ListView<String> countryView = new ListView<String>("country", model.<List<String>>bind("country")) {
#Override
protected void populateItem(final ListItem<String> item) {
final String country = item.getModelObject();
item.add(new ValidationDisplayableLabel("country", country, new String[] { modelPath }));
item.add(new AjaxLink("deleteLink") {
#Override
public void onClick(AjaxRequestTarget target) {
model.getObject().getCountry().remove(country);
if (issPeriod) {
addButton.setVisible(true);
countryTextField.setVisible(true);
findButton.setVisible(true);
}
if (target != null)
target.addComponent(rowPanel);
}
});
}
};
countryTextField = new ValidationDisplayableTextField("countryCodeInput", model.bind("oneCountry"), "job.country.value");
**countryView.setReuseItems(true);**
rowPanel.add(countryView);
rowPanel.add(countryTextField);
addButton.setOutputMarkupPlaceholderTag(true);
rowPanel.add(addButton);
And the addButton looks like that:
AjaxSubmitLink addButton = new AjaxSubmitLink(LinkNames.addCountry.toString()) {
#Override
public void onSubmit(AjaxRequestTarget target, Form form) {
if (model.getObject().getOneCountry() != null)
addCountry();
if (target != null)
target.addComponent(rowPanel);
target.addComponent(form.getPage().get("feedbackPanel"));
}
#Override
protected void onError(AjaxRequestTarget target, Form<?> form)
{
onSubmit(target, form);
}
};
The thing is, that when I fail my dateTimeField (e.g. set hours to 100), enter country code in countryTextField, and press on addButton, it displays validation message in feedback panel, that hour range is incorrect, but don't add the country. This is because my model isn't updated. Maybe there is a way to update it manually? So validation message will be displayed, but the country listView still could be updated?
Submit of the whole form is on other button, so logically it is normal to add a country even if there is a validation error in dateTimeField.
Thanks!
P.S. i've read a lot of posts about similar problem, but most of them were solved with .setReuseItems(true), but it doesn't work in my case.
P.P.S Apache wicket 1.4.17
As an update to this answer, in Wicket 6, you can accomplish this by overriding onError() in the Form:
#Override
protected void onError() {
super.onError();
this.updateFormComponentModels();
}
I faced a similar problem in my project, the workaround I found was to use a special Visitor. It will update the model even though the submitted input is invalid.
public class VisitorUpdateModelWithoutValidation implements FormComponent.IVisitor {
public Object formComponent(IFormVisitorParticipant formComponent) {
if (formComponent instanceof FormComponent) {
final FormComponent<?> formComponent1 = (FormComponent<?>) formComponent;
boolean required = formComponent1.isRequired();
if (required) {
formComponent1.setRequired(false);
}
formComponent1.modelChanging();
formComponent1.validate();
formComponent1.updateModel();
formComponent1.modelChanged();
if (required) {
formComponent1.setRequired(true);
}
}
return Component.IVisitor.CONTINUE_TRAVERSAL;
}
}
Simply use it in the onSubmit method of your behavior : getForm().visitFormComponents(new VisitorUpdateModelWithoutValidation());
You can issue a field.clearInput() on the fields you are updating before you target the update(s).