0

Different template for each grid row

asked 2013-03-04 13:19:24 +0800

coleriv gravatar image coleriv
37 2

Hi everybody, the problem is this one (with some simplification).

I've a class: Result, and two other classes that extend the first one: NumberResult and TextResult. NumberResult has three fields: value, minValue and maxValue; TextResult has two fields: value and reference. Then there's another class: Exam, that has a list of Result.

I need to show the results of an exam in a grid. I can have text and number results mixed together and I can't modify the order of the list. Here is my solution.

<grid vflex="1" model="@load(vm.examResults)">
    <columns>
        <column hflex="1" label="Value" />
        <column hflex="2" label="Reference" />
        <column hflex="1" label="Min." />
        <column hflex="1" label="Max." />
    </columns>
    <template name="model">
        <row>
            <label value="${each.value}" />
            <label value="${c:isInstance('myPackage.TextResult', each) ? each.reference : null}" />
            <label value="${c:isInstance('myPackage.NumberResult', each) ? each.minValue : null}" />
            <label value="${c:isInstance('myPackage.NumberResult', each) ? each.maxValue : null}" />
        </row>
    </template>
</grid>

It's not a very nice solution and it uses a deprecated tag library (c). Moreover, because the grid has much more fields that those showed in this example, it's also not very efficient. So I'm trying to find a way to use two templates, one for the NumberResult and the other for the TextResult, but I can't find how to do yet.

Any idea will be really appreciated.

Roberto

delete flag offensive retag edit

2 Answers

Sort by ยป oldest newest most voted
0

answered 2013-03-09 03:50:22 +0800

rickcr gravatar image rickcr
704 7

Maybe not ideal but you could use an Adapter pattern where your Adapter class holds an instance of Result and then you could provide accessor methods. Ideally you'd stuff your Result instances into this Adapter when you getting your collection the first time to avoid an extra iteration.

I put together an example here for you http://zkfiddle.org/sample/11r42l4/10-AdapterExample (Note: not sure why, but Zkfiddle didn't like me using an Interface so that's the only reason you see the classes extends Result, but you get the idea.)

It works because the el on the page won't complain the first time there is null object even if the next property doesn't exist on the object.

Here is a sample of what I did as well (note the static classes just bc I was lazy in my IDE)

<window border="none" apply="org.zkoss.bind.BindComposer"  id="mainWindow"
        viewModel="@id('vm') @init('net.reumann.zktesting.TestVM')" width="100%" height="100%">
        <vlayout>
            <grid vflex="1" model="@load(vm.results)">
                <columns>
                    <column hflex="1" label="Value" />
                    <column hflex="2" label="Reference" />
                    <column hflex="1" label="Min." />
                    <column hflex="1" label="Max." />
                </columns>
                <template name="model">
                    <row>
                        <label value="${each.textResult.value}" />
                        <label value="${each.textResult.reference}" />
                        <label value="${each.numberResult.minVal}" />
                        <label value="${each.numberResult.maxVal}" />
                    </row>
                </template>
            </grid>
        </vlayout>
</window>


public class TestVM {

    public List<UiResultAdapter> getResults() {
        //call to DB would return these
        List<UiResultAdapter> results = new ArrayList<UiResultAdapter>();
        Result r1 = new TextResult("t1","ref1");
        results.add(new UiResultAdapter(r1));
        Result r2 = new NumberResult(1,10);
        results.add(new UiResultAdapter(r2));
        return results;
    }

    public static class UiResultAdapter {
        private Result result;

        public UiResultAdapter(Result result) {
            this.result = result;
        }

        public TextResult getTextResult() {
            return result instanceof TextResult ? (TextResult) result :null;
        }
        public NumberResult getNumberResult() {
            return result instanceof NumberResult ? (NumberResult) result :null;
        }
    }

    public static interface Result {

    }
    public static class TextResult implements Result {
        private String value;
        private String reference;

        public TextResult(String value, String reference) {
            this.value = value;
            this.reference = reference;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public String getReference() {
            return reference;
        }

        public void setReference(String reference) {
            this.reference = reference;
        }
    }
    public static class NumberResult implements Result {
        private int minVal;
        private int maxVal;

        public NumberResult(int minVal, int maxVal) {
            this.minVal = minVal;
            this.maxVal = maxVal;
        }

        public int getMinVal() {
            return minVal;
        }

        public void setMinVal(int minVal) {
            this.minVal = minVal;
        }

        public int getMaxVal() {
            return maxVal;
        }

        public void setMaxVal(int maxVal) {
            this.maxVal = maxVal;
        }
    }
}
link publish delete flag offensive edit

Comments

Also note you can nest templates in a grid if that helps you http://forum.zkoss.org/question/84802/problem-with-dyanmic-columns-and-rows-in-a-grid/

rickcr ( 2013-03-09 03:51:56 +0800 )edit
0

answered 2013-03-11 03:12:07 +0800

dennis gravatar image dennis
3669 1 6
http://www.javaworld.com....

use @teamplate (note:the following code is not verified in runtime)

<grid vflex="1" model="@load(vm.examResults) @template(c:isInstance('myPackage.TextResult', each)?'textTemp':'numberTemp')">
    <columns>
        <column hflex="1" label="Value" />
        <column hflex="2" label="Reference" />
        <column hflex="1" label="Min." />
        <column hflex="1" label="Max." />
    </columns>
    <template name="textTemp">
        <row>
            <label value="${each.value}" />
            <label value="${each.reference}" />
            <label value="" />
            <label value="" />
        </row>
    </template>
    <template name="numberTemp">
        <row>
            <label value="${each.value}" />
            <label value="" />
            <label value="${each.minValue}" />
            <label value="${each.maxValue}" />
        </row>
    </template>
</grid>
link publish delete flag offensive edit
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow
1 follower

RSS

Stats

Asked: 2013-03-04 13:19:24 +0800

Seen: 160 times

Last updated: Mar 11 '13

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