Revision history [back]

click to hide/show revision 1
initial version

answered 2012-02-24 03:09:26 +0800

benbai gravatar image benbai

http://www.zkoss.org

Just point out in stead of make it nested then workaround restrict this or prevent that, prevent the nested directly is another choice.

Another way is make the parent to keep the binding bean for BindingMacro child, please refer to the sample below.

In first case there are four macro component with binding with respect to the specified bean name, two of them are nested and the other two are not, all work fine.

In second case there are two macro component with binding, one is nested and the other is not, both work fine.

test with 5.0.8 or later:

consider multiple macro with dynamic bean name:

ZKFiddle-Link

MacroComposer.java

package jtsptbo$v2;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.util.GenericForwardComposer;

public class MacroComposer extends GenericForwardComposer {
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        String beanName = ((MacroComp)comp.getParent().getParent()).getBeanName();
        Executions.createComponentsDirectly("<label id=\"mc_label\" value=\"@{"+beanName+".time}\" />", null, comp, null);
    }
}

Bean.java

package jtsptbo$v2;


import java.util.Date;

public class Bean {
    String _entity;
    public Bean (String entity) {
        _entity = entity;
    }
    public String getTime() {
        return _entity + " time: " + new Date(System.currentTimeMillis()).toString();
    }
}

BindingMacro.java

package jtsptbo$v2;

import org.zkoss.zkplus.databind.AnnotateDataBinder;

public interface BindingMacro {
    /**
     * return whether this component has binding
     */
    public boolean hasBinding();
    /**
     * put all binding to another binder
     */
    public void delegateBinding(AnnotateDataBinder adb);
}

MacroComp.java

package jtsptbo$v2;

import org.zkoss.zk.ui.HtmlMacroComponent;
import org.zkoss.zkplus.databind.AnnotateDataBinder;

public class MacroComp extends HtmlMacroComponent implements BindingMacro {
    Bean b;
    String _beanName;
    boolean _hasBinding = true;
    public void afterCompose() {
        super.afterCompose();
        b = new Bean(_beanName);
        AnnotateDataBinder binderOne = (AnnotateDataBinder)getFirstChild().getAttribute("binder");
        binderOne.bindBean(_beanName, b);
        binderOne.loadAll();
    }
    /**
     * return whether this component has binding
     */
    public boolean hasBinding() {
        return _hasBinding;
    }
    /**
     * put all binding to another binder
     */
    public void delegateBinding(AnnotateDataBinder adb) {
        adb.bindBean(_beanName, b);
        getFirstChild().setAttribute("binder", null);
        _hasBinding = false;
    }
    public void setBeanName(String beanName) {
        _beanName = beanName;
    }
    public String getBeanName() {
        return _beanName;
    }
}

TestComposer.java

package jtsptbo$v2;


import java.util.*;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zkplus.databind.AnnotateDataBinder;

public class TestComposer extends GenericForwardComposer {
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        // get the binder of this composer
        AnnotateDataBinder binderTwo = (AnnotateDataBinder)comp.getAttribute("binder");
        List<Component> children = comp.getChildren();
        for (Component c : children) {
            if (c instanceof BindingMacro) {
                // if the child is a BindingMacro and has binding,
                // get binding from it
                BindingMacro bc = (BindingMacro) c;
                if (bc.hasBinding())
                    bc.delegateBinding(binderTwo);
            }
        }
        binderTwo.bindBean("beanTwo", new Bean(" outer div"));
        binderTwo.loadAll();
    }
}

macrocomp.zul

<zk>
    <window style="display: inline-block;" apply="org.zkoss.zkplus.databind.AnnotateDataBindingComposer">
        <window id="mc_innerWin" apply="jtsptbo$v2.MacroComposer">

        </window>
    </window>
</zk>

index.zul

<?component name="macrocomp" macroURI="macrocomp.zul"
   class="jtsptbo$v2.MacroComp"?>
<zk>
    <div apply="org.zkoss.zkplus.databind.AnnotateDataBindingComposer,jtsptbo$v2.TestComposer">
        <label id="windowLabel" value="@{beanTwo.time}" /><div></div>
        <!-- There is another AnnotateDataBindingComposer
            and bind another bean in macrocomp -->
        <macrocomp beanName="firstMacro" /><div></div>
        <macrocomp beanName="secondMacro" />
    </div>
    <macrocomp beanName="thirdMacro" /><div></div>
    <macrocomp beanName="4thMacro" />
</zk>

allowed only one macro in nested:

ZKFiddle-Link

Bean.java

package jtsptbo$v1;


import java.util.Date;

public class Bean {
    public String getTime() {
        return "time: " + new Date(System.currentTimeMillis()).toString();
    }
}

BindingMacro.java

package jtsptbo$v1;

import org.zkoss.zkplus.databind.AnnotateDataBinder;

public interface BindingMacro {
    /**
     * return whether this component has binding
     */
    public boolean hasBinding();
    /**
     * put all binding to another binder
     */
    public void delegateBinding(AnnotateDataBinder adb);
}

MacroComp.java

package jtsptbo$v1;

import org.zkoss.zk.ui.HtmlMacroComponent;
import org.zkoss.zkplus.databind.AnnotateDataBinder;

public class MacroComp extends HtmlMacroComponent implements BindingMacro {
    Bean b = new Bean();
    boolean _hasBinding = true;
    public void afterCompose() {
        super.afterCompose();
        AnnotateDataBinder binderOne = (AnnotateDataBinder)getFirstChild().getAttribute("binder");
        binderOne.bindBean("bean", b);
        getFirstChild().getFellow("mc_label");
        binderOne.loadAll();
    }
    /**
     * return whether this component has binding
     */
    public boolean hasBinding() {
        return _hasBinding;
    }
    /**
     * put all binding to another binder
     */
    public void delegateBinding(AnnotateDataBinder adb) {
        adb.bindBean("bean", b);
        getFirstChild().setAttribute("binder", null);
        _hasBinding = false;
    }
}

TestComposer.java

package jtsptbo$v1;

import java.util.*;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zkplus.databind.AnnotateDataBinder;

public class TestComposer extends GenericForwardComposer {
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        // get the binder of this composer
        AnnotateDataBinder binderTwo = (AnnotateDataBinder)comp.getAttribute("binder");
        List<Component> children = comp.getChildren();
        for (Component c : children) {
            if (c instanceof BindingMacro) {
                // if the child is a BindingMacro and has binding,
                // get binding from it
                BindingMacro bc = (BindingMacro) c;
                if (bc.hasBinding())
                    bc.delegateBinding(binderTwo);
            }
        }
        binderTwo.bindBean("beanTwo", new Bean());
        binderTwo.loadAll();
    }
}

macrocomp.zul

<zk>
    <window style="display: inline-block;" apply="org.zkoss.zkplus.databind.AnnotateDataBindingComposer">
        <label id="mc_label" value="@{bean.time}" />
    </window>
</zk>

index.zul

<?component name="macrocomp" macroURI="macrocomp.zul"
   class="jtsptbo$v1.MacroComp"?>
<zk>
    <div apply="org.zkoss.zkplus.databind.AnnotateDataBindingComposer,jtsptbo$v1.TestComposer">
        <label id="windowLabel" value="@{beanTwo.time}" /><div></div>
        <!-- There is another AnnotateDataBindingComposer
            and bind another bean in macrocomp -->
        <macrocomp />
    </div>
    <macrocomp />
</zk>

Regards, ben

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More