0

jquery for modification of widget/components and update server

asked 2014-05-23 14:29:33 +0800

jlsevasion gravatar image jlsevasion
3 1

Hi,

I have been looking for the solution to this problem for almost a week but have not been able to make it work. I have a third party library written in jquery. This library is able to add new elements to a tree in clients and handle their size etc.. (Many fatures really useful to my app)

I got it working when the elements are <h:li>, their parent is <h:ul> and they (the <h:li>) are defined in the .zul

But when I create dynamically a new component (in the server, lets say a new "org.zkoss.zhtml.Li li "). i can not make it visible to my .js script of jquery where I need to handle this.

I have tried among other things passing the id, uuid, etc... on the server

@Listen("onClick = #add")
public void anadir_tarjeta() {
    Li li = new Li();
    li.setId("t1");
    li.setAttribute("class", "blanco");
    li.setParent(frame);
    Clients.evalJavaScript("adds('" + li.getId() + "');");
}

and then in the .js retrieving the id, uuid etc... by doing a direct call to the id, or using zk.Widget.

   function adds(id) {
        board.add_widget($(id),3,3,1,1);    
                    return false;
    };

I feel that this should be straight forward, but I haven't been able to do it. Not even something as simple as retriving the widget using the id or uuid reference and changing the width (.width(115)) or reading the id (.attr('id')).

If i d the opposite (crating a component in jquery and then try to work with the component in the server side I can't either. I see the component appearing in the browser but it does not exist in the server).

I guess my problem is connecting the server with the client side and been able to work in both worlds with the component / widget by referencing it using its id or something else.

Any help would be very appreciated thanks!

delete flag offensive retag edit

4 Answers

Sort by ยป oldest newest most voted
0

answered 2014-06-03 15:34:00 +0800

cyiannoulis gravatar image cyiannoulis
1191 10

updated 2014-06-03 16:16:44 +0800

Well, there are two ways to do what you want.

CASE -1-

When you create a component dynamically it has not yet a UUID assigned to it. The UUID will be given to the component as soon as the html is ready to be sent to the client. There is indeed a workaround to override the default UUID generator but it is NOT recommended. So, a simple solution is to assign a "dummy" styling class to the component. This class should be unique. Then using jQuery selectors you can select the component and do what you want using client-side javascript.

Check the working example below:

<?page title="Card Holder" contentType="text/html;charset=UTF-8"?>
<zk>

<script type="text/javascript">

    function changeCardStyle(classId) {
        $("." + classId).addClass("v-card");
    }

</script>

<style>
    .v-card {
        align: center;
        border:2px solid;
        border-radius:25px;
        box-shadow: 10px 10px 5px #888888;
        height: 70px;
        width: 25%;
    }
</style>

<window title="Card Holder" border="normal" 
        apply="snippets.MvcCardHolderController" 
        width="100%" height="100%">

    <hlayout>
        <textbox id="txtCardName" placeholder="Type a name" 
                class="form-control" width="200px" />
        <button id="btnAdd" label="Add Component" 
                sclass="btn btn-primary" />
    </hlayout>

    <separator height="20px" />

    <vlayout id="container" style="overflow:auto;" vflex="true" />

</window>
</zk>

And here is the controller:

public class MvcCardHolderController extends SelectorComposer<Component> {

    private static final long serialVersionUID = 1L;

    @Wire
    private Vlayout container;
    @Wire
    private Textbox txtCardName;

    private int classGenerator;

    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);

        classGenerator = 0;
    }

    @Listen("onClick = #btnAdd")
    public void onClickButton() {

        if (txtCardName.getValue() == null || 
            txtCardName.getValue().isEmpty()) {
            Clients.showNotification("Please type a name first");
            return;
        }

        String sclass = "card_" + ++classGenerator;

        Div div = new Div();

        div.setParent(container);
        div.setSclass(sclass);

        Hlayout hlayout = new Hlayout();
        hlayout.setParent(div);

        Separator separator = new Separator();
        separator.setParent(hlayout);
        separator.setWidth("10px");

        Label label = new Label(txtCardName.getValue());
        label.setParent(hlayout);
        label.setStyle("font-weight: bold; font-size: 20px");

        txtCardName.setValue("");

        Clients.evalJavaScript("changeCardStyle('" + sclass + "')");
    }

}

As you can see, i am using the "classGenerator" field to create a unique "dummy" style for each DIV. Then i pass this class back to the client-side javascript function changeCardStyle(). Then i use a normal jQuery selector to get the component and change its style. Simple ah?

CASE -2-

well.... read my second answer :)

Costas

link publish delete flag offensive edit
0

answered 2014-05-28 13:38:02 +0800

jlsevasion gravatar image jlsevasion
3 1

Thanks cianoullis,

I have tried many solutions, with negative results. I am using a jquery library that in order to work needs to modify certain attributes like width in jquery. On the other hand in order to be able to modifiy and work with those widgets in ZK at the server side. ZK needs to have created this widgets (or at least that my understanding).

I have not been able to find a way to create the widget at the server side pass it to the client side (I've tried evalajavaScript calling a function and passing either the uuid or zk's id both of them show undifined when I try to handle them in javascript)and then allow the abovementioned jquery library to handle the widget.

One way, I am now trying is to create an org.zkoss.zhtml.Li (since that is an html element instead of a zk element) and try to pass it as an HTML element (Since the jquery library asks for an HTML element as a possible input). But at least from now with no luck

Any ideas.

Summary of the problem: need to pass to jquery something that allows me to refer to a widget created at the server side.

Thanks

link publish delete flag offensive edit
0

answered 2014-06-03 16:12:34 +0800

cyiannoulis gravatar image cyiannoulis
1191 10

So, here is the second case where the UUID has already been assigned to each component and we need to manipulate these components using native javascript on the client-side:

CASE -2-

In the following example we have a grid populated with some records from the ViewModel class. Then the user may click on each row button to change it's style. The button invokes the server-side @command and then the server calls a client-side JS function passing the UUID of the row back to the client:

<?page title="Card Holder" contentType="text/html;charset=UTF-8"?>
<zk>

<script type="text/javascript">

    function changeCardStyle(componentId) {
        $(componentId).addClass("v-card");
    }

</script>

<style>
    .v-card {
        border:2px solid;
        height: 70px;
    }
</style>

<window title="Card Holder" border="normal" width="100%" height="100%"
        apply="org.zkoss.bind.BindComposer" 
        viewModel="@id('vm') @init('snippets.CardHolderVM')"
        xmlns:n="native">

    <grid model="@load(vm.cards)">
        <columns>
            <column label="Cards" hflex="max"></column>
            <column hflex="min"></column>
        </columns>
        <template name="model" var="card">
            <row>
              <cell>
                <label value="@load(card)" />
              </cell>
              <cell>
                <button label="Change" onClick="@command('change-style', row=self.parent.parent)" />
              </cell>
            </row>
        </template>
    </grid>
</window>
</zk>

And here is the View Model:

public class CardHolderVM {

  @Command("change-style")
  public void onChangeStyle(@BindingParam("row") Component row) {

    String componentId = "#" + row.getUuid();
    Clients.evalJavaScript("changeCardStyle('" + componentId + "')");
  }

  public ListModel<String> getCards() {
    List<String> data = new ArrayList<String>();
    data.add("Costas");
    data.add("Nick");
    data.add("Peter");
    data.add("Paul");
    data.add("Mario");
    data.add("John");
    data.add("Jack");
    return new ListModelList<String>(data);
  }
}

There is indeed one more way to do the above using the "native" namespace but i think that you will be fine with these two cases.

Hope that helps

Costas

link publish delete flag offensive edit
0

answered 2014-06-03 16:54:52 +0800

jlsevasion gravatar image jlsevasion
3 1

Thanks case 1 worked perfectly.

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
2 followers

RSS

Stats

Asked: 2014-05-23 14:29:33 +0800

Seen: 53 times

Last updated: Jun 03 '14

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