简体   繁体   中英

Flex: passing parameters to custom components

I am trying to create a component which can receive an additional value from mxml code:

public class Board extends Canvas
{
    public var boardSize:Number;
    private var cellWidth:Number;
    public function Board()
    {
        super();

    }
}

How can I pass boardSize value from the mxml code. eg

<MyComp:Board x="22" y="25" width="600" height="600" boardSize="19">

But it doesn't work. When I am trying to debug the code I see that boardSize variable is NaN inside the class

When are you testing this? If you test the code by putting a breakpoint in the constructor, boardSize should be null. Just like your code, instantiating by MXML requires that the constructor is called before any of the member variables are set.

For an example, try this app using the TestObject class. When you run it in debug mode, the trace will tell you that n and s aren't set, but when you see the app, the two labels are clearly bound after the trace has happened.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:local="*">
    <mx:TraceTarget />
    <local:TestObject id="o" n="19" s="19" />
    <mx:Label text="Number Field: {o.n}" />
    <mx:Label text="String Field: {o.s}" />
</mx:Application>


package
{
    public class TestObject
    {
        [Bindable]
        public var n:Number;
        [Bindable]
        public var s:String; 

        public function TestObject()
        {
            trace("Initialized test object ...", n, s);
        }
    }
}

Just to elaborate on Dan Monego answer and comments. Change the class to look like the class below. Then you can set a break point on the set function.

public class Board extends Canvas
{
        private var _boardSize:Number;

        public function get boardSize():Number{
           return _boardSize;
        }


        public function set boardSize(val:Number):Void{
           _boardSize = val;
        }

        private var cellWidth:Number;
        public function Board()
        {
                super();

        }
}

try this:

<MyComp:Board x="22" y="25" width="600" height="600" boardSize="{Number(19)}">

or this:

<mx:Script>
<![CDATA[
public var boardSize:Number = 19;
]]>
</mx:Script>

<MyComp:Board x="22" y="25" width="600" height="600" boardSize="{boardSize}">

The problem may be that you are passing it as a string to the component, it doesn't realize that it is a number.

I think to get mxml code completion you need to add the [Inspectable] metatag above the property that you want.

[Inspectable(defaultValue="", type="Number", name="boardSize", format="Number")]
public var boardSize:Number;

Try this and let me know how you got on. Loads more info on this kind of component development here

If you look at your constructor it has no arguments hence you need the properties, or public vars, to set the value. If you wanted to create your custom component with arguments you would have to create a different constructor as listed below. Don't think it is is possible to call the constructor with args from mxml but with actionScript you could have optional parameters that would set the values...

public class Board extends Canvas
{
        public var boardSize:Number;
        private var cellWidth:Number;
        public function Board(boardSize:Number = 0, cellWidth:Number = 0)
        {
                super();
                this.boardSize = boardSize;
                this.cellWidth = cellWidth;


        }
}

The place where you most probably want to have access to this property would be during setup of the component and creation of its children - as "creationComplete" should be already after you've done that :) For this, override the createChildren() method. Additionally you probably also want to create a setter for it (or at least bind to it) to catch changes.

Example:

package {
  import flash.events.Event;

  public class Board extends Canvas {

  /** clever ASDoc comment goes here */
  [Bindable("boardSizeChanged")]
  [Inspectable(category="General", defaultValue="")]
  var _boardSize: Number;
  public function get boardSize(): Number {
      return _boardSize;
  }
  public function set boardSize(value: Number): void {
      if (_boardSize == value) return;
      _boardSize = value;
      // do something when boardSize changes, e.g. update child components
      trace("Boardsize is now: " + value);
      dispatchEvent(new Event("boardSizeChanged"));
  }

  public function Board() {
      super();
  }

  override protected function createChildren(): void {
      super.createChildren();
      // create your own children, using the boardSize property (this uses the getter function)
      trace("Boardsize: " + boardSize);
  }
}}

Please note that in this example, set boardSize() is called prior to createChildren - so if you use boardSize to change your children you should make sure that they actually already exists in this setter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM