0

Problem creating data binding programmatically [closed]

asked 2022-03-31 20:13:33 +0800

ImanolRP gravatar image ImanolRP
150 4

updated 2022-04-01 12:04:54 +0800

jeanher gravatar image jeanher
1824 2 6
ZK Team

Hello everyone,

Im creating a zk component for mount easy grid from view database. One of his powerful features is the automatic generation of filters by column. This filters appear automatically on the top column inside the auxheader tag and are generadted programmatically on java with the column info. Example of database view TIMESTAMP column (sorry not css right now)

URL with example but insuficient karma -> prntscr.com/ZK9nMws2l68p

My problem now its i dont know how bind these datebox generated programmatically on java with the view for recover the filter values.

I was searching inside the zkoss wiki and only found this page:

URL with wiki example but insuficient karma -> zkoss.org

/wiki/User:Hawk/CreateDataBinding_Programmatically

Where you can find how bind zk components of the zul, or how bind components generated programatically if the parent has an item render option.

But i need generate N datebox, numberbox, textbox depending the number and type of the columns and recover the values of it.

Anyone knows how do it?

The component has a loot of code and scrap but more or less the idea is:

URL with pseudocode of the component but insuficient karma -> pastebin.com/Q5VX472L

delete flag offensive retag edit

The question has been closed for the following reason "question is not relevant or outdated" by ImanolRP
close date 2022-09-30 21:09:37

1 Answer

Sort by ยป oldest newest most voted
1

answered 2022-04-01 17:04:13 +0800

MDuchemin gravatar image MDuchemin
2228 1 5
ZK Team

Alright! so there's a lot of ground to cover :)

Just a friendly reminder that the Karma system is here because without it spam happens. Legitimate users tend to get a karma bump if they need to post links, images.

Now for the meat of the question.

The wiki link is quite old, and not relevant to modern ZK MVVM architecture, so I would not advise going that direction.

The main point of friction here is that in the MVVM pattern, you should treat the MacroComponent as the interface with its content, not the individual components that are located inside of the macroComponent.

So I guess the question is how the communication should work, and which data flows do you want to achieve? I see from the pastebin that you already have a columnsList containing your column definition.

The way I would approach that to match the MVVM pattern would be to have a columnValue setter on the component, which would accept a Map<columnid, headervalue=""> (assuming a column ID, but would work with any way to match a value to a column), which you then use to iterate over your existing headers (or on an internal collection if you want to maintain one on the macrocomponent itself), and add a onColumnValueChangeEvent event to the macroComponent, which itself would be fired whenever the relevant component in one of the header fires.

You already have the proper annotation for the binder to know which event / property should be sent / listened to: @ComponentAnnotation({"value:@ZKBIND(ACCESS=both,SAVE_EVENT=onEdited)"}) (although it doesn't look like you have a getter / setter for value, or a onEdited event in this component?)

This way, you could have (everything below is pseudo-ish code, may need tweaking to run, but the structure is here):

    <datatableComponent columnsList="@load(vm.columnsDefinition)" columnsValues="@bind(vm.columnValues)" onColumnValueChange="@command('doColumnValueChange', targetColumnId= event.data.targetColumnId, updatedValue=event.data.updatedValue)" ... >

In order to achieve that, you'll need to set some event listeners on each of your header inputs when creating them from the macroComponent:

@ComponentAnnotation("columnsValues:@ZKBIND(ACCESS=both, SAVE_EVENT=onColumnValueChange)")
class ...

private Map<String, Object> columnsValues;
//getters and setters goes here

... //skipping non relevant code until mountDatatable
        private void mountDatatable() {
...
        for (int indexColumn = 0; indexColumn < columnsList
        .size(); indexColumn++) {
      if (columnsList.get(indexColumn).getVisible()) {
        // i have definned the diferent Auxheader with a patron factory


        // you'd pass the event listener to the factory, or have it added on the created header's input component after retrieving the created header. I'd assume you'd want to do it at the factory, since different components would have different events to listen to (onChange for textbox, datebox, etc. onCheck for checkboxes if you use these, etc, onSelect for dropDowns, etc.)

    EventListener<Event> eventListener = new EventListener<Event>() {
        @Override
        public void onEvent(Event event) throws Exception {
            onHeaderValueChange(columnId, value, event);
        }
    };


        Auxheader auxheader = gridDatatableFilterFactory.generateFilter(
            columnsList.get(indexColumn).getTerms().getType(),
            columnsList.get(indexColumn).getTerms().getKey(),


);
        auxheader.setParent(auxhead1);
      }
    }

...

       // build an event sent by the macroComponent itself to whathever might be listening (used to trigger commands, used to trigger @bind and @save annotations if you have them wired on it)
    public void onHeaderValueChange(String columnId, Object value, Event event) {
        Map<String,Object> data = new HashMap<String, Object>();
        data.put("targetColumnId", columnId);
        data.put("updatedValue", value); //you'd have to retrieve the value per the original event, would happen in your factory
        data.put("originalEvent", event); //you may need to access the original event for some reason
        org.zkoss.zk.ui.event.Events.postEvent(new Event("onColumnValueChange", this, data));
    }

Lastly, an alternative solution:

Do you have access to MVVM Shadow elements from the zkmax package? If yes, I'd recommend evaluating whether you could replace the MacroComponent with am Apply Shadow element. That would achieve the same benefit of code reuse, but would be easier to match to the MVVM pattern. Instead of using a MacroComponent, you would use either children binding or forEach shadow element to iterate over the columns definition and create each individual column header with its component, matching command, etc.

link publish delete flag offensive edit

Question tools

Follow
2 followers

RSS

Stats

Asked: 2022-03-31 20:13:33 +0800

Seen: 14 times

Last updated: Apr 01

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