I need to refresh the panel (it has been declared as panel in the below code) after I add a new group. The ItemSelectionComponent component is a different Panel that contains the added groups of a particular person. What I need to do is once I add a new group that particular panel (the ItemSelectionComponent panel with the wicket id "panel") should be refreshed and the newly added group should get displayed.
I currently use
target.addComponent(panel);
to refresh, but it doesn't seems to be working :(
Can someone tell me whats wrong?
thanks!
Your avaiableGroups should be a LoadableDetachableModel that contains your list of GroupSelectionModels. When you use the AjaxSubmitLink get List from the LoadableDetachableModel and add to it.
LoadableDetachableModel<List<GroupSelectionModel>> LDM = new LoadableDetachableModel<List<GroupSelectionModel>>() {
private static final long serialVersionUID = 1L;
#Override
protected String load() {
return ServiceLocator.getInstance().find(GroupService.class).getAllGroups();;
}
};
AjaxSubmitLink addBtn = new AjaxSubmitLink("addBtn") {
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> f) {
List<Group> currentGroups = ServiceLocator.getInstance().find(GroupService.class).getAllGroups();
Group group = new Group();
group.setGroupType(Group.GroupType.EMAIL);
group.setMerchant(merchant);
group.setGroupName(form.getModelObject().getGroupName());
ServiceLocator.getInstance().find(GroupService.class).saveGroup(group);
GroupSelectionModel newGroup = new GroupSelectionModel();
newGroup.setGroup(group);
newGroup.setGroupSelected(true);
LDM.getObject().add(newGroup);
target.addComponent(panel);
}
};
Then pass LDM as a param to ItemSelectionComponent instead of avaiableGroups. Use LDM in ItemSelectionComponent like you did avaiableGroups.
public class ItemSelectionComponent extends Panel{
private static final long serialVersionUID = 6670144847L;
private LoadableDetachableModel<List<GroupSelectionModel>> model;
public ItemSelectionComponent(String id,LoadableDetachableModel<List<GroupSelectionModel>> model){
super(id);
this.model = model;
init();
}
private void init(){
WebMarkupContainer groupSelectionContainer = new WebMarkupContainer("groupSelectionContainer");
RepeatingView repeater = new RepeatingView("groupList");
WebMarkupContainer groupList;
for(final GroupSelectionModel m : model.getObject()){
groupList = new WebMarkupContainer(repeater.newChildId());
WebMarkupContainer groupNameContainer = new WebMarkupContainer("groupNameContainer");
groupNameContainer.add(new Label("groupName", m.getGroup().getGroupName()));
groupList.add(groupNameContainer);
repeater.add(groupList);
}
groupSelectionContainer.add(repeater);
this.add(groupSelectionContainer);
}
}
Hope this helps.
I have one possible solution to your problem.
Add a WebMarkupContainer:
final WebMarkupContainer panelContainer = new WebMarkupContainer("panelContainer");
panelContainer.setOutputMarkupId(true);
And in the html you will have it as:
<div wicket:id="panelContainer"></div>
Then you must add the panel to your markup container:
panelContainer.add(panel)
And add the markup container on the target instead of the panel:
target.addComponent(panelContainer);
If this doesn't work let me know and i will provide further assitance
When you target the panel the components in it will be refreshed. But what happens depends on how "ItemSelectionComponent" is using "avaiableGroups".
Related
I'm quite new using Wicket framework.
Currently I'm working on to set the setEnabled of the TextField. In my case, I have two TextField to control using AjaxCheckbox. During my trial, I have no issue to setEnabled for the first TextField, but when I add second TextField with AjaxCheckbox, the second one didn't work, only the first one.
Is there something that I missed out?
The first one
mobileNo = new TextField<String>("mobileNo", new PropertyModel<String>(getModelObject(), "mobileNo")) {
#Override
protected void onConfigure() {
setEnabled(mobileNoCheckBoxValue);
}
};
mobileNo.setOutputMarkupPlaceholderTag(true);
form.add(mobileNo);
AjaxCheckBox mobileNoCheckBox = new AjaxCheckBox("mobileNoCheckBox", new PropertyModel<Boolean>(this, "mobileNoCheckBoxValue")) {
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(mobileNo);
}
};
form.add(mobileNoCheckBox);
and the second one
appliedAmount = new TextField<BigDecimal>("appliedAmount", new BigDecimalFormatProperty<BigDecimal>(getModel(), "appliedAmount")) {
#Override
protected void onConfigure() {
setEnabled(appliedAmountCheckBoxValue);
}
};
appliedAmount.setOutputMarkupPlaceholderTag(true);
form.add(appliedAmount);
AjaxCheckBox appliedAmountCheckBox = new AjaxCheckBox("appliedAmountCheckBox", new PropertyModel(this, "appliedAmountCheckBoxValue")) {
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(appliedAmount);
}
};
form.add(appliedAmountCheckBox);
Check your HTML code and make sure you use different id attribute values for <input type="checkbox" .../>.
If you have id attribute in your HTML template then better remove it completely and let Wicket to auto-generate it. The ids must be unique by HTML specification. But also Wicket uses them to lookup the HTML elements when sending their values with Ajax.
I guess when you click the second checkbox Wicket sends the state of the first one, which does not toggle.
I'm trying to create a web app via Vaadin (Vaadin Framework 8).
I read several pages of documentation but still, I have big problems concerning the structure of a Vaadin app. My problem is that I lack something about the theory behind it, and I'll try to expose my problems with a first attempt of code. I'll really appreciate anything that can help me understand how Vaadin works.
I want to create a website where a user can register, log in and log out.
The structure of the GUI of the website is an Homepage where there is something like a button or something like that to do the login if the user is not logged, and if the user is logged, instead of the login button, it should appear a logout button.
First thing, I have a class that extends UI; in that class, I set the servlet and the init() method.
In the init() method, I start creating a VerticalLayout(), then a MenuBar and a Panel (called contentPanel). Then, I create a Navigator. The first problem I encounter is that I understand the Navigator as a possibility of browsing between different pages; the constructor of a Navigator wants a SingleComponentContainer, so for now, I don't know how to navigate between different web pages. For my example, in the constructor I use the Panel: new Navigator(this, contentPanel); Then I add different View that will then appear inside the panel. Finally, I navigate to the Welcome page.
MyUI class:
public class MyUI extends UI {
/**
* Class that checks if the user is in the database
* and the psw inserted is correct
*/
public static Authentication AUTH;
public static User user = null;
#WebServlet(value = "/*", asyncSupported= true)
#VaadinServletConfiguration(productionMode = false, ui = MyUI.class)
public static class MyUIServlet extends VaadinServlet {
}
#Override
protected void init(VaadinRequest request) {
AUTH = new Authentication();
VaadinSession.getCurrent().setAttribute("user", user);
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
setContent(layout);
Panel contentPanel = new Panel("Main Panel");
contentPanel.setSizeFull();
new Navigator(this, contentPanel);
getNavigator().addView(LoginPage.NAME, LoginPage.class);
getNavigator().setErrorView(LoginPage.class);
getNavigator().addView(LogoutPage.NAME, LogoutPage.class);
getNavigator().addView(WelcomePage.NAME, WelcomePage.class);
MenuBar.Command welcome = new Command() {
#Override
public void menuSelected(MenuItem selectedItem) {
getNavigator().navigateTo(WelcomePage.NAME);
}
};
MenuBar.Command login = new Command() {
#Override
public void menuSelected(MenuItem selectedItem) {
getNavigator().navigateTo(LoginPage.NAME);
}
};
MenuBar.Command logout = new Command() {
#Override
public void menuSelected(MenuItem selectedItem) {
getNavigator().navigateTo(LogoutPage.NAME);
}
};
MenuBar mainMenu = new MenuBar();
mainMenu.addItem("Welcome", VaadinIcons.ARROW_CIRCLE_LEFT, welcome);
mainMenu.addItem("Login", VaadinIcons.ENTER, login);
mainMenu.addItem("Logout", VaadinIcons.EXIT, logout);
layout.addComponent(mainMenu);
layout.addComponent(contentPanel);
getNavigator().navigateTo(WelcomePage.NAME);
}
}
LoginPage class:
public class LoginPage extends VerticalLayout implements View {
private static final long serialVersionUID = 1L;
public static final String NAME = "loginpage";
public LoginPage(){
Panel panel = new Panel("Login");
panel.setSizeUndefined();
addComponent(panel);
FormLayout content = new FormLayout();
TextField username = new TextField("Username");
content.addComponent(username);
PasswordField password = new PasswordField("Password");
content.addComponent(password);
Button send = new Button("Enter");
send.addClickListener(new Button.ClickListener() {
private static final long serialVersionUID = 1L;
public void buttonClick(ClickEvent event) {
//The authenticate method will returns
//true if the credentials are correct
//false otherwise
if(MyUI.AUTH.authenticate(username.getValue(), password.getValue())){
//In AUTH there is a User field called "user"
//User is a class that represents an user (so it has mail, psw, name etc)
VaadinSession.getCurrent().setAttribute("user", MyUI.AUTH.getUser());
}else{
Notification.show("Invalid credentials", Notification.Type.ERROR_MESSAGE);
}
}
});
content.addComponent(send);
content.setSizeUndefined();
content.setMargin(true);
panel.setContent(content);
setComponentAlignment(panel, Alignment.MIDDLE_CENTER);
}
}
Logout class has the same structure of Login class; there is a logout method:
private void doLogout() {
MyUI.AUTH.setUser(null);
VaadinSession.getCurrent().setAttribute("user", MyUI.AUTH.getUser());
getSession().close();
}
Another problem is: how can I dynamically add components in my layout, basing on the user status (logged or not?)
Next problem is: I didn't understand how to effectively do a logout.
I'll add complete code to facilitate any tests.
public class LogoutPage extends VerticalLayout implements View {
private static final long serialVersionUID = 1L;
public static final String NAME = "logoutpage";
public LogoutPage(){
Panel panel = new Panel("Logout");
panel.setSizeUndefined();
addComponent(panel);
Button logout = new Button("Logout");
logout.addClickListener(e -> doLogout());
addComponent(logout);
}
private void doLogout() {
MyUI.AUTH.setUser(null);
VaadinSession.getCurrent().setAttribute("user", MyUI.AUTH.getUser());
getSession().close();
}
}
______________________________________________________________________________
public class WelcomePage extends VerticalLayout implements View {
private static final long serialVersionUID = 1L;
public static final String NAME = "welcomepage";
public WelcomePage() {
setMargin(true);
setSpacing(true);
Label welcome = new Label("Welcome");
welcome.addStyleName("h1");
addComponent(welcome);
}
#Override
public void enter(ViewChangeEvent event) {
}
}
______________________________________________________________________________
public class Authentication {
private static User user = null;
//those fields should be in user; this is just a test
private String userID = "ID";
private String psw = "psw";
public Authentication() {
}
public void setUser(User user) {
Authentication.user = user;
}
public User getUser(){
return Authentication.user;
}
public Boolean authenticate(String userID, String psw){
if(userID == this.userID && psw == this.psw) {
user = new User();
return true;
}
return false;
}
}
I have seen many users struggling with the vaadin concept.
In short it is not a page-based framework, where you switch to a new page with each mouse click.
Instead it is more like a Swing application, where you have a single gui instance, where you add forms/poups/buttons, modify them and remove them based on user interaction. This is known as a Single-Page Application.
The Navigator is mainly used to allow the user to navigate with the backward/forward buttons of the webbrowser to the "previous" page, or bookmark specific pages.
This link provides some more detailed informations about this concept.
To answer you question:
- Use a single page/nvigation
- When not logged in, show a modal login popup
- When the user correctly enters authentification, remove the popup and show the main content in the vertical layout
- When the user logs out, remove the content from the vertical layout
For your simple use case, there is no need to work with the Navigator or Views
I initially ran into the same issues, which got me interested in Spring and ultimately Vaadin4Spring. Check out https://github.com/peholmst/vaadin4spring/tree/master/samples/security-sample-managed even if you have no interest in using Spring. It will provide you some insight on your View Navigation and with the addition of the Vaadin4Spring Sidebar it can make it easy to control access to views and menus. I am sure permissions will be your focus soon which can be complex.
I need to update the list of a ListSelect after i click in one button but i dont know how to
Here is my code:
Create List Method
private void createListPanel() {
VerticalLayout listPanel = new VerticalLayout();
listPanel.setWidth(100f, Unit.PERCENTAGE);
queryList= new ListSelect("List Of Querys", getQueryList());
queryList.setWidth(100f, Unit.PERCENTAGE);
queryList.setNullSelectionAllowed(false);
queryList.addValueChangeListener(event -> {
selectedQuery = (String) (queryList.getValue());
String retrievedQuery = repository.getRawQuery(selectedQuery);
});
listPanel.addComponent(queryList);
panelSuperior.addComponent(listPanel);
}
getQueryList()
private List<String> getQueryList() {
return repository.getQueryNames();
}
Create Button Method
private void CreateButton() {
Button buttonRefresh= new Button("Refresh");
buttonRefresh.addClickListener((Button.ClickEvent e) -> {
// i tried this
queryList.setContainerDataSource((Container) getQueryList());
});
buttonPanel.addComponent(button);
}
I tried this line at CreateButton() method:
queryList.setContainerDataSource((Container) getQueryList())
but i get a
java.lang.ClassCastException: java.util.ArrayList cannot be cast to com.vaadin.data.Container
because this method need a Container Object
I was searching in the Vaadin javadoc but I am not able to find a method to set or update the list of the ListSelect
Vaadin Javadoc: Vaadin Javadoc 7.7.9 ListSelect
Thanks in advance
The straightforward way is to remove all items from an underlying container and add new items afterward:
Container container = queryList.getContainerDataSource();
container.removAllItems();
List<String> queries = getQueryList();
for(String query : queries) {
container.addItem(query);
}
ListSelect(String caption, Collection<?> options) constructor creates an IndexedContainer and populates it with items from your collection.
Another option is to bind ListSelect to a container which could possibly enable it to track changes automatically. For more on this, see "Collecting Items in Containers" topic from Vaadin docs.
i would like to do Enable/Disable textbox using Checkbox in wicket framework.
here is my code:
List<DeliveryFormat> formatChoices = lookupProcessor.getLookupValues(DeliveryFormat.class);
//add(new RadioChoice("deliveryFormat", formatChoices, new ChoiceRenderer<DeliveryFormat>("label")));
//Add the check boxes for Delivery format
ChoiceRenderer<DeliveryFormat> deliveryFormatShippment = new ChoiceRenderer<DeliveryFormat>("label", "id");
CheckBoxMultipleChoice<DeliveryFormat> deliveryChoices = new CheckBoxMultipleChoice<DeliveryFormat>(
"deliveryFormat", formatChoices, deliveryFormatShippment);
add(deliveryChoices);
add(new DeliveryFormatValidator(deliveryChoices));
final WebMarkupContainer deliveryFormatCountryValue = new WebMarkupContainer("deliveryFormatCountry");
deliveryFormatCountryValue.setOutputMarkupId(true);
deliveryFormatCountryValue.setOutputMarkupPlaceholderTag(true);
add(deliveryFormatCountryValue);
deliveryFormatCountryValue.setVisible(DeliveryFormat.DELIVERY_FORMAT_ONE.equals(order.getObject().getDeliveryFormat()));
final TextArea<String> sampleTextArea = new TextArea<String>("address.country");
sampleTextArea.add(StringValidator.maximumLength(250)).add(
InlineErrorFeedback.INSTANCE);
sampleTextArea.setRequired(true);
sampleTextArea.setOutputMarkupId(true);
sampleTextArea.setMarkupId("address.country");
deliveryFormatCountryValue.add(sampleTextArea);
deliveryChoices.add(new AjaxFormComponentUpdatingBehavior("address.country") {
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget target) {
deliveryFormatCountryValue.setVisible(DeliveryFormat.DELIVERY_FORMAT_ONE.equals(order.getObject().getDeliveryFormat()));
target.addComponent(deliveryFormatCountryValue);
}
});
but i unable to do wt ever i want..is any thing wrong in my code?
my HTML page:
USA
The AjaxFormComponentUpdatingBehavior you are using expects the name of the JavaScript event you want to listen for and not the markup id of an HTML element, as you provided to it.
So for example new AjaxFormComponentUpdatingBehavior("change") would be correct.
In your case you could even use an OnChangeAjaxBehavior, since it's exactly made for the type of event you are trying to listen for.
You need to change this statement
deliveryChoices.add(new AjaxFormComponentUpdatingBehavior("address.country") {
to
deliveryChoices.add(new AjaxFormComponentUpdatingBehavior("onchange") {1
I have a simple, mysterious problem with a label and using ajax to show it.
public class ChecklistTemplateForm extends Form{
private static final long serialVersionUID = 1L;
private Label cantSaveLabel;
public ChecklistTemplateForm(String id) {
super(id);
cantSaveLabel = new Label("cantSaveLabel", "Name is not unique, enter another name and try saving again.");
cantSaveLabel.setVisible(false);
cantSaveLabel.setOutputMarkupId(true);
add(cantSaveLabel);
add(new AjaxButton("saveButton") {
private static final long serialVersionUID = 1L;
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
target.addComponent(cantSaveLabel);
//here i do some stuff to decide if canSave is true or false
if (canSave){
setResponsePage(AdminCheckListPage.class);
}
else if (!canSave){
cantSaveLabel.setVisible(true);
System.out.println(canSave);
}
}
});
}
}
The funny thing is, is canSave is false, the System.out.print works but the cansavelabel never becomes visible. What am I missing?
You have to tell wicket that it should use a placeholder for you label because it can't update a component that doesn't exist in the markup.
cantSaveLabel.setOutputMarkupId(true);
cantSaveLabel.setOutputMarkupPlaceholderTag(true);
You can not update the Label via Ajax as it is not in the rendered page. The
cantSaveLabel.setVisible(false);
makes it so that the Label is not in the HTML. You would need to surround the Label with another component (WebMarkupContainer), call setOutputMarkupId(true) on this and add this container to the AjaxRequestTarget instaed of the label.