0

Maybe this question is too simple:

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark">
    <s:Label id="label1"/>
    <fx:Script>
        public function setMsg(msg:String):void
        {
            label1.text = msg;
        }
    </fx:Script>
</s:View>

There's a run time error because label1 is null. But when I change s:View to s:Group, everything's OK. Why?

PS: put the label in SkinableContainer will also has this problem

zero323
  • 322,348
  • 103
  • 959
  • 935
willzeng
  • 915
  • 1
  • 8
  • 19
  • You need to access label after the `creationComplete` event is dispatched. Showing code of when `setMsg` is called would help debug the issue. – Jason Sturges Oct 26 '12 at 04:57
  • OK, to be precise, in the app's creationComplete, i new the view and setMsg before add it as a child/element. – willzeng Oct 29 '12 at 02:27

1 Answers1

1

Components are instanciated asynchronously. You may want to try this implementation.

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark">
  <fx:Script>
    <![CDATA[
    private var _message:String, _messageChanged:Boolean;

    public function get message():String {
      return _message;
    }

    [Bindable("messageChanged")]
    public function set message(value:String):void {
      if (_message == value) {
        return;
      }
      _message = value;
      _messageChanged = true;
      invalidateProperties();
      dispatchEvent(new Event('messageChanged'));

    }

    override protected function commitProperties():void {
      super.commitProperties();
      if (_messageChanged) {
        _messageChanged = false;
        label1.text = _message;
      }
    }
    ]]>
  </fx:Script>

  <s:Label id="label1"/>
</s:View>

This is based on the Flex component live cycle, which lets you type a bit, but with a template it's ok if you can't/don't want to use data binding like in this example:

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark">
  <fx:Script>

    [Bindable]
    private var _message:String;

    public function setMsg(msg:String):void
    {
      _message = msg;
    }
  </fx:Script>

  <s:Label id="label1" text="{_message}"/>
</s:View>

This example is might me a good choice as well - depending on your needs.

Florian Salihovic
  • 3,921
  • 2
  • 19
  • 26
  • I don't understand the life cycle yet, but I tried the second approach, it worked. Thanks! – willzeng Oct 29 '12 at 02:31
  • Now I thought the problem is not completely solved. If I need to call label1.addChild() from within creationComplete, there are still errors. I think it's the same problem? – willzeng Oct 29 '12 at 06:59
  • When the Label is declared in MXML, it is automatically added. It seems like you have to add the view. – Florian Salihovic Oct 29 '12 at 07:33