I want to make a colspan in a display:column so I tried to do it as follows:
<display:column style="width=50% colspan=2 " title="${textResources['Exam.endDate']}">
but it doesn't work it seems that this property is not allowed in a display:column so how to do that?
To add a colspan to the display column you have to create a Table Decorator extends the TableDecorator class, override the method init, in this method you need to get the header for your cell and add the colspan attribute.
package org.hannibal.utils.view.decorators;
import java.util.List;
import javax.servlet.jsp.PageContext;
import org.displaytag.decorator.TableDecorator;
import org.displaytag.model.HeaderCell;
import org.displaytag.model.TableModel;
import org.displaytag.util.HtmlAttributeMap;
public class ColspanTableDecorator extends TableDecorator {
#Override
public void init(PageContext pageContext, Object decorated,
TableModel tableModel) {
super.init(pageContext, decorated, tableModel);
List headersList = tableModel.getHeaderCellList();
HeaderCell myHeader = (HeaderCell)headersList.get(0);
HtmlAttributeMap map = myHeader.getHeaderAttributes();
map.put("colSpan", "2");
}
}
And in the jsp I use it so.
<display:table name="sessionScope.employees" pagesize="10" cellpadding="2" cellspacing="0"
decorator="org.hannibal.utils.view.decorators.ColspanTableDecorator">
I hope this will help you
Related
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 am a newbie to play and have started to develop an application to fetch the data from database.
I have the following code in my application:
public static Result list() {
List products = Productslist.getListOfProducts();
return ok(index.render(products));
}
and this gives me the following error:
Actual List cannot be converted to String on method invocation conversion
You can also view my index.scala.html
#{extends 'main.html' /}
#{set title:'Cars in the car lot' /}
<h1>Products in Lot</h1>
<table border=1>
<tr>
<td>productname</td>
<td>Quantity</td>
<td>Price</td>
</tr>
#{list items:products, as:'product'}
<tr>
<td>${product.getProductname()}</td>
<td>${product.getQuantity()}</td>
<td>${product.getPrice()}</td>
</tr>
#{/list}
</table>
The complete code for Application.java is:
package controllers;
import play.*;
import play.mvc.*;
import models.Productslist;
import views.html.*;
import views.*;
import java.util.*;
public class Application extends Controller
{
public static Result list()
{
List products = Productslist.getListOfProducts();
return ok(index.render(products));
}
}
Can anyone help me find the source of the error?
Look like you used the wrong code for the view. Try this instead
#(products: List[Productslist])
#import helper._
#main("Product list") {
<h1>#product.size() product(s)</h1>
<ul>
#for(product <- products) {
<li>
#product.name
</li>
}
</ul>
}
Use play clean-all before running your server
Looks like error is happening on index.render(products) ; where method render is expecting a string but we are passing list. Can you put in the code of method render()
I will want to use Data binding in Java Class rather than
#bind
With each ListCell in Listbox.
I tried with this example
My ZUl File...
<zk>
<window border="normal" title="hello" apply="org.zkoss.bind.BindComposer"
viewModel="#id('vm') #init('com.test.binding.TestRenderer')" >
<button label="ClickMe" id="retrieve"
onClick="#command('onOK')">
</button>
<div height="800px">
<listbox model="#load(vm.model)" itemRenderer="#load(vm.itemRenderer)" vflex="true" multiple="true"/>
</div>
</window>
</zk>
My Java Class or ViewController.....
package com.test.binding;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.zkoss.bind.annotation.AfterCompose;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.zk.ui.Component;
import org.zkoss.zkplus.databind.AnnotateDataBinder;
import org.zkoss.zkplus.databind.Binding;
import org.zkoss.zkplus.databind.BindingListModelList;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Textbox;
public class TestRenderer {
ListModelList model = new ListModelList();
private AnnotateDataBinder binder;
#AfterCompose
public void afterCompose(#ContextParam(ContextType.VIEW) Component view) {
binder = new AnnotateDataBinder(view);
List persons = new ArrayList();
model.add(new Person("David", "Coverdale"));
model.add(new Person("Doug", "Aldrich"));
model.add(new Person("Reb", "Beach"));
model.add(new Person("Michael", "Devin"));
model.add(new Person("Brian", "Tichy"));
binder.loadAll();
}
public void setModel(ListModelList model) {
this.model = model;
}
public ListModel getModel() {
return model;
}
// method for ZK 6
public ListitemRenderer getItemRenderer() {
ListitemRenderer _rowRenderer = null;
if (_rowRenderer == null) {
_rowRenderer = new ListitemRenderer() {
public void render(final Listitem item, Object object,
int index) throws Exception {
final Person dataBean = (Person) object;
binder.bindBean(item.getId() , dataBean);
Listcell cell = new Listcell();
Textbox name = new Textbox();
name.setValue(dataBean.getFirstName());
System.out.println(item.getId()+ "------------------>"+item.getId() + ".name");
//binder.addBinding(name, "value", item.getId()+i + ".name", null, null, "both", null, null, null, null);
//binder.addBinding(name, "value",item.getId() + ".name", new String[] {}, "none", "both", null);
cell.appendChild(name);
//cell.addAnnotation(cell, "bind", null);
cell.setParent(item);
}
};
binder.saveAll();
binder.loadAll();
}
return _rowRenderer;
}
#Command
public void onOK() {
binder.saveAll(); //load Inputfields from Form, Constraints will be performed
binder.loadAll();
Collection<Binding> test = binder.getAllBindings();
System.out.println(model);
}
public class Person {
private String firstName;
private String lastName;
public Person(String fn, String ln) {
setFirstName(fn);
setLastName(ln);
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String fn) {
firstName = fn;
}
public String getLastName() {
return lastName;
}
public void setLastName(String ln) {
lastName = ln;
}
}
#Command
public void clickMe(){
BindingListModelList blml = (BindingListModelList) getModel();
for (Object object : blml) {
System.out.println(Integer.parseInt((String) object));
}
}
}
Can any one give me the Demo Example How Binding should work with
getItemRendered()
In Listbox
Thanks
You are trying to mix different paradigms. You want to use databinding especially MVVM style but also introduce your custom renderer in the process. Even if this works I think it is a VERY bad practice. Either go pure MVVM databinding where you separate your view from model and only define binding in your view or go with pure MVC and use your own renderer to render your model data anyway you want.
The whole point of databinding is to let binder take care of rendering/updating component state based on databinding annotations.
Talking specifically about your sample code here you are using org.zkoss.bind.BindComposer which will init a binder instance automatically and after that you are also explicitly instantiating a separate AnnotateDataBinder in #AfterCompose so there will be conflict between these two.
My suggestion would be to go with pure MVVM databinding by introdcing <template> in your view and let MVVM binder to render this template using #Bind or #Load annotations OR go with pure Java style MVVM databinding as described in this "MVVM in Java" article
In my opinion, using ListitemRenderer with MVVM is not so bad, sometimes it can be the 'bridge' between zul page and ViewModel, and it can be considered as a part of component (since once you assign a model, listbox will use default renderer to render item if you do not assign a template or a custom renderer) (see List Model). If there is nothing bad that assign only model and render items by default renderer, there is nothing bad assign both model and custom renderer to render items.
Let's define what the 'good' is at first:
-- The zul file do not need to know how ViewModel works, just ask for data and trigger command as needed.
-- The ViewModel do not need to know anything in zul page, just provide data and process some predefined event.
Now thinking about a simple scenario like the one described in the official document:
Performing Actions on Events
see this line
onClick="#command('deleteOrder', cartItem=cartItem)"
and this line
public void deleteOrder(#BindingParam("cartItem") CartItem cartItem)
In this case, the zul page need to know bring the param to deleteOrder command while event triggered, and even have to know the param should assign the variable named cartItem in ViewModel. On the other hand, the ViewModel need to retrieve the param passed from zul page.
This is obviously not the 'good' situation.
With the ListitemRenderer, let's say ShoppingcartOrderlistItemRenderer, we can simply post an event to Listbox (e.g., onDeleteOrder) with the required data, then make it becomes
<listbox onDeleteOrder="#command('deleteOrder')" ...
and
public void deleteOrder(#ContextParam(ContextType.TRIGGER_EVENT) DeleteOrderEvent event) {
getShoppingCart().remove(event.getProductId());
}
Rely on an event instead of rely on a param defined in zul page, I think this is more robust.
Finally, still have to say, just personal opinion.
#subodh
You can also try add EventListener in ListitemRenderer and pass some custom event with required data to listbox then bind that custom event to ViewModel, please refer to
the sample project at github and the demo online
Edit:
A related post at my blog: ZK Listbox: Event Processing with Renderer and MVVM
How do I get the code for the line that I edited using the JTable and its listeners?
I'm doing this:
import java.util.Arrays;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
class TableListener implements TableModelListener {
#Override
public void tableChanged(TableModelEvent e) {
if ( e.getType() == TableModelEvent.UPDATE ) {
System.out.println("Updating ...\n");
TableModel model = (TableModel)e.getSource();
String columnName = model.getColumnName(e.getColumn());
Object data = model.getValueAt(e.getFirstRow(), e.getColumn());
System.out.println(Arrays.asList(data));
}
}
}
model.addTableModelListener(new TableListener());
CustomersList lista = new CustomersList();
final JTable table = lista.getTable();
table.setModel(model);
table.setColumnSelectionAllowed(false);
lista.setVisible(true);
I just do not have, or know of no method that returns only the code myself, I also block cell editing in the code ..
Yes, but this getting after edited
The model does not track before/after values. If you want this information you need to do it yourself.
Or, you can use the Table Cell Listener which does this for you.
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
}