Can I bind a Flex component property to a function?
Asked Answered
P

4

7

I want to set the enabled property on a button based on the return value of a function that has one or more parameters. How can I do this?

private function isUserAllowed (userName:Boolean):Boolean {
   if (userName == 'Tom')
      return true;
   if (userName == 'Bill')
      return false;
}

<mx:Button label="Create PO" id="createPOButton"
enabled="<I want to call isUserAllowed ('Bill') or isUserAllowed ('Tom') here>"
click="createPOButton_Click()" />
Pilewort answered 15/1, 2009 at 1:18 Comment(0)
A
7
<mx:Button
enabled = "{this.myFunction(this.myVariable)}"
>

or inline:

<mx:Button
enabled = "{(function(arg:Object):Boolean{ ... })(this.myVariable)}"
>
Actinology answered 15/1, 2009 at 15:17 Comment(3)
I don't see the point of passing the variable as a parameter to the function, since it is global.Monospermous
If the parameter isn't mentioned on the "enabled" line, then the binding won't trigger when the value changes - the button would have no way of knowing that it should re-evaluate the "enabled" condition.Francois
Despite that it works, this approach still feels like a big ol' kludge to me personally; it seems much more appropriate to bind to the function explicitly, rather than to do so incidentally by way of a public variable "passed into" it. Weird practice. But to each his own!Hartzel
H
10

According to the Flex docs, as long as the property is bindable, you can simply do this (I've included the two extra buttons to demonstrate):

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

    <mx:Script>
        <![CDATA[

            [Bindable]
            private var currentUser:String = "Bill";

            private function isUserAllowed(user:String):Boolean
            {
                if (user == "Bill")
                {
                    return true;
                }

                return false;
            }

        ]]>
    </mx:Script>

    <mx:VBox>
        <mx:Button label="My Button" enabled="{isUserAllowed(currentUser)}" />
        <mx:HBox>
            <mx:Button label="Try Tom" click="{currentUser = 'Tom'}" />
            <mx:Button label="Try Bill" click="{currentUser = 'Bill'}" />
        </mx:HBox>
    </mx:VBox>

</mx:Application>

Without currentUser marked [Bindable], though, it won't work.

Another way to go, if you wanted to bind more literally to the function (this is also expressed in the docs), would be to have the function respond to an event you dispatch when the current user changes, like so:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()">

    <mx:Script>
        <![CDATA[

            private var _currentUser:String = "Bill";

            public function set currentUser(value:String):void
            {
                if (_currentUser != value)
                {
                    _currentUser = value;
                    dispatchEvent(new Event("userChanged"));
                }
            }           

            [Bindable(event="userChanged")]
            private function isUserEnabled():Boolean
            {
                if (_currentUser == "Bill")
                {
                    return true;
                }

                return false;
            }

        ]]>
    </mx:Script>

    <mx:VBox>
        <mx:Button label="My Button" enabled="{isUserEnabled()}" />
        <mx:HBox>
            <mx:Button label="Try Tom" click="{currentUser = 'Tom'}" />
            <mx:Button label="Try Bill" click="{currentUser = 'Bill'}" />
        </mx:HBox>
    </mx:VBox>

</mx:Application>

So there are a couple of ways. IMO, the second seems somehow more proper, but there's definitely nothing wrong with the first. Good luck!

Hartzel answered 15/1, 2009 at 4:42 Comment(1)
+1 Option 2 all the way! Though not a direct answer to the question, a much better approach.Marje
A
7
<mx:Button
enabled = "{this.myFunction(this.myVariable)}"
>

or inline:

<mx:Button
enabled = "{(function(arg:Object):Boolean{ ... })(this.myVariable)}"
>
Actinology answered 15/1, 2009 at 15:17 Comment(3)
I don't see the point of passing the variable as a parameter to the function, since it is global.Monospermous
If the parameter isn't mentioned on the "enabled" line, then the binding won't trigger when the value changes - the button would have no way of knowing that it should re-evaluate the "enabled" condition.Francois
Despite that it works, this approach still feels like a big ol' kludge to me personally; it seems much more appropriate to bind to the function explicitly, rather than to do so incidentally by way of a public variable "passed into" it. Weird practice. But to each his own!Hartzel
F
2

Here's what I've done a few times in similar circumstances:

<mx:Script>
<![CDATA[

    [Bindable] var _username : String;

    private function isUserAllowed (userName:Boolean):Boolean {
        if (userName == 'Tom')
            return true;
        if (userName == 'Bill')
            return false;
    }

]]>
</mx:Script>

<mx:Button label="Create PO"
    id="createPOButton"
    enabled="{isUserAllowed(_username)}"
    click="createPOButton_Click()" />

This way, when the Bindable _username changes, it will fire a change notification. Since the label is listening to _username changes (even if it is simply a parameter to another function), the enabled property will be re-evaluated.

Francois answered 15/1, 2009 at 2:8 Comment(0)
M
0
<mx:Script>
    <![CDATA[
        [Bindable]
        private var userName : String = "Tom"; // or whatever ...
        [Bindable]
        private var userAllowed : Boolean;

        private function isUserAllowed ():Boolean {
           if (userName == 'Tom')
             return false;
           if (userName == 'Bill')
              return false;
           return false;
        }
    ]]>
</mx:Script>

    <mx:Button label="Create PO" id="createPOButton" enabled="{userAllowed}" addedToStage="isUserAllowed()"/>
Monospermous answered 15/1, 2009 at 1:46 Comment(2)
But where do I pass in the parameter to the function isUserAllowed? I want to call the function dynamically when it tries to set the enabled property.Pilewort
The variable is going to be a global variable, there is no need to pass it to the function.Monospermous

© 2022 - 2024 — McMap. All rights reserved.