views:

3696

answers:

4

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()" />
A: 
<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()"/>
ForYourOwnGood
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.
try this, I updated it.
ForYourOwnGood
The variable is going to be a global variable, there is no need to pass it to the function.
ForYourOwnGood
+1  A: 

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.

Matt Dillard
+3  A: 

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!

Christian Nunciato
+2  A: 
<mx:Button
enabled = "{this.myFunction(this.myVariable)}"
>

or inline:

<mx:Button
enabled = "{(function(arg:Object):Boolean{ ... })(this.myVariable)}"
>
I don't see the point of passing the variable as a parameter to the function, since it is global.
ForYourOwnGood
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.
Matt Dillard
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!
Christian Nunciato