Enable/Disable textbox using Checkbox in wicket framework - java

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

Related

Multiple AjaxCheckBox did not work to control setEnabled

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.

Property bind in zul view not happening when event registered by event listner is called and changes the property of view model

I am new zk framework. In my zul file there is a notification count indicator, which is a property of view model and indicates the notification count. When I click on notification indicator it opens a toggle window containing notifications. Here I want to implement that when I read a notification , the count will be reduced by one.
<div class="notification_popup"
viewModel="#id('vm') #init('com.zk.viewmodels.ViewAnnouncementViewModel')">
<a sclass="activity-dropdown" id="announcement_notification" iconSclass="z-icon-bell" popup="ann_notification,position=after_end,type=toggle" tooltiptext="Notifications">
<span class="num"><label value="#bind(vm.announcementCount)"/></span></a>
<popup id="ann_notification" class="header-top-dropdown notification-dropdown">
<vlayout id="vl" sclass="notify-popup">
</vlayout>
</popup>
</div>
#VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
public class ViewAnnouncementViewModel {
private long announcementCount = 0;
#NotifyChange({".", "announcementCount"})
public void setAnnouncementCount(long announcementCount) {
this.announcementCount = announcementCount;
}
#SuppressWarnings("unchecked")
#AfterCompose
public void afterCompose(#ContextParam(ContextType.VIEW) Component view) {
super.afterCompose(view);
Selectors.wireComponents(view,this,false);
Html h1 = new Html();
h1.setContent("<h4>Notifications</h4>");
vl.appendChild(h1);
div = new Div();
div.setId("announcementList");
div = updateAnnouncement(div);
vl.appendChild(div);
}
public Div updateAnnouncement(Div div){
private Collection<AnnouncementResultDTO> searchResults =
announcementService.retrieveAnnouncement(instanceInfo);
announcementCount = searchResults.size();
setAnnouncementCount(announcementCount);
postNotifyChange(this,"announcementCount");
for(final AnnouncementResultDTO pasrDTO:searchResults){
A s1 = new A();
Label l1 = new Label();
l1.setValue("Annoncements");
s1.appendChild(l1);
div.appendChild(s1);
s1.addEventListener("onClick", new EventListener() {
public void onEvent(Event event) throws Exception {
Map<String, Object> map = new HashMap<String,Object>();
announcementCount=announcementCount-1;
setAnnouncementCount(announcementCount);
postNotifyChange(this,"*");
Window window = (Window) Executions.getCurrent().createComponents("announcement_popup.zul",null,map);
window.doModal();
}
});
}
}
But announcementCount is reducing when event fires but it is not reflected in view model.
I think the problem is that if we debug and try to find the value 'this', it will contain object with two inner object , one is view model. Here we can understand that postnotify method receives not a view model, but a wrapper class which contain viewmodel as inner class. I dont know my assumption is true. Please help me
Although you have found the correct way to notify a ViewModel's property. But I recommend you not to mix MVVM and MVC pattern in the same scope. Because MVVM is a pattern that let ZK framework manipulate your components, but MVC is a pattern that you (app developers) manipulate components by yourselves by component API. Sometimes your manipulation might interfere ZK framework's MVVM working and produce an unexpected result. Such case is hard to debug for you. One page in one pattern is recommended.
For example, regarding the code snippets:
for(final AnnouncementResultDTO pasrDTO:searchResults){
A s1 = new A();
Label l1 = new Label();
....
If you need to create multiple component according to a collections, please use
<forEach items="#load(vm.searchResults)">
<label value="Annoncements"
...
</forEach>
Please see Shadow components for details.
I got the solution for this . Use postNotifyChange(ViewAnnouncementViewModel.this,""); inside onEvent() method instead of postNotifyChange(this,"");
s1.addEventListener("onClick", new EventListener() {
public void onEvent(Event event) throws Exception {
Map<String, Object> map = new HashMap<String,Object>();
announcementCount=announcementCount-1;
setAnnouncementCount(announcementCount);
postNotifyChange(ViewAnnouncementViewModel.this,"*");
Window window = (Window) Executions.getCurrent().createComponents("announcement_popup.zul",null,map);
window.doModal();
}
});
Thanks https://www.javacodegeeks.com/2012/07/zk-in-action-mvvm-working-together-with.html

Wicket ajax possible to update border without changing body?

I'm trying to implement a Bootstrap Validated Input field with Help-text and validation icons in Wicket. (http://getbootstrap.com/css/#forms-help-text)
see example
I've encapsulated the TextField and the ComponentFeedbackPanel (BootstrapFieldFeedbackPanel) with a Border (BootstrapFormGroup), where the validation icon and the form-group css-class are controlled.
Problem is, when i update the whole Border after a keyDown/input event, the Textfield gets updated too and the cursor jumps to the beggining, losing the previous insert position. That doesn't happen with a change event, but then the ajax validation occurs only after I leave the field and not during insertion, as desired. Is there a way to update the Border without actually trigerring the update of the Body contents (Textfield)? Do you have another suggestion of how could I encapsulate the Textfield with markup and still be able to control the attributes of the encapsulating form-group/validation icon without changing the content/status of the Textfield itself?
myUrl = new TextField<String>("url");
myUrl.add(new UrlValidator(new String[]{"http", "https"}));
myUrl.setLabel(new StringResourceModel("lbl.myLink", this, null));
myUrl
.setOutputMarkupId(true)
.add(new AjaxFormComponentUpdatingBehavior("oninput") {
private static final long serialVersionUID = 1L;
#Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(myLinkFeedback);
formGroup.setFeedbackStatus(BootstrapFormGroup.VALIDATION_SUCCESS);
target.add(formGroup);
}
#Override
protected void onError(AjaxRequestTarget target, RuntimeException e) {
target.add(myLinkFeedback);
formGroup.setFeedbackStatus(BootstrapFormGroup.VALIDATION_ERROR);
target.add(formGroup);
}
});
formGroup = new BootstrapFormGroup("formGroup", new StringResourceModel("lbl.myLink", this, null));
formGroup.setOutputMarkupId(true);
formGroup.setShowFeedbackStatusIcon(true);
formGroup.add(myUrl);
myLinkFeedback = new BootstrapFieldFeedbackPanel("myLinkFeedbackField", myUrl);
formGroup.add(myLinkFeedback);
form.add(formGroup);
You can introduce method like FormGroup#repaint(AjaxRequestTarget) that adds only the children you want to be repainted.

How to set value on click of link in vaadin

I am new to vaadin. I have one Link like
Link link = new Link("", new ExternalResource(redirectURL));
my requirement is, I have to set value when user clicks the link. Can I add listener when user click the link. Or is there alternate ways of setting value if link is clicked.
To capture onClick on a link or a label, I always create a HorizontalLayout and put the component inside it:
HorizontalLayout hor = new HorizontalLayout();
final Link link = new Link("Click on Me!", new ExternalResource("http://www.google.com"));
hor.addComponent(link);
hor.addLayoutClickListener(new LayoutClickListener() {
#Override
public void layoutClick(LayoutClickEvent event) {
// capture the click here and do whatever you'd like to do, e.g.
// if ( event.getClickedComponent() != null ) {
// if(event.getClickedComponent().equals(link)) {}
}
});
I interpreted your question as changing the caption of the link. As far as I know it's not possibly with the Link component. Take a look at the activelink addon: http://vaadin.com/addon/activelink.
This addon behaves like Link and lets you add a LinkActivatedListener to it. The code should look like this:
final ActiveLink link = new ActiveLink("", new ExternalResource(redirectURL));
link.addListener(new LinkActivatedListener() {
#Override
public void linkActivated(LinkActivatedEvent event) {
link.setCaption("newCaption");
}
});
You could use the new BrowserWindowOpener class:
From the API:
Component extension that opens a browser popup window when the
extended component is clicked.
Example:
BrowserWindowOpener browserWindowOpener = new BrowserWindowOpener(new ExternalResource("http://google.com"));
/*
* Apparently, the BrowserWindowOpener method setWindowName uses the HTML5 target
* attribute (no longer deprecated as it was in HTML4).
* So you can use either a frame name, or one of four special attribute values:
* _blank, _self, _parent, _top
*
* browserWindowOpener.setWindowName();
*/
final Button btn = new Button("Click me");
browserWindowOpener.extend(btn);
btn.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
btn.setCaption("clicked");
}
});
More information here.
I dint work on Vaadin yet But I looked into the document. I found that the Link class internally extends AbstractComponent class which has many functions which you can override. like it has addListener function where you need to pass the Component listener as a parameter and can detect the click event and do whatever you want to.
For reference check this
and this too
Hope this will help :)

The wicket Panel doesn't get refresh on button submit

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".

Categories