Using the Repeater component

You use the <mx:Repeater> tag to declare a Repeater component that handles repetition of one or more user interface components based on dynamic or static data arrays at run time. The repeated components can be controls or containers. Using a Repeater component requires data binding to allow for run-time-specific values. For more information about data binding, see Storing data.

You can use the <mx:Repeater> tag anywhere a control or container tag is allowed, as long as you wrap the repeater tag in a MX container, such as VBox, HBox, Panel, or Canvas. If you use a container such as Canvas that uses absolute positioning, you must manually position each repeated element so that they do not overlap.

To repeat user interface components, you place their tags within the <mx:Repeater> tag. All components derived from the UIComponent class can be repeated with the exception of the Application container tag. Components that are not based on UIComponent class cannot be children of the Repeater control.

You can also use more than one <mx:Repeater> tag in an MXML document, and you can nest <mx:Repeater> tags.

Declaring the Repeater component in MXML

You declare the Repeater component in the <mx:Repeater> tag, inside a MX container. The following table describes the Repeater component’s properties:

Property

Description

id

Instance name of the corresponding Repeater component.

dataProvider

An implementation of the ICollectionView interface, IList interface, or Array class, such as an ArrayCollection object.

You must specify a dataProvider value or the Repeater component will not execute.

Generally, you specify the value of the dataProvider property as a binding expression because the value is not known until run time.

startingIndex

Number that specifies the element in the data provider at which the repetition starts. The data provider array is zero-based, so to start at the second element of the array, specify a starting index of one. If the startingIndex is not within the range of the dataProvider property, no repetition occurs.

count

Number that specifies how many repetitions occur. If the dataProvider property has fewer items than the number in the count property, the repetition stops with the last item.

currentIndex

Number that specifies the element of the dataProvider item currently being processed. The data provider array is zero-based, so when the third element is being processed, the current index is two. This property changes as the Repeater component executes, and is -1 after the execution is complete. It is a read-only property that you cannot set in the <mx:Repeater> tag.

currentItem

Reference to the item that is being processed in the dataProvider property. This property changes as the Repeater component executes, and is null after the execution is complete. It is a read-only property that you cannot set in the <mx:Repeater> tag.

After a Repeater component finishes repeating, you do not use the currentItem property to get the current item. Instead, you call the getRepeaterItem() method of the repeated component itself. For more information, see Referencing repeated components.

recycleChildren

Boolean value that, when set to true, binds new data items into existing Repeater children, incrementally creates new children if there are more data items, and destroys extra children that are no longer required. For more information, see How a Repeater component executes.

The following table describes the Repeater component’s events:

Event

Description

repeat

Dispatched each time an item is processed and currentIndex and currentItem are updated.

repeatEnd

Dispatched after all the subcomponents of a repeater are created.

repeatStart

Dispatched when Flex begins processing the dataProvider property and begins creating the specified subcomponents.

Basic principles of the Repeater component

The simplest repeating structures you can create with a Repeater component are static loops that execute a set number of times. The following Repeater component emulates a simple for loop that executes four times, printing a simple line of text and incrementing the counter by one each time:

<?xml version="1.0"?>
<!-- repeater/StaticLoop.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns="*">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

    <fx:Script>
        <![CDATA[
            [Bindable]
            public var myArray:Array=[1,2,3,4];
        ]]>
    </fx:Script>

    <fx:Declarations>
        <mx:ArrayCollection id="myAC" source="{myArray}"/>
    </fx:Declarations>

    <!-- Notice that the Repeater is inside a MX container. -->
    <mx:VBox>
        <mx:Repeater id="myrep" dataProvider="{myAC}"> 
            <mx:Label id="Label1" text="This is loop #{myrep.currentItem}"/>
        </mx:Repeater>
    </mx:VBox>
  
</s:Application>

The executing SWF file for the previous example is shown below:

In actuality, the counter is not the data within the array, but the position within the array. As long as the array contains four elements, you can provide any data within the array itself, and the Repeater component still executes four times. The following example illustrates this principle:

<?xml version="1.0"?>
<!-- repeater/StaticLoop2.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Script>
        <![CDATA[
            [Bindable]
            public var myArray:Array=[10,20,30,40];
        ]]>
    </fx:Script>

    <fx:Declarations>
        <mx:ArrayCollection id="myAC" source="{myArray}"/>
    </fx:Declarations>

    <!-- Notice that the Repeater is inside a MX container. -->
    <mx:VBox>
        <mx:Repeater id="myrep" dataProvider="{myAC}"> 
            <mx:Label id="Label1" text="This is loop #{myrep.currentIndex+1}"/>
        </mx:Repeater>
    </mx:VBox>
        
</s:Application>

The executing SWF file for the previous example is shown below:

Notice that this example prints the current index plus one, not the index itself. This is because the first element of the array is assigned an index value of zero (0).

You can also use the startingIndex and count properties to adjust the starting point and total number of executions. The count property sets a maximum on the number of times the Repeater component executes. The count property is often—but not always—an exact measure of the number of times that the content within the Repeater component will execute. This number is because the Repeater component stops after the last element of the data provider is reached, regardless of the value of the count property.

The following example shows how the count and startingIndex properties affect a Repeater component:

<?xml version="1.0"?>
<!-- repeater\StartingIndexCount.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

    <fx:Script>
        <![CDATA[
            [Bindable]
            public var myArray:Array=[100,200,300,400,500,600];
        ]]>
    </fx:Script>

    <fx:Declarations>
        <mx:ArrayCollection id="myAC" source="{myArray}"/>
    </fx:Declarations>

    <mx:VBox>
        <mx:Repeater id="myrep" dataProvider="{myAC}" count="6"> 
            <mx:Label id="Label1" 
                text="Value: {myrep.currentItem}, Loop #{myrep.currentIndex+1} of {myrep.count}"/>
        </mx:Repeater> 
    </mx:VBox>

    <mx:HRule/>

    <mx:VBox>
        <mx:Repeater id="myrep2" dataProvider="{myAC}" 
                count="4" startingIndex="1"> 
            <mx:Label id="Label2" 
                text="Value: {myrep2.currentItem}, Loop #{myrep2.currentIndex-myrep2.startingIndex+1} of {myrep2.count}"/>
        </mx:Repeater> 
    </mx:VBox>

    <mx:HRule/>

    <mx:VBox>
        <mx:Repeater id="myrep3" dataProvider="{myAC}" count="6"
                startingIndex="3"> 
            <mx:Label id="Label3" 
                text="Value: {myrep3.currentItem}, Loop #{myrep3.currentIndex-myrep3.startingIndex+1} of {myrep3.count}"/>
        </mx:Repeater> 
    </mx:VBox>
</s:Application>

The executing SWF file for the previous example is shown below:

The first Repeater component loops through each element of the data provider, starting with the first and stopping after the last. The second Repeater component starts at the second element of the data provider and iterates four times, ending at the fifth element. The third Repeater component starts with the fourth element and continues until the end of the data provider array, and then stops. Only three iterations occur despite the fact that the count property is set to 6.

Creating dynamic loops with the Repeater component

Instead of a static data written directly into your application, your application might work with dynamic data providers. Dynamic data is defined in an <fx:Model> tag and drawn from an XML file, a web service, a remote object, or some other source. The data is collected and evaluated at run time to determine the number and value of elements in the data provider and how the Repeater component behaves.

In the following example, an <mx:Repeater> tag repeats a RadioButton control for each product in an XML file:

<?xml version="1.0"?>
<!-- repeater\DynamicLoop.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark"
    initialize="catalogService.send();">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

    <fx:Declarations>
        <mx:HTTPService id="catalogService" url="assets/repeater/catalog.xml"
                resultFormat="e4x"/>

        <mx:XMLListCollection id="myXC"
                source="{catalogService.lastResult.product}"/>
    </fx:Declarations>

    <mx:VBox>
        <mx:Repeater id="r" dataProvider="{myXC}">
            <mx:RadioButton id="Radio" label="{r.currentItem.name}"
                    width="150"/>
        </mx:Repeater>
    </mx:VBox>
</s:Application>

Assume that catalog.xml contains the following:

<?xml version="1.0"?>
<!-- assets\catalog.xml -->
<products>
  <product>
    <name>Name</name>
    <price>Price</price>
    <freeship>Free Shipping?</freeship>
  </product>
  <product>
    <name>Whirlygig</name>
    <price>5</price>
    <freeship>false</freeship>
  </product>
  <product>
    <name>Tilty Thingy</name>
    <price>15</price>
    <freeship>true</freeship>
  </product>
<product>
    <name>Really Big Blocks</name>
    <price>25</price>
    <freeship>true</freeship>
  </product>
</products>

You can still use the count property to restrict the number of iterations performed. You can use the startingIndex property to skip entries at the beginning of the data provider.

In the preceding example, the first product entry in the XML file contains metadata that other applications use to create column headers. Because it doesn’t make sense to include that entry in the radio buttons, start the Repeater component at the second element of the data provider, as in the following code example:

<?xml version="1.0"?>
<!-- repeater\StartSecondElement.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark"
    initialize="catalogService.send();"> 

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

    <fx:Declarations>
        <mx:HTTPService id="catalogService" url="assets/repeater/catalog.xml"
                resultFormat="e4x"/>

        <mx:XMLListCollection id="myXC"
                source="{catalogService.lastResult.product}"/>
    </fx:Declarations>
            
    
    <mx:VBox>
        <mx:Repeater id="r" dataProvider="{myXC}"
                startingIndex="1">
            <mx:RadioButton id="Radio" label="{r.currentItem.name}"
                width="150"/>
        </mx:Repeater>
    </mx:VBox>
</s:Application>

Referencing repeated components

To reference individual instances of a repeated component, you use indexed id references, as the following example shows:

<?xml version="1.0"?> 
<!-- repeater\RefRepeatedComponents.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

    <fx:Script>
        <![CDATA[

            public function labelTrace():void {
                for (var i:int = 0; i < nameLabel.length; i++)
                    trace(nameLabel[i].text);
            }
        ]]>
    </fx:Script>

    <fx:Declarations>
        <fx:Model id="catalog" source="../assets/repeater/catalog.xml"/>
        <s:ArrayCollection id="myAC" source="{catalog.product}"/>
    </fx:Declarations>
    
    <s:Label id="title" text="Products:"/>   
    
    <s:VGroup>
        <mx:VBox>
            <mx:Repeater id="r" dataProvider="{myAC}" startingIndex="1">
                <mx:Label id="nameLabel"
                    text="{r.currentItem.name}: ${r.currentItem.price}"
                    width="200"/>
            </mx:Repeater>
        </mx:VBox>

        <s:Button label="Trace" click="labelTrace();"/>
    </s:VGroup>
</s:Application>

The executing SWF file for the previous example is shown below:

In this example, the id of the repeated Label control is nameLabel; each nameLabel instance created has this id. You reference the individual Label instances as nameLabel[0], nameLabel[1], and so on. You reference the total number of nameLabel instances as nameLabel.length. The for loop traces the text property of each Label control in the nameLabel Array object. The labelTrace() method prints the name and price of each product in the system log, provided you’ve defined it in the mm.cfg file.

Referencing repeated child components

When a container is repeated and indexed in an array, its children are also indexed. For example, for the following MXML code, you reference the child Label controls of the VBox container vb[0] as nameLabel[0] and shipLabel[0]. The syntax for referencing the children is the same as the syntax for referencing the parent.

<?xml version="1.0"?>
<!-- repeater\RefRepeatedChildComponents.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

    <fx:Script>
        <![CDATA[
        
            public function labelTrace():void {
                for (var i:int = 0; i < nameLabel.length; i++)
                    trace(nameLabel[i].text);
            }
        ]]>
    </fx:Script>

    <fx:Declarations>
        <fx:Model id="catalog" source="../assets/repeater/catalog.xml"/>
    </fx:Declarations>
    
    <s:Label id="title" text="Products:"/>

    <mx:VBox>
        <mx:Repeater id="r" dataProvider="{catalog.product}" 
                startingIndex="1">
            <mx:VBox id="vb">
                <mx:Label id="nameLabel"
                    text="{r.currentItem.name}: ${r.currentItem.price}"
                    width="200"/>
                <mx:Label id="shipLabel" 
                    text="Free shipping: {r.currentItem.freeship}"/>
                <mx:Spacer/>
            </mx:VBox>
        </mx:Repeater>
    </mx:VBox>

    <s:Button label="Trace" click="labelTrace();"/>

</s:Application>

The executing SWF file for the previous example is shown below:

Referencing nested Repeater components

When <mx:Repeater> tags are nested, the inner <mx:Repeater> tags are indexed Repeater components. For example, for the following MXML code, you access the nested Repeater components as r2[0], r2[1], and so on. The syntax for referencing the children is same as the syntax for referencing the parent.

<?xml version="1.0"?>
<!-- repeater\RefNestedComponents.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

  <fx:Script>
    <![CDATA[
    
      public function labelTrace():void {
        for (var i:int = 0; i < nameLabel.length; i++)
         for (var j:int = 0; j < nameLabel[i].length; j++)
          trace(nameLabel[i][j].text);
      }
    ]]>
  </fx:Script>

  <fx:Declarations>    
      <fx:Model id="data">
        <color>
          <colorName>Red</colorName>
          <colorName>Yellow</colorName>
          <colorName>Blue</colorName>
        </color>
      </fx:Model>

      <fx:Model id="catalog" source="../assets/repeater/catalog.xml"/>
      <s:ArrayCollection id="myAC1" source="{catalog.product}"/>
      <s:ArrayCollection id="myAC2" source="{data.colorName}"/>
  </fx:Declarations>    

  <s:Label id="title" text="Products:"/>

  <mx:VBox>
      <mx:Repeater id="r" dataProvider="{myAC1}" startingIndex="1">
        <mx:Repeater id="r2" dataProvider="{myAC2}">
          <mx:Label id="nameLabel" text="{r2.currentItem} {r.currentItem.name}: ${r.currentItem.price}" width="250"/>
        </mx:Repeater>
      </mx:Repeater>
  </mx:VBox>

  <s:Button label="Trace" click="labelTrace();"/>
</s:Application>

The executing SWF file for the previous example is shown below:

This application places the full list of products with color and price into the system log when you click the Button control (provided you have defined the log file in the mm.cfg file).

In the previous example, the instances of the Label control are multiply indexed because they are inside multiple Repeater components. For example, the index nameLabel[1][2] contains a reference to the Label control produced by the second iteration of r and the third iteration of r2.

Using the getRepeaterItem() method in an event handler for the Repeater component

When a Repeater component is busy repeating, each repeated object that it creates can bind at that moment to the Repeater component’s currentItem property, which is changing as the Repeater component repeats. You cannot give each instance its own event handler by writing something like click="doSomething({r.currentItem})" because binding expressions are not allowed in event handlers, and all instances of the repeated component must share the same event handler.

Repeated components and repeated Repeater components have a getRepeaterItem() method that returns the item in the dataProvider property that was used to produce the object. When the Repeater component finishes repeating, you can use the getRepeaterItem() method to determine what the event handler should do based on the currentItem property. To do so, you pass the event.currentTarget.getRepeaterItem() method to the event handler. The getRepeaterItem() method takes an optional index that specifies which Repeater components you want when nested Repeater components are present; the 0 index is the outermost Repeater component. If you do not specify the index argument, the innermost Repeater component is implied.

Note: After a Repeater component finishes repeating, you do not use the Repeater.currentItem property to get the current item. Instead, you call the getRepeaterItem() method of the repeated component itself.

The following example illustrates the getRepeaterItem() method. When the user clicks each repeated Button control, the corresponding colorName value from the data model appears in the Button control label.

<?xml version="1.0"?> 
<!-- repeater\GetItem.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

  <fx:Script> 
    <![CDATA[
      public function clicker(cName:String):void { 
         foolabel.text=cName; 
       }  
    ]]>
  </fx:Script> 

  <s:Label id="foolabel" text="foo"/> 

  <fx:Declarations> 
      <fx:Model id="data"> 
        <color>
          <colorName>Red</colorName> 
          <colorName>Yellow</colorName> 
          <colorName>Blue</colorName>
        </color>
      </fx:Model> 
      <s:ArrayCollection id="myAC" source="{data.colorName}"/>
  </fx:Declarations> 

  <mx:VBox>
      <mx:Repeater id="myrep" dataProvider="{myAC}"> 
        <mx:Button click="clicker(event.currentTarget.getRepeaterItem());"
          label="{myrep.currentItem}"/> 
      </mx:Repeater> 
  </mx:VBox>
</s:Application>

The executing SWF file for the previous example is shown below:

The code in the following example uses the getRepeaterItem() method to display a specific URL for each Button control that the user clicks. The Button controls must share a common data-driven click handler, because you cannot use binding expressions inside event handlers. However, the getRepeaterItem() method lets you change the functionality for each Button control.

<?xml version="1.0"?>
<!-- repeater\DisplayURL.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

  <fx:Script>
    <![CDATA[
      [Bindable]
      public var dp:Array = [ 
        { label: "Flex", url: "http://www.adobe.com/flex" },
        { label: "Flash", url: "http://www.adobe.com/flash" } 
      ];
    ]]>
  </fx:Script>

  <fx:Declarations> 
      <s:ArrayCollection id="myAC" source="{dp}"/>
  </fx:Declarations> 

  <mx:VBox> 
      <mx:Repeater id="r" dataProvider="{myAC}">
        <mx:Button label="{r.currentItem.label}" 
           click="navigateToURL(
            new URLRequest(event.currentTarget.getRepeaterItem().url), '_blank');"/>
      </mx:Repeater>
  </mx:VBox> 
</s:Application>

The executing SWF file for the previous example is shown below:

When executed, this example yields two buttons: one for Flex and one for Adobe® Flash®. When you click the button of your choice, the relevant product page loads in a new browser window.

Accessing specific instances of repeated components

Repeated components and repeated Repeater components have three properties that you can use to dynamically keep track of specific instances of repeated objects, to determine which Repeater component produced them, and to determine which dataProvider items were used by each Repeater component. The following table describes these properties:

Property

Description

instanceIndices

Array that contains the indices required to reference the component from its document. This Array is empty unless the component is in one or more Repeater components. The first element corresponds to the outermost Repeater component. For example, if the id is b and instanceIndices is [2,4], you would reference it on the document as b[2][4].

repeaters

Array that contains references to the Repeater components that produced the component. The Array is empty unless the component is in one or more Repeater components. The first element corresponds to the outermost Repeater component.

repeaterIndices

Array that contains the indices of the items in the dataProvider properties of the Repeater components that produced the component. The Array is empty unless the component is within one or more Repeater components. The first element corresponds to the outermost Repeater component. For example, if repeaterIndices is [2,4], the outer Repeater component used its dataProvider[2] data item and the inner Repeater component used its dataProvider[4] data item.

This property differs from instanceIndices if the startingIndex of any of the Repeater components is not 0. For example, even if a Repeater component starts at dataProvider item 4, the document reference of the first repeated component is b[0], not b[4].

The following example application uses the repeaters property to display the id value of the Repeater components in an Alert control when the user clicks one of the Button controls labelled by the index value of the outer Repeater component and inner Repeater component, respectively. It uses the repeaters property to get the id value of the inner Repeater component:

<?xml version="1.0"?>
<!-- repeater\RepeatersProp.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

  <fx:Script>
    <![CDATA[
      import mx.controls.Alert;
      [Bindable]
      public var myArray:Array=[1,2];
    ]]>
  </fx:Script>

  <fx:Declarations> 
    <s:ArrayCollection id="myAC" source="{myArray}"/>
  </fx:Declarations> 
  
  <mx:VBox> 
      <mx:Repeater  id="repeater1" dataProvider="{myAC}">
        <mx:Repeater  id="repeater2" dataProvider="{myAC}">
          <mx:Button
            label="[{repeater1.currentIndex},{repeater2.currentIndex}]"
            click="Alert.show(event.target.repeaters[1].id);"/>
        </mx:Repeater>
      </mx:Repeater>
  </mx:VBox> 
</s:Application>

The executing SWF file for the previous example is shown below:

The following example application uses the instanceIndices property to set the text property of a TextInput control when the user clicks the corresponding Button control in the set of repeated Button and TextInput controls. You need to use the instanceIndices property because you must get the correct object dynamically; you cannot get it by its id value.

The following example shows how to use the instanceIndices property to set the text property of a TextInput control when the user clicks a Button control. The argument event.target.instanceIndices gets the index of the corresponding TextInput control.

<?xml version="1.0"?>
<!-- repeater\InstanceIndicesProp.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

  <fx:Script>
    <![CDATA[
      [Bindable]
      public var myArray:Array=[1,2,3,4,5,6,7,8];
    ]]>
  </fx:Script>

  <fx:Declarations> 
    <mx:ArrayCollection id="myAC" source="{myArray}"/>
  </fx:Declarations> 
  
  <mx:Box>
      <mx:Repeater id="list" dataProvider="{myAC}" count="4" startingIndex="2">
        <mx:HBox>
          <mx:Button label="Click Me"
            click="myText[event.target.instanceIndices].text=
            event.target.instanceIndices.toString();"/>
          <mx:TextInput id="myText"/>
        </mx:HBox>
      </mx:Repeater>
  </mx:Box>
</s:Application>

The executing SWF file for the previous example is shown below:

The following code shows how to use the repeaterIndices property instead of the instanceIndices property to set the text property of a TextInput control when the user clicks a Button control. The value of event.target.repeaterIndices is based on the current index of the Repeater component. Because the startingIndex property of the Repeater component is set to 2, it does not match the event.target.instanceIndices value, which always starts at 0.

<?xml version="1.0"?>
<!-- repeater\RepeaterIndicesProp.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

  <fx:Script>
    <![CDATA[
      [Bindable]
      public var myArray:Array = [1,2,3,4,5,6,7,8];
    ]]>
  </fx:Script>

  <mx:Box>
      <mx:Repeater id="list" dataProvider="{myArray}" 
        startingIndex="2" count="4">
            <mx:HBox>
                <mx:Button id="b" label="Click Me"
                    click="myText[event.target.repeaterIndices-list.startingIndex].text=
                    event.target.repeaterIndices.toString();"/>
                <mx:TextInput id="myText"/>
            </mx:HBox>
      </mx:Repeater>
  </mx:Box>
</s:Application>

The executing SWF file for the previous example is shown below:

In this case, clicking the button prints the current element of the data provider, not the current iteration of the loop.

Note: The value of the repeaterIndices property is equal to the startingIndex property on the first iteration of the Repeater component. Subtracting the startingIndex value from the repeaterIndices value always yields the instanceIndices value.

Using a Repeater component in a custom MXML component

You can use the <mx:Repeater> tag in an MXML component definition in the same way that you use it in an application file. When you use the MXML component as a tag in another MXML file, the repeated items appear. You can access an individual repeated item by its array index number, just as you do for a repeated item defined in the application file.

In the following example, a Button control in an MXML component called childComp is repeated for every element in an Array object called dp:

<?xml version="1.0"?>
<!-- repeater\myComponents\CustButton.mxml -->
<mx:VBox 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark">

  <fx:Script>
    <![CDATA[
      [Bindable]
      public var dp:Array=[1,2,3,4];
    ]]>
  </fx:Script>

  <fx:Declarations>    
      <s:ArrayCollection id="myAC" source="{dp}"/>
  </fx:Declarations>    
    
  <mx:Box>    
      <mx:Repeater id="r" dataProvider="{myAC}">
        <mx:Button id="repbutton" label="button {r.currentItem}"/>
      </mx:Repeater>
  </mx:Box>    
</mx:VBox>

The application file in the following example uses the childComp component to display four Button controls, one for each element in the array. The getLabelRep() function displays the label text of the second Button in the array.

<?xml version="1.0"?>
<!-- repeater\RepeatCustButton.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009"    
    xmlns:mx="library://ns.adobe.com/flex/mx"     
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:MyComp="myComponents.*">

    <s:layout> 
        <s:VerticalLayout/> 
    </s:layout>

  <fx:Script>
    <![CDATA[
      import mx.controls.Alert;
      public function getLabelRep():void {
        Alert.show(comp.repbutton[1].label);
      }
    ]]>
  </fx:Script>
    
  <MyComp:CustButton id="comp"/>

  <s:Button label="Get label of Repeated element" width="200"
    click="getLabelRep();"/>
</s:Application>

The executing SWF file for the previous example is shown below:

Dynamically creating components based on data type

You can use a Repeater component to dynamically create different types of components for specific items in a set of data. A Repeater component broadcasts a repeat event as it executes, and this event is broadcast after the currentIndex and currentItem properties are set. You can call an event handler function on the repeat event, and dynamically create different types of components based on the individual data items.

How a Repeater component executes

A Repeater component executes initially when it is instantiated. If the Repeater component’s dataProvider property exists, it proceeds to instantiate its children, and they instantiate their children, recursively.

The Repeater component re-executes whenever its dataProvider, startingIndex, or count properties are set or modified either explicitly in ActionScript, or implicitly by data binding. If the dataProvider property is bound to a web service result, the Repeater component re-executes when the web service operation returns the result. A Repeater component also re-executes in response to paging through the dataProvider property by incrementally increasing the startingIndex value, as the following example shows:

r.startingIndex += r.count;

When a Repeater component re-executes, it destroys any children that it previously created (assuming the recycleChildren property is set to false), and then reinstantiates its children based on the current dataProvider property. The number of children in the container might change, and the container layout changes to accommodate any changes to the number of children.

Recreating children in a Repeater component

The recycleChildren property controls whether children of a Repeater component are recreated when the Repeater component re-executes. When you set the recycleChildren property to false, the Repeater component recreates all the objects when you swap one dataProvider with another, or sort, which causes a performance lag. Only set this property to true if you are confident that modifying your dataProvider will not recreate the Repeater component’s children.

The default value of the recycleChildren property is false, to ensure that you do not leave stale state information in a repeated instance. For example, suppose you use a Repeater component to display photo images, and each Image control has an associated NumericStepper control for how many prints you want to order. Some of the state information, the image, comes from the dataProvider, while other state information, the print count, is set by user interaction. If you set the recycleChildren property to true and page through the photos by incrementally increasing the Repeater component’s startingIndex value, the Image controls bind to the new images, but the NumericStepper controls keep the old information.