i have created an class com.test.test.But
public class But extends Bandbox {
private Label mc_who;
public But() {
Executions.createComponents("/WEB-INF/username.zul", this, null);
Components.wireVariables(this, this, '$', true, true);
Components.addForwards(this, this, '$');
}
public String getWho() {
return mc_who.getValue();
}
public void setWho(String who) {
mc_who.setValue(who);
}
}
and an username.zul
<zk>
<label id="mc_who"></label>
</zk>
and index.zul
<window id="test" >
<bandbox>
<bandpopup>
<username who="Joe"/>
<username who="Hellen"/>
</bandpopup>
</bandbox>
</window>
and i am getting this exception
org.zkoss.zk.ui.UiException: Unsupported parent for row: <Bandpopup g4HQ2>
org.zkoss.zul.Row.beforeParentChanged(Row.java:264)
org.zkoss.zk.ui.AbstractComponent.setParent(AbstractComponent.java:959)
org.zkoss.zk.ui.impl.AbstractUiFactory.newComponent(AbstractUiFactory.java:91)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:714)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:685)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:629)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate(UiEngineImpl.java:596)
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.ja
Your example is not complete since I don't see row (and grid) in your sample code, while the exception said there is one. Please make a sample that can reproduce the issue.
I went through several iterations as well, and found that the most reliable way is to use the div tag as follows:
<zk>
<div>
<label id="mc_who"></label>
</div>
</zk>
This is an example of the component being used:
<window id="test" >
<bandbox>
<bandpopup>
<username who="Joe"/>
<username who="Hellen"/>
</bandpopup>
</bandbox>
</window>
And the source code:
package com.pontusnetworks.zkwidgets;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.IdSpace;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.Div;
import org.zkoss.zul.Row;
import org.zkoss.zul.Textbox;
public class Username extends Div implements IdSpace {
#Wire
private Textbox mc_who; //will be wired when Components.wireVariables is called
public Username() {
//1. Render the template
Executions.createComponents("/composite/username.zul", this, null);
//2. Wire variables, components and event listeners (optional)
Selectors.wireVariables(this, this, null);
Selectors.wireComponents(this, this, false);
Selectors.wireEventListeners(this, this);
}
public String getWho() {
return mc_who.getValue();
}
public void setWho(String who) {
mc_who.setValue(who);
}
//public void onOK() {..} //Add event listeners if required, and wired by Components.addForwards
}
Related
I create widget containing AbsolutePanel using GWT UiBinder like this:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<g:VerticalPanel>
<g:Label>Label1</g:Label>
<g:AbsolutePanel height="500" width="500">
<g:at left='10' top='60'>
<g:Label>Label2</g:Label>
</g:at>
<g:at left='10' top='100'>
<g:Label>Label3</g:Label>
</g:at>
</g:AbsolutePanel>
<g:Label>Label4</g:Label>
</g:VerticalPanel>
</ui:UiBinder>
Than create corresponding class :
public class TestAbsPanelWidget extends Composite {
#UiTemplate("TestAbsPanelWidget.ui.xml")
interface MyUiBinder extends UiBinder<Widget, TestAbsPanelWidget> {}
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
public TestAbsPanelWidget() {
initWidget(uiBinder.createAndBindUi(this));
}
}
Than use it my GWT entry point like this:
public class TestAbsPanel2 implements EntryPoint {
public void onModuleLoad() {
RootPanel.get("div_id").add(new TestAbsPanelWidget());
}
}
After that I see "Label1" and "Label4" on screen in browser, but no "Label2" and "Label3". It seems that AbsolutePanel not shown. What am I doing wrong help me please.
You try to set the panel's width and height with:
<g:AbsolutePanel height="500" width="500">
but you don't specify CSS units. Try:
<g:AbsolutePanel height="500px" width="500px">
and you will see Label2 and Label3.
I am understanding how to handle JS events like onfocus and onblur in apache wicket. I have a simple form in which there is a textfield. "onfocus" event on this I am trying to set the textfield to a value. I have observed on running the code that onfocus is called again and again (recursively it seems). I fail to understand why and what I have done wrong.
Below is the code :
HTML:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<head>
<title>Wicket Examples - component reference</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<form wicket:id="form">
<INPUT wicket:id="input" type="text" name="input" style="WIDTH: 800px" />
</form>
Java:
package com.poc.pages;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.Model;
public class IndexPage extends WebPage
{
/**
* Constructor
*/
public IndexPage()
{
Form form = new Form("form");
TextField<String> TextInput = new TextField<String>("input",Model.of(""));
TextInput.add(new AjaxFormComponentUpdatingBehavior("onfocus"){
#Override
protected void onUpdate(AjaxRequestTarget target) {
String thisValue =
this.getComponent().getDefaultModelObjectAsString();
thisValue = "ChangedNormally";
this.getComponent().setDefaultModelObject("ChangedViaDefaultSetModel");
target.add(this.getComponent());
System.out.println("onfocus"+thisValue);
}
});
form.add(TextInput);
add(form);
}
}
When I focus on textfield here, ChangedViaDefaultSetModel is set and on console onfocusChangedNormally gets print continuously. I fail to undertsand few things :
Why does onfocus gets called again and again printing onfocusChangedNormally evertytime on console?
How can I get the value of actual model and not default model.
WHy does the normal value doesnot get reflected in model whereas on doing setDefaultModel() it works?
Thanks For Help
1) This behavior, you implmented, is a little tricky. When you focus your TextField and add this component to the target, then AjaxRequest is updating it. When update is over, component must return its state, thats why focus gained and your behavior method onUpdate is called again.
To resolve this problem you must use some kind of blocking. The easiest way is to use boolean field and check if focus was already gained to prevent another update. (see the code below).
2) Second and third question is about models, and this is very large subject to discuss. You can learn more by reading this and this articles, or "Wicket in Action" and "Wicket cookbook" books.
In my solution I used PropertyModel, that reflects the value of the field you set as a model of the Component. This code:new PropertyModel<String>(this, "modelValue") means that Wicket must search field with name "modelValue" in this (IndexPage) object and set as the model of TextField. That's why now you can only change this object field to set another value to TextField (don't forget to update component after that).
Comments for code:
I have used AjaxEventBehavior but it's ok to use AjaxFormComponentUpdatingBehavior.
I have added onblur behavior to return old value of the TextField just to show possibilities of this solution.
I have changed TextInput to textInput because code conventions said so.
package com.poc.pages;
import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
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.model.PropertyModel;
public class IndexPage extends WebPage {
private String modelValue = "ChangedNormally";
private boolean focusGained = false;
public IndexPage() {
Form form = new Form("form");
TextField<String> textInput = new TextField<String>("input", new PropertyModel<String>(this, "modelValue"));
textInput.add(new AjaxEventBehavior( "onfocus" ) {
#Override
protected void onEvent(AjaxRequestTarget target) {
if (!focusGained) {
modelValue = "ChangedViaDefaultSetModel";
target.add(this.getComponent());
focusGained = true;
System.out.println( "focus gained " + getComponent().getDefaultModelObject() );
}
}
});
textInput.add(new AjaxEventBehavior( "onblur" ) {
#Override
protected void onEvent(AjaxRequestTarget target) {
modelValue = "ChangedNormally";
target.add(this.getComponent());
focusGained = false;
System.out.println( "focus lost " + getComponent().getDefaultModelObject() );
}
});
form.add(textInput);
add(form);
}
}
Hope this helps.
I'm learning the development flow of Play Framework following this tutorial http://www.playframework.com/documentation/2.1.1/JavaTodoList.
However I'm getting this compilation error at index.scala.html view:
"value description is not a member of Product"
It's my Product's model:
package app.models;
import java.util.*;
import javax.validation.*;
import play.data.validation.Constraints.*;
/**
* Product.
*/
public class Product
{
public int id;
public String name;
public String description;
public String dimensions;
public double price;
public static List<Product> all()
{
return new ArrayList<Product>();
}
public static void create(Product product)
{
return;
}
public static void delete(Long id)
{
return;
}
}
And here is the view's code:
#(products: List[Product], productForm: Form[Product])
#import helper._
#main("ezbuy") {
<h1>#products.size() product(s)</h1>
<ul>
#for(product <- products) {
<li>
#product.description
#form(routes.Application.deleteProduct(product.id)) {
<input type="submit" value="Delete">
}
</li>
}
</ul>
<h2>Add a new product</h2>
#form(routes.Application.newProduct()) {
#inputText(productForm("label"))
<input type="submit" value="Create">
}
}
I'm just not finding where is the problem, since I've declared the Product's list at the top of the view and it's looping using the #for statement.
Thanks in advance.
There is a Scala class scala.Product (http://www.scala-lang.org/api/current/index.html#scala.Product). Scala automatically imports all from the scala package. I think you got that class and not app.models.Product.
Use the fully qualified class name:
#(products: List[app.models.Product], productForm: Form[app.models.Product])
That error does not occur if you put Product directly into the models package, since models.* are imported by default in Scala templates of Play. So there would be no need to use the fully qualified class name.
in my current project i've faced a problem of customizing IndicatingAjaxLink in wicket, is there any solution to change standart gif image to my own?
For example we have following listeneer
add(new IndicatingAjaxLink("closeReceivedBillspanel") {
public void onClick(AjaxRequestTarget art) {
// some timeconsuming calculations
}
});
as user clicks this link, the gif with loading appears, and i want to change this gif, is there any solution for this problem?
Have your page implements the IAjaxIndicatorAware interface
public class BasePage extends WebPage implements IAjaxIndicatorAware {
public BasePage(final PageParameters parameters) {
// Home link
AjaxLink<Page> homeLink = new AjaxLink<Page>("homeLink") {
private static final long serialVersionUID = 1L;
#Override
public void onClick(AjaxRequestTarget target) {
setResponsePage(HomePage.class);
}
};
add(homeLink);
}
#Override
public String getAjaxIndicatorMarkupId() {
return "indicator";
}
This way, you can set, in the html, any image you want to display when the loading appears by changing the image in the "img" tag
<div id="indicator" style="display: none;">
<div class="indicator-content">
Please wait... <wicket:link><img src="images/loading.gif" width="16" height="16" alt="loading" /></wicket:link>
</div>
</div>
Create yoru own custom class like, (copy whats inside IndicatingAjaxLink and update)
public class MyIndicatingAjaxLink<T> extends AjaxLink<T> implements IAjaxIndicatorAware {
private final MyAjaxIndicatorAppender indicatorAppender = new MyAjaxIndicatorAppender();
.
//rest of the code is same as IndicatingAjaxLink class
.
}
Also you need a custom AjaxIndicatorAppender within your customIndicatingAjaxLink and you need to override below method of indicatorAppender to return path of your custom image
protected CharSequence getIndicatorUrl()
Let's say the following XML is given:
<?xml version="1.0" encoding="UTF-8"?>
<ResC>
<Err text="Error text 1"/>
<ConRes>
<Err text="Error text 2"/>
<ConList>
<Err text="Error text 3"/>
<Con>
<Err text="Error text 4"/>
</Con>
</ConList>
</ConRes>
</ResC>
As you can see the <Err> element may appear on every level of the XML.
Using Simple I would like to deserialize this XML. So, I have created the following class:
#Element(required=false)
public class Err {
#Attribute
private String text;
public void setText(String text) { this.text = text; }
public String getText() { return text; }
}
However, how do I have to annotate the classes for <ResC>, <ConRes>, <ConList> and <Con>? Do I really have to declare an attribute of type <Err> in every single class in which it may appear? This seems like a lot of overhead. If so, then I would have to check every single object if it contains an error.
Is there any better and easier way? :-)
Thanks,
Robert
The important thing to remember is that Simple XML should be able to follow any structure that you can logically generate using classes. So you could just create a BaseClass that uses an error interface and applies the Decorator pattern so that it passes all of that through to a concrete error class without any of the implementing objects needing to know what they have been given.
That probably made no sense. How about I just show you...okay...I just went away and implemented exactly what I was thinking and here are the results (full code link):
The Main File:
package com.massaiolir.simple.iface;
import java.io.File;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
public class Main {
public static void main(String[] args) throws Exception {
Serializer serial = new Persister();
ResC resc = serial.read(ResC.class, new File("data/testdata.xml"));
System.out.println(" == Printing out all of the error text. == ");
System.out.println(resc.getErrorText());
System.out.println(resc.conRes.getErrorText());
System.out.println(resc.conRes.conList.getErrorText());
for (Con con : resc.conRes.conList.cons) {
System.out.println(con.getErrorText());
}
System.out.println(" == Finished printing out all of the error text. == ");
}
}
It just runs simple and displays the results.
The BaseObject.java class:
package com.massaiolir.simple.iface;
import org.simpleframework.xml.Element;
public class BaseObject implements Error {
#Element(name = "Err", required = false, type = ConcreteError.class)
private Error err;
#Override
public String getErrorText() {
return err.getErrorText();
}
#Override
public void setErrorText(String errorText) {
err.setErrorText(errorText);
}
}
This is the class that everything should extend if it wants 'Err'.
The Error interface:
package com.massaiolir.simple.iface;
public interface Error {
void setErrorText(String errorText);
String getErrorText();
}
The ConcreteError class:
package com.massaiolir.simple.iface;
import org.simpleframework.xml.Attribute;
public class ConcreteError implements Error {
#Attribute
private String text;
#Override
public String getErrorText() {
return text;
}
#Override
public void setErrorText(String errorText) {
this.text = errorText;
}
}
The actual implementing classes are after this point. You will see that they are rather trivial because the real work is being handled in the classes above.
The Con class:
package com.massaiolir.simple.iface;
public class Con extends BaseObject {
}
The ConList class:
package com.massaiolir.simple.iface;
import java.util.ArrayList;
import org.simpleframework.xml.ElementList;
public class ConList extends BaseObject {
#ElementList(entry = "Con", inline = true)
public ArrayList<Con> cons;
}
The ConRes class:
package com.massaiolir.simple.iface;
import org.simpleframework.xml.Element;
public class ConRes extends BaseObject {
#Element(name = "ConList")
public ConList conList;
}
The ResC class:
package com.massaiolir.simple.iface;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
#Root
public class ResC extends BaseObject {
#Element(name = "ConRes")
public ConRes conRes;
}
And that is all that there is to it. Pretty simple right. I was able to bang that all out in ten minutes. It actually took me longer to write this response than it took me to write the code that I am giving you. If you do not understand anything about the code that I have just written then please let me know. I hope this helps you to understand how you might go about doing something like this.