Chat with Global Command

From Documentation
Revision as of 04:07, 2 April 2014 by Chillworld (talk | contribs) (added comments section)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
DocumentationSmall Talks2014MarchChat with Global Command
Chat with Global Command

Author
Cossaer Filip
Date
March 06, 2014
Version
ZK 6 and above

Introduction: Chat in MVVM with Global Command

In the article ZK 5: Chat with Event Queue, Tom Yeh explains how to create a chat program with the event Queue. Now with MVVM we can do that way also, or say, we use a more MVVM compliant approach. In this small talk we will write a simple chat program just like Tom Yeh. We suggest you to read the previous article first for better understanding.

The global command

What is Global Comand

Global Command is also a ViewModel's command and can hook UI component's events to it. Local command can only be triggered by events of a ViewModel's Root View Component and its child components whereas the global command can be triggered by a component's event from any ZUL. The main difference of a global command from a local command is that the event doesn't have to belong to the ViewModel's root view component or its child component. By default we can bind an event to any ViewModel's global command within the same desktop. A method can be both a local command and a global command.

The scope of an global command

The default scope of a global command is the Desktop scope, this can be changed by the user.

Changing the scope

We can modify the scope of the Viewmodel. By changing the Viewmodel's scope the global-command can be called into that scope.

    <window apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('be.chillworld.YourVM')" binder="@init(queueScope='application')">

We can apply multiple binders to one scope by adding a queueName.

    <window apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('be.chillworld.YourVM')" binder="@init(queueName='chillworld',queueScope='application')">

More info about the differtent scopes : Scope of an Event Queue.
More info about the binder : DataBinding - Binder.

How to call a global command

We can call our global command in 2 ways. From the zul we do this :

    <button label="Send" onClick="@global-command('send')" />

From java we do this :

    BindUtils.postNotifyChange(java.lang.String queueName, java.lang.String queueScope, java.lang.Object bean, java.lang.String property)

More info about the BindUtil class : BindUtils.

An example: chat

The chat pojo. (I use this when I can enums for singelton because this is the best and easiest way to create them)

package be.chillworld;

/**
 *
 * @author chillworld
 */
public enum Chat {
    
    INSTANCE;
    
    private StringBuilder chat = new StringBuilder();
    
    public String getChat () {
        return chat.toString();
    }
    
    public void addText (String text) {
        chat.append("\n");
        chat.append(text);
    }
}

the index.zul :

<?xml version="1.0" encoding="UTF-8"?>
<zk>
    <window border="normal" title="chat with global command" apply="org.zkoss.bind.BindComposer"
          viewModel="@id('vm') @init('be.chillworld.IndexVM')" binder="@init(queueScope='application')">
        <vbox> 	
            <label value="@load(vm.chat)" multiline="true" height="300px"/>
            <textbox value="@bind(vm.text)"/>
            <button label="Send text" onClick="@command('chat')"/>
        </vbox>
    </window>
</zk>

and the viewmodel :

package be.chillworld;

import org.zkoss.bind.annotation.GlobalCommand;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.Sessions;

/**
 *
 * @author chillworld
 */
public class IndexVM{

    private String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getChat() {
        return Chat.INSTANCE.getChat();
    }

   @Command("chat")
    public void chat() {
        if (text != null) {
            Chat.INSTANCE.addText(Sessions.getCurrent().toString() + " says : " + text);
            text = null;
        }
        BindUtils.postGlobalCommand(null, EventQueues.APPLICATION, "update", null);
    }

    @GlobalCommand("update")
    @NotifyChange({"chat", "text"})
    public void update() {}
}

I created a maven project for this.
You can download this here.
Note : Remember that this needs two different sessions so best way to test is open 2 different browsers.

Special Thanks

bartvdc for asking this question.
ZK team allowing me to write a small talk.



Comments



Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.