Learn from Saki

Knowledge is power

This content is for registered users only. Please login.
Hello! To access your account, please Log in. Not a member? Sign up
  • Videos
  • Blog
  • Examples
  • Services
  • Add-ons
  • About

Ext.ux.MsgBus Plugin

September 20, 2009 by saki 28 Comments

Code in this post can be obsolete, however, principles and theory may still apply.
Recently I’ve been looking for a better way of inter-component communication in Ext so I’ve read a couple of posts with Message Bus implementations, I’ve skimmed over OpenAjax Hub page but I haven’t found anything suitable for my needs. The first approach was Simple Message Bus Example but that is more concept proof than a really usable way in production environment. I like the concept of message subjects (topics) as dot separated sequence of tokens with the ability to subscribe to messages with specific subjects and with wildcard support. For example, if a component would subscribe to the subject eu.extjs.desktop.** it would receive message with subject eu.extjs.desktop.wallpaper.set but it wouldn’t receive message eu.extjs.taskbar.hide. So this plugin was born. Ext.ux.MsgBus fits in any component that is descendant of Ext.util.Observable and it does not need any other changes/overrides. You would stick it only into the components that must participate in bus messaging. It adds subscribe and publish methods to the component. Usage example:
1
2
3
4
5
6
7
8
var p = new Ext.Panel({
     plugins:['msgbus']
    ,onWallpaper:function(subject, message) {
        // do something
    }
    // the rest of config
});
p.subscribe('eu.extjs.desktop.wallpaper.**', {fn:p.onWallpaper, single:true});
The above would call p.onWallpaper callback once upon the receipt of a “wallpaper” message. Other example:
1
p.publish('eu.extjs.this.panel.move', {oldx:100, oldy:200, x:300, y:400});
I haven’t tested it fully yet so take it more as an initial idea than as a bullet-proof, worldwide-tested code. Also, I didn’t try in any means to implement OpenAjax standards and use this plugin for an inter library communication. Consider it as a one possibility of intra-Ext, inter-component communication. Any comments and/or bug reports are welcome.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// vim: sw=4:ts=4:nu:nospell:fdc=4
/**
* Message Bus Plugin
*
* @author    Ing. Jozef Sakáloš
* @copyright (c) 2009, by Ing. Jozef Sakáloš
* @date      19. September 2009
* @version   $Id: Ext.ux.MsgBus.js 29 2009-09-23 09:51:55Z jozo $
*
* @license Ext.ux.MsgBus.js is licensed under the terms of the Open Source
* LGPL 3.0 license. Commercial use is permitted to the extent that the
* code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* License details: http://www.gnu.org/licenses/lgpl.html
*/
 
/*global Ext,window */
 
/**
* @class Ext.ux.MsgBus
*
* Creates new Ext.ux.MsgBus object
* @constructor
* @param {Object} config The config object
*/
Ext.ux.MsgBus = function(config) {
    Ext.apply(this, config, {
    });
}; // eo constructor
 
Ext.override(Ext.ux.MsgBus, {
    /**
     * @cfg {String} busName Name of the global Observable instance
     */
     busName:'Ext.ux.Bus'
    /**
     * @private
     */
    ,bus:false
    /**
     * Initializes the plugin and component
     * @private
     */
    ,init:function(cmp) {
        this.cmp = cmp;
        cmp.bus = this.getBus();
        cmp.bus.addEvents('message');
        cmp.subs = {};
        this.applyConfig();
    } // eo function init
    // {{{
    /**
     * Returns or creates the global Observable instance
     * @private
     */
    ,getBus:function() {
        var bus = window;
        var a = this.busName.split('.');
        var last = a.pop();
        Ext.each(a, function(n) {
            if(!Ext.isObject(bus[n])) {
                bus = false;
                return false;
            }
            else {
                bus = bus[n];
            }
        }, this);
        if(false === bus) {
            Ext.ns(this.busName);
            return this.getBus();
        }
        if(!(bus[last] instanceof Ext.util.Observable)) {
            bus[last] = new Ext.util.Observable();
        }
        return bus[last];
    } // eo function getBus
    // }}}
    // {{{
    /**
     * Creates RegExp for message filtering.
     * Override it if you need another logic.
     * @param {String} subject The message subject
     * @return {RegExp} RegExp used for message filtering
     */
    ,getFilterRe:function(subject) {
        var a = subject.split('.');
        var last = a.length - 1;
        a[last] = '**' === a[last] ? '.*' : a[last];
        var re = /^w+$/;
        Ext.each(a, function(token, i) {
            if(!re.test(token) && '*' !== token && '.*' !== token) {
                throw 'Invalid subject: ' + subject;
            }
            if('*' === token) {
                a[i] = '\w+';
            }
        });
        return new RegExp('^' + a.join('\.') + '$');
    } // eo function getFilter
    // }}}
    // {{{
    /**
     * Applies new methods to the component
     * @private
     */
    ,applyConfig:function() {
        Ext.applyIf(this.cmp, {
            /**
             * Subscribes to messages (parent component method)
             * @param {String} subject Dotted notation subject with wildcards.
             * See http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Topic_Names
             * @param {Object} config Same as addListener config object
             * @return {Boolean} success true on success, false on failure (subscription exists)
             */
             subscribe:function(subject, config) {
                 var sub = this.subs[subject];
                if(sub) {
                    return false;
                }
                config = config || {};
                config.filter = this.getFilterRe(subject);
                this.subs[subject] = {config:config, fn:this.filterMessage.createDelegate(this, [config], true)};
                this.bus.on('message', this.subs[subject].fn, config.scope || this, config);
                return true;
            }
 
            /**
             * Unsubscribes from messages (parent component method)
             * @param {String} subject Dotted notation subject with wildcards.
             * @return {Boolean} success true on success, false on failure (nonexistent subscription)
             */
            ,unsubscribe:function(subject) {
                var sub = this.subs[subject];
                if(!sub) {
                    return false;
                }
                this.bus.un('message', sub.fn, sub.scope || this, sub.config);
                delete this.subs[subject];
                sub = null;
                return true;
            } // eo function unsubscribe
 
            /**
             * Publishes the message (parent component method)
             * @param {String} subject Message subject
             * @param {Mixed} message Message body, most likely an object
             */
            ,publish:function(subject, message) {
                this.getFilterRe(subject);
                this.bus.fireEvent('message', subject, message);
            } // eo function publish
 
            /**
             * Returns current subscriptions
             * @return {Object} subscriptions
             */
            ,getSubscriptions:function() {
                return this.subs;
            } // eo function
 
            /**
             * @private
             */
            ,getFilterRe:this.getFilterRe
 
            /**
             * Filters incoming messages
             * @private
             */
            ,filterMessage:function(subject, message, config) {
                if(config.filter.test(subject)) {
                    (config.fn || this.onMessage).call(config.scope || this, subject, message);
                }
            } // eo function filterMessage
 
            /**
             * Default message processing function
             * @param {String} subject The message subject
             * @param {Mixed} message The message body
             */
            ,onMessage:Ext.emptyFn
        });
    } // eo function applyConfig
    // }}}
 
}); // eo override
 
// register ptype
Ext.preg('msgbus', Ext.ux.MsgBus);
 
// eof
Enjoy! The accompanying example: Ext.ux.MsgBus
  • Author
  • Recent Posts
Follow me:
saki
I'm a well seasoned developer, consultant and educator of web applications based mainly on Sencha libraries, PHP, MySQL and Node.js. Besides (Apple) computers, I love photography and mountain biking.
Follow me:
Latest posts by saki (see all)
  • Ext, Angular, React, and Vue - June 27, 2019
  • The Site Resurgence - February 11, 2018
  • Configuring ViewModel Hierarchy - June 19, 2015

Filed Under: Addons

Comments

  1. joe says

    August 13, 2010 at 7:01 pm

    re: Konstantin

    I think that is a limitation of Ext, since direct Observable descendents to not take the “plugin” property. tried it on a RowSelectionModel instance and it failed as well.

    Log in to Reply
  2. joe says

    August 13, 2010 at 8:30 pm

    Very useful stuff indeed. My approach of what I started today before i found your blog post was an event broker component that would pool all events that are relayed to it. Although I do prefer your solution of a message bus.

    However, my approach was hooking the necessary code right into Ext.util.Observable, so that all objects that are descendants of Observable could communicate (right now anything thats not of the Component class won’t accept plugins). However, I failed to override Ext.util.Observable properly, my skillz are not at leet 😉

    I’d love to any pointers by anyone on how to override Ext.util.Observable properly, since it seems to be quite different to overriding Component, to fit the code into the override and have the messagebus be accessible by any descendant of Observable.

    Log in to Reply
  3. Saki says

    August 16, 2010 at 3:14 am

    Take a look at forum and/or learn section of http://sencha.com/learn Hint: override constructor.

    Log in to Reply
  4. Totti says

    September 9, 2010 at 4:40 am

    Very nice idea. I’m gonna use this for my current project as to reduce the coupling.

    Log in to Reply
  5. Red says

    January 18, 2012 at 6:27 pm

    I am little confused about how the actual filtering is performed. Because the subscription is always done for ‘message’ and the publish always fires the ‘message’ event. Is the filtering used in the publish method?

    I am trying to get this to work on ExtJs4..it works allright..but Its basically working by creating a listener for message and firing an event on it. No subject filtering as expected. What am I doing wrong?

    Log in to Reply
  6. Vijay says

    July 9, 2012 at 4:50 pm

    Can you write the example by using msgbus plugin in Object Oriented manner ?

    Why because if components are there in a single page it is nicely working.. But i want in object oriented manner i dont’t know how to do it in OOP style ?

    Log in to Reply
  7. Rahul Umrao says

    July 19, 2012 at 7:58 am

    If multiple component are in the same page then it is working fine ..but if in the object oriented manner how can i use publish/subscribe methods and most importantly where i use these methods in the component –
    for Ex- component 1(Ext.panel) having button and on button click i want to open a component 2 (Ext.panel) then how & where i need to put publish and subscribe by using message bus plugins …… please give me suggestion because of this i am not able to use correctly the message bus functionality .

    Log in to Reply
  8. Lev Dashevskiy says

    April 22, 2013 at 8:02 pm

    Hello, Saki!
    First of all, thanks so much for all of your superb work – you seem to be everywhere (ExtJs is) ! 🙂
    Secondly, I wanted to ask you a question about the MsgBus. It probably is a broader question about the JavaScript scope and area of visibility.
    If I have 2 segments of JavaScript code within my HTML page code (that is 2 … chunks, separated by other HTML), each of the chunks rendering some UI, is it possible to use a MsgBus instance to communicate between the 2 interfaces?
    Thanks.

    Log in to Reply
  9. Oğuz Çelikdemir says

    April 22, 2014 at 1:23 pm

    Saki, it would be nice to see a syntax highlighter in your blog to be able to read easily code!

    Log in to Reply
    • Saki says

      April 22, 2014 at 8:03 pm

      It shortly stopped to work after port. Syntax highlighter should be now up and running.

      Log in to Reply
  10. jmchoulet says

    October 15, 2019 at 7:59 am

    Hello,

    I cannot get http://examples.learnfromsaki.com/?ex=msgbus example.

    Is it available yet?

    Jean-Marc

    Log in to Reply
    • saki says

      November 10, 2019 at 11:18 pm

      Yeah it doesn’t work for some reason. I’m now away but I’ll take a look in a week or so.

      Log in to Reply
« Older Comments

We will be happy to hear back from you Cancel reply

You must be logged in to post a comment.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Categories

  • Addons (2)
  • Architecture (14)
  • Examples (2)
  • ExtJS (26)
  • Howtos (16)
  • Javascript (1)
  • Know-how (32)
  • Linux (1)
  • Mac OS X (2)
  • SASS/CSS (2)
  • Snippets (9)
  • Theory (14)
  • Touch (6)
  • Tutorials (5)
  • What is a … (9)

Tag cloud

abstract class accordion application button class cluster column component config css definition deprecated design education event example extension extjs factory function form grid html initComponent items javascript Know-how knowledge layout Linux listener mysql old panel pattern php plugin render snippet sql sqlite state table touch tree viewpoint

Membership

Become a Member
Affiliate Program

Support

FAQ
Contact

Legal

Terms and Conditions
Licensing
Privacy Policy

Copyright © 2021 · Dynamik-Gen on Genesis Framework · WordPress · Log in