4

I've searched the examples and docs and I couldn't find if its possible to use wildcards in the ComponentQuery query. Id like to do the following:

 Ext.ComponentQuery.query('button > menu > menuitem[text="Welcome*"]');

Since the button text will be the current user name for example "Welcome Shaun".

sra
  • 23,820
  • 7
  • 55
  • 89
b3labs
  • 960
  • 1
  • 14
  • 29

3 Answers3

4

Try

Ext.ComponentQuery.query('menuitem{text.search( \'Menu Item\' )!=-1}');

Per the docs, you can use custom expressions. This works for the code I've included below:

var toolbar = Ext.widget('toolbar', {
        items   : [
            {
                xtype:'splitbutton',
                text: 'Menu Button',
                iconCls: 'add16',
                menu: [{text: 'Menu Item 1'},{text: 'Menu Item 2'}],
                reorderable: false
            },
            {
                xtype: 'button',
                text: 'Get matches',
                handler: function(){
                    var match = Ext.ComponentQuery.query('menuitem{text.search( \'Menu Item\' )!=-1}');
                    console.log( match )
                }
            }
        ]
    });

    Ext.widget('panel', {
        renderTo: Ext.getBody(),
        tbar    : toolbar,
        border  : true,
        width   : 600,
        height  : 400
    });
existdissolve
  • 3,104
  • 1
  • 16
  • 12
  • That's not documented, is this a guess? http://docs.sencha.com/ext-js/4-1/#!/api/Ext.ComponentQuery – Ruan Mendes Jan 24 '13 at 18:35
  • @JuanMendes It is documented, cause he uses a member expression along with the native [string.search](http://www.w3schools.com/jsref/jsref_search.asp) method. The example for Member expressions is not the best cause the don't make it clear that you can apply a member function to a selector so that it will only run on that. – sra Jan 25 '13 at 07:33
  • @JuanMendes Btw. with `The example for Member expressions is not the best...` I am referring to the example of the API! – sra Jan 25 '13 at 12:12
  • @sra existdissolve changed his answer, it used to contain a `^=` operator – Ruan Mendes Jan 25 '13 at 16:36
3

Just for the sake of completeness (and because Member Expressions can crash the query)

As @existdissolve stated you can archive something similar (not the same!) of a wildcard with the use of a Member Expression like in your case

Ext.ComponentQuery.query('button > menu > menuitem{text.search("Welcome")!=-1}');

This will try to perform the native JS search operation on the text property of any found menuitem. No matter if this property exist (or the method) which brings me to the main issue of Member Expressions

What you need to know about Member Expressions

You can use a Member Expressions on nearly every selector but they need to exist on that selector or you end up with a exception which aborts the query (totally, like a exception does).

Here's a simple example. Let's say you want to find a button by it's text. That should be no problem, all buttons need a text, didn't they? This works for quite a time till your customer complains that some buttons don't need text a simple image would be enough. You have forgotten about the query thing and add the button and suddenly parts of your application stop working while you end up with a exception like

Uncaught TypeError: Cannot call method 'search' of undefined

You can try it yourself in this JSFiddle example. Try 'find me' and after that hit the 'add image button' and try it again.

Why does this happen? The Ext.ComponentQuery test neither if property exist nor if the expression exist which can quickly lead to a total fail of the query.

Yes, the example above is simple and you may find the source of the error real quick but it can also be completely different.

What now? I don't want to say to say that you should not use a Member Expression but you really need to care about the side effects that you may face.

Community
  • 1
  • 1
sra
  • 23,820
  • 7
  • 55
  • 89
  • 1
    Agreed. In the case of the original question, I would probably opt for putting a unique name on the type of menut item being used (regardless of the mutability of the text), and then simply use that name in the the more "standard" component query. – existdissolve Jan 25 '13 at 11:48
  • @existdissolve Don't get me wrong. In my comment to your answer I am referring to the API not your answer. I think I didn't made that clear enough. Your answer is absolute correct. With my addition I just want to to point out the cons of `Member Expressions` – sra Jan 25 '13 at 12:15
  • Thanks I wanted to avoid assign ID to my components and just use generated ID. But in this case I think I'll do just that and you the simple query as @existdissolve points out. – b3labs Jan 25 '13 at 12:56
  • Instead of assigning an id, you could just add an additional class to all the menu items that are of the same type, and use that in the selector. – existdissolve Jan 25 '13 at 14:08
  • 2
    @theboulderer Or just any property name you like. For example a `itemId:ButtonABC` which is in addition supported by ExtJS or any other like `action:'start'` – sra Jan 25 '13 at 14:19
0

Starting with ExtJS 5 functionality was introduced that makes this task much cleaner by allowing matching via regular expressions. The documentation provides further detail, but a solution that solves the posted question would look like this:

Ext.ComponentQuery.query('button > menu > menuitem[text/="^Welcome"]');
Grant Humphries
  • 2,696
  • 2
  • 23
  • 24