The following code seems to work fine on all of the browsers I have tried, except for Firefox 3.6.x.
What happens is that on each key up of invalid email address I get a duplicate error message appearing. This means that the error messages soon expand down the page.
Have I missed something or is it just a bug in Wicket or Firefox 3.6? (this is with Wicket 1.4.x - I just upgraded to 1.4.18 in the hopes that it was fixed there, I also tried some older versions of 1.4.x as well, and the latest 5.1 RC).
package com.mycompany;
import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.form.AjaxFormValidatingBehavior;
import org.apache.wicket.extensions.validation.validator.RfcCompliantEmailAddressValidator;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
import org.apache.wicket.util.time.Duration;
public class HomePage extends WebPage
{
private static final long serialVersionUID = 1L;
public HomePage(final PageParameters parameters)
{
add(new FormX());
}
private class FormX
extends Form<Void>
{
FormX()
{
super("form");
final TextField<String> field;
final ComponentFeedbackPanel feedback;
field = new TextField<String>("a");
field.add(RfcCompliantEmailAddressValidator.getInstance());
field.setRequired(true);
field.setOutputMarkupId(true);
feedback = new ComponentFeedbackPanel("b", field);
feedback.setOutputMarkupId(true);
add(field);
add(feedback);
AjaxFormValidatingBehavior.addToAllFormComponents(this,
"onkeyup",
Duration.milliseconds(250));
}
}
}
<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
<head>
<title>Wicket Quickstart Archetype Homepage</title>
</head>
<body>
<strong>Wicket Quickstart Archetype Homepage</strong>
<br/><br/>
<form wicket:id="form">
<input class="in" type="text" wicket:id="a"/>
<label wicket:id="b">[Feedback]</label>
</form>
</body>
</html>
Turns out you need to use <span wicket:id="b"></span> instead of label.
Related
The site structure is as like this in my aem project.
For the footer component i am using following code :-
<div class="ftrsection" data-sly-repeat="${currentPage.listChildren}">
<h3 data-sly-test.child="${item.title}" >${child}</h3>
<ul class="footermenu">
<li data-sly-repeat.subpage="${item.listChildren}">
${subpage.title}
</li>
</ul>
</div>
When i am in the home page it takes it as current page in the first line of the code and displays the site hierarchy in the footer perfectly as this
But when i am in a inner page( here explore page) it takes it as currectPage and displays the footer as this which i dont want . i want it to be constant through out the whole site. How to make it constant?
You can create a Java Use Object (for example Footer.java that allows you to always get the correct root page for your website. You can then invoke it like:
data-sly-use.footer=“Footer” data-sly-repeat=“${footer.rootPage.listChildren}”
It is solved. Had to create a helper class to find the correct root.
File :Footer.java
package com.csmpl.bbsr.me.core.models;
import java.util.*;
import java.util.Iterator;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageFilter;
import com.adobe.cq.sightly.WCMUsePojo;
public class Footer extends WCMUsePojo{
private List<Page> items = new ArrayList<Page>();
private Page rootPage;
// Initializes the navigation
#Override
public void activate() throws Exception {
rootPage = getCurrentPage().getAbsoluteParent(2);
if (rootPage == null) {
rootPage = getCurrentPage();
}
Iterator<Page> childPages = rootPage.listChildren(new PageFilter(getRequest()));
while (childPages.hasNext()) {
items.add(childPages.next());
}
}
// Returns the navigation items
public List<Page> getItems() {
return items;
}
// Returns the navigation root
public Page getRoot() {
return rootPage;
}
}
Then had to access the class in the footer's htl like:
<div class="ftrsection" data-sly-use.footer="com.csmpl.bbsr.me.core.models.Footer" data-sly-repeat="${footer.root.listChildren}">
<h3 data-sly-test.child="${item.title}" >${child}</h3>
<ul class="footermenu">
<li data-sly-repeat.subpage="${item.listChildren}">
${subpage.title}
</li>
</ul>
</div>
And it worked. Hope it helps. :)
I have an integer field and when i enter a non integer value (let's say a symbolic one) the Feedback panel should be triggered automatically with default message, but it does not work, I have to call it in onError method of the form by method error().
This is the textField, that i use:
RequiredTextField<Integer> intField =
new RequiredTextField<>("intValue", integerValue,Integer.class);
this is my simple FeedBackPanel:
fragment.add(new FeedbackPanel("feedback"));
it works only when i call method error() in method onError() of the form.
Could you show us how you create your Form and the Model you use? As far as I understand it you will want to bind a Model to your Fields. My best guess is that your Model does not have a property "intValue".
You might want to (re)visit the Wicket Wiki "More on Models".
I'm not sure how you are setting your model. And once you add RequiredTextField it will not allow you empty and since you set the Integer type it will not allow characters to be entered.
I have tried some code snippet which is working perfectly and validating.
HomePage.html
<html xmlns:wicket="http://wicket.apache.org">
<body>
<form wicket:id="someForm">
<div wicket:id="feedback"></div>
<input type="text" wicket:id="requiredText">
<input type="submit" value="submit">
</form>
</body>
</html>
HomePage.Java
public class HomePage extends WebPage {
private static final long serialVersionUID = 1L;
public HomePage(final PageParameters parameters) {
super(parameters);
Form form = new Form("someForm");
form.add(new FeedbackPanel("feedback"));
IModel integerValue= Model.of("");
form.add(new RequiredTextField("requiredText",integerValue,Integer.class));
add(form);
}
}
Please let me get back to me on this incase if you need anything .
We are using 1.4.9 for our current webapp. But we want to upgrade to higher 1.4.x version preferably 1.4.22(latest 1.4). The problem is that the page won't submit if AjaxButton is clicked. This is working in 1.4.9. I put breakpoint on the onSubmit of that button but it is not going there. Any insights on this? Thanks!
Here is the code:
For the button:
public abstract class SXIButton extends AjaxButton {
public SXIButton(String id, Form form) {
super(id, form);
initialize();
add(new SimpleAttributeModifier("validating", "false"));
}
}
In the java:
searchForm.add(new SXIButton("searchButton", searchForm) {
private static final long serialVersionUID = -4366670520053224476L;
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
LOG.info("Searching Users");
target.addComponent(userContainer);
userSearchModel.setUserCurrentUserFilter(getSessionBOUser().getCd());
UserDataProvider udp = new UserDataProvider(userSearchModel,isForSearch);
udp.setSort("cd", true);
userContainer.addOrReplace(getResultPanel(udp));
}
});
add(portlet);
portlet.add(searchForm);
in html
<input type = "submit" wicket:id = "searchButton" wicket:message="value:button.search" />
Without any code it's hard to help you out. I would first check the changelog to see if anything was changed in a later version that might causes you trouble (e.g. this ticket). If you cannot find anything obvious you might want to update first to another version which is not the latest one, to narrow down in which version your code breaks for the first time.
But those are just shots in the dark.
I am using DockLayoutPanel as my main panel.
Dependent of the menu I click I change the center-part of the DLP.
For example I change either to form1.ui.xml or to form2.ui.xml.
Both of these forms have a "marker" implemented to display an error message:
<g:HTMLPanel ui:field="messageblock"/>
I am following the MVP Pattern (I use EventBus for communication) and so far everything works great. The only thing I can't figure out is how to replace the content of messageblock. Or to be more concret how to get access to messageblock from my MainPresenter. The main idea behind this stuff is to bundle the error-handling in one presenter...
I am looking for something like
final Panel panel = DockLayoutPanel.get("messageblock");
panel.add(subwidget);
I appreciate every hint...
You could either make the Display responsible for rendering the error (make some interface with a renderError(Error) method) or make the Display return an HTMLPanel that something else can render the error into (some interface with a HTMLPanel getErrorPanel() method). The latter is closest to what you're talking about. Have Form1 and Form2 both implement HasErrorPanel and then call getErrorPanel().add(subWidget).
Here is the conclusion I came to. Maybe it helps someone else.
It's based on what Riley Lark recommended - Thanks to Riley btw.
RegistrationPresenter here is responsible for the registration process and shows a registration form to the user. The error-message should be displayed as close as possible to the place where the error occurred.
Without error http://www.mikemitterer.at/fileadmin/stacktrace_imagehosting/screenshot-778.jpg
An error occurred:
Error popped up http://www.mikemitterer.at/fileadmin/stacktrace_imagehosting/screenshot-780.jpg
Here now a rough description how I implemented this behavior:
public class RegistrationPresenter implements Presenter {
public interface Display extends StatusDisplay, HasMessageBlock {
Widget asWidget();
void setData(RegistrationTO registration);
}
private final Display display;
private final EventBus eventBus;
...
as you can see it's Display implements HasMessageBlock:
public interface HasMessageBlock {
void showMessage(Message message);
void hideMessage();
}
There exists a UIBinder-Widget MessageBlock (MessageBlock.ui.xml + MessageBlock.java)
(messageblock will be turned to invisible in it's constructor)
<g:HTMLPanel styleName="errorblock" ui:field="messageblock">
<div id="errorMsg" class="flurid">
<div class="row">
<div class="column width_15/16">
<h3><ui:msg key="errorblock.headline">An error occurred...</ui:msg></h3>
</div>
<div class="column orientation-right islink width_1/16">
<g:Image resource='{res.xgray}' ui:field="image" />
</div>
...
The Registration-Widget now includes MessageBlock
<g:HTMLPanel styleName="registration" ui:field="panel">
<div class="uniForm maxgrid700">
<h1>
<ui:msg key="registration.headline">Registration</ui:msg>
</h1>
<c:MessageBlock ui:field="messageblock"/>
<div class="ctrlHolder">
<p class="label">
<em></em>
<ui:msg key="registration.name">Name:</ui:msg>
</p>
...
Now, if someone fires a Message
eventbus.fireEvent(new MessageEvent(new MessageImpl(Message.MESSAGETYPE.ERROR, "Server Error Message")));
every Presenter which has "HasMessageBlock" for it's Display can process/display the message:
eventBus.addHandler(MessageEvent.TYPE, new MessageEventHandler() {
#Override
public void execute(final MessageEvent event) {
display.showMessage(event.getMessage());
}
});
I'm stuck -
I need to have a Wicket Panel be able to add a class attribute to the <body> tag of whatever page it's on.
Example usage:
Java:
add(new SpecialSidebarComponent("sidebar"));
Generated HTML:
<body class="sidebar">
...
<div id="sidebar">My Wicket Panel</div>
...
</body>
I cannot add a wicket:id and make the body a Wicket component, because this makes it very difficult to add components to a page in the big page hierarchy I have, and it still also doesn't easily allow for a Panel to modify the body attribute.
I thought BodyTagAttributeModifier may be for this, but apparently it is for something else and cannot get it to function ( Wicket: how to use the BodyTagAttributeModifier class? )
Any helpful ideas?
Update:
In looking at it, it appears the BodyTagAttributeModifier class is only for a Panel's parent tag, not the Page's <body> tag:
Example (Scala syntax):
class Home extends WebPage {
add(new Sidebar("sidebar"))
}
class Sidebar(id: String) extends Panel(id) {
add(new BodyTagAttributeModifier("class", true, new Model("layout-class"), getParent))
}
Template:
<html>
<body>
<div wicket:id="sidebar">Sidebar</div>
</body>
</html>
Rendered:
<html>
<body>
<div class="layout-class">
<h1>Hello World!</h1>
</div>
</body>
</html>
Very confusing name IMHO. Doesn't solve the issue but at least makes more sense.
I personally think the Javascript option is the cleanest for this specific case. However, your comment about add(Component...) being final leads me to believe that you might be interested in the setTransparentResolver(true) method. Here's how it works...
BasePage.html
<body wicket:id="body">
<div wicket:id="panel" />
</body>
BasePage.java
public class BasePage extends Page {
public String bodyClass = "";
public BasePage() {
super();
WebMarkupContainer bodyContainer = new WebMarkupContainer("body");
bodyContainer.setTransparentResolver(true);
bodyContainer.add(new SimpleAttributeModifier("class", new PropertyModel<String>(this, "bodyClass")));
}
}
MyPage.java (extends BasePage)
public class MyPage extends BasePage {
public MyPage() {
super();
add(new SidebarPanel("panel"));
super.bodyClass = "sidebar";
}
}
Even though you are not adding the SidebarPanel directly to the bodyContainer in the BasePage, it will still work out because of setTransparentResolver(true).
For your simple case, go with the Javascript. For the general issue of feeling constrained by subclasses not being able to fit inside containers, be aware of transparent resolving.
If you really can't give the <body> tag a wicket:id (I'll assume you don't have a BasePage that every, or almost every, other page extends in which to abstract this), it'll be not possible to know at page render time (when that <body> tag is rendered) what class to append to it, it will be simply copied as is from your HTML to the output.
You could achieve the same via javascript, however. Make your Panel implement IHeaderContributor and use IHeaderResponse.renderOnDomReadyJavscript().
public abstract class SpecialSidebarComponent(String id) extends Panel
implements IHeaderContributor {
.....
public void renderHead(IHeaderResponse response){
String javascript = "document.body.setAttribute('class', 'sidebar');";
response.renderOnDomReadyJavascript(javascript);
}
....
}
I think you were on the right track with BodyTagAttributeModifier, at least according to JavaDoc. The compilation problems in the linked article stem from the use of a non-existing Constructor...
in SpecialSidebarComponent you should be able to do this:
add(new BodyTagAttributeModifier("class", Model.of("sidebar"), this));
Can't try this right now because I'm not at my development computer...