Adding links to MX and Spark DataGrids using inline item renderers

While working on a recent project, I couldn’t find examples of adding inline links to the Spark and MX DataGrids. There were lots of examples of item renderers, but nothing that did exactly what I wanted: just a hyperlink in the DataGrid cell.

Below are two examples: one shows the Spark DataGrid and the other shows the MX DataGrid with inline links.

There are some subtle differences between how to define an inline item renderer. There are also some subtleties to the way you define the links. I’ll let the code speak for itself, but note that there are some things to keep in mind:

  • The cursor changes to a hand when you mouse over the link (without embedding a new cursor image or invoking the CursorManager)
  • The links are styled blue and underlined like real web links
  • For the MX DataGrid, it’s mx:DataGridColumn > mx:itemRenderer > fx:Component > mx:Label
  • For the Spark DataGrid, it’s s:GridColumn > s:itemRenderer > fx:Component > s:GridItemRenderer > s:Label
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx">
    
    <fx:Declarations>
        <!-- Define the data -->
        <fx:XMLList id="siteList">
            <site>
                <name>IMDB</name>
                <url>http://www.imdb.com</url>
            </site>
            <site>
                <name>BoardgameGeek</name>
                <url>http://www.boardgamegeek.com</url>
            </site>
            <site>
                <name>Yahoo! Finance</name>
                <url>http://finance.yahoo.com</url>
            </site>
        </fx:XMLList>
        <!-- Use an XMLListCollection for the Spark DataGrid -->
        <s:XMLListCollection id="siteList2" source="{siteList}"/>
    </fx:Declarations>
    
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>
    
    <s:Panel title="Spark DataGrid Links"
             width="75%" height="75%" 
             horizontalCenter="0" verticalCenter="0">
            <s:DataGrid id="sparkDataGrid" 
                        width="100%" height="100%" 
                        dataProvider="{siteList2}">
                <s:columns>
                    <s:ArrayList>
                        <s:GridColumn dataField="name" headerText="Name"/>
                        <s:GridColumn dataField="url" headerText="URL">
                            <s:itemRenderer>
                                <fx:Component>
                                    <s:GridItemRenderer>                                  
                                        <s:Label text="{data.url}" 
                                            color="0x336699" 
                                            verticalCenter="0" paddingLeft="5" 
                                            textDecoration="underline" 
                                            buttonMode="true" 
                                            click="navigateToURL(new URLRequest(data.url))"/>
                                    </s:GridItemRenderer>
                                </fx:Component>
                            </s:itemRenderer>                 
                        </s:GridColumn>
                    </s:ArrayList>
                </s:columns>      
            </s:DataGrid>
    </s:Panel>

    <s:Panel title="MX DataGrid Links"
             width="75%" height="75%" 
             horizontalCenter="0" verticalCenter="0">
        <mx:DataGrid id="mxDataGrid" 
                     width="100%" height="100%" 
                     dataProvider="{siteList}">
            <mx:columns>
                <mx:DataGridColumn headerText="Name" dataField="name"/>
                <mx:DataGridColumn headerText="URL" dataField="url">
                    <mx:itemRenderer>
                        <fx:Component>
                            <mx:Label text="{data.url}" 
                                      textDecoration="underline" 
                                      color="0x336699" 
                                      buttonMode="true" 
                                      useHandCursor="true" 
                                      mouseChildren="false"
                                      click="navigateToURL(new URLRequest(data.url))"/>
                        </fx:Component>
                    </mx:itemRenderer>
                </mx:DataGridColumn>              
            </mx:columns>
        </mx:DataGrid>
    </s:Panel>    
</s:Application>

Getting Started Resources for Flex 4.5, Flash Builder 4.5, and Flex Mobile

The Flex 4.5 release introduced many new features, including support for mobile devices and tablets. The following links will help you get started with the Flex 4.5 release:

And don’t forget about the Flex documentation at http://www.adobe.com/devnet/flex/documentation.html. In particular, there is new content that focuses on mobile app development with Flex

 

Stephen Gilson
Flex Doc Team

Flash Builder 4.5 and Flex 4.5 documentation is live!

As you probably already know, we shipped Flex 4.5 and Flash Builder 4.5 today. Although you’ll find a lot of information on the Flex product page, the Flash Builder product page, the Flex Developer Center, and the (new!) Flash Builder Developer Center, I’m using this post to focus on the documentation:

  • (New!) Developing Mobile Applications with Flex and Flash Builder – Contains information on using mobile-oriented Flash Builder and Flex features. We put a lot of effort into making this content as clear and searchable as possible and are all very proud of it. That said, I recommend that you start by reading NJ’s Mobile development using Adobe Flex 4.5 SDK and Flash Builder 4.5 article before jumping in. Notice that the pages in this book contain numerous links to external videos, devcenter articles, and blog posts, which we think will be tremendously helpful as you come up to speed in this new area.
  • Platform ActionScript Reference – Contains new and updated classes for all Adobe products that feature ActionScript APIs. In particular, it has new Flex classes, such as Spark DataGrid, Image, and Form. If you haven’t used the Platform ASR before, note that you can change the filter settings to control which products and versions you see.
  • Using Flex – Contains usage information on new Flex SDK features, such as Spark DataGrid, Image, and Form (remember, we have corresponding reference and usage discussions for most Flex features). This book also contains updates and enhancements to existing discussions.
  • Using Flash Builder – We reorganized this book to clarify the Flash Catalyst, ActionScript, and Flash Professional workflows. In particular, there is new information on implementing two-way designer-developer workflows with Flash Catalyst.
  • Accessing Data with Flex – There aren’t many changes to this book, although we did update screen shots in the Flash Builder workflows.

And lightning will strike me down if I neglect to highlight the amazing work done by the Flex and Flash Builder Community Help & Learning (aka documentation) team: Stephen Gilson, Matt Horn, Mallika Yelandur, Pam Araki, Rosana Francescato, Janice Campbell, Sunil Bhaskaran, and Helen Li all did a great job bringing this content to fruition. Also we received critical support from Cate de Heer, Denise Green, Brian Rinaldi, my old friend Erick Vera, and my manager, Helen Whelan.

That’s all for now, but my team and I will be updating this site regularly over the next few weeks, so stay tuned.

-Randy

Update – May 4, 2011: – Sorry. I forgot three important links:

Upgrading and reinstalling the Adobe Community Help Client (CHC)

Hi all,
Over the past few months, I’ve spent a lot of time talking to internal and external customers about Adobe Community Help. Some of the people I’ve met have complaints about the CHC not working (a common issue is that context-sensitive help is broken) and in many cases, this is because they have an old version. In particular, customers who were in either the Flash Builder prerelease or the CS 5 prerelease will have context-sensitive help issues and can have trouble updating.

The current CHC release is 3.2.0.610 (one customer I spoke with last week was still on 2.6.1.14!)

In most cases, the CHC prompts you when an update is available. However, if that isn’t working, follow the instructions on http://kb2.adobe.com/cps/842/cpsid_84215.html to uninstall and reinstall the CHC AIR application.

If you’ve been unhappy with the CHC, I ask that you please upgrade and try it out again. There are a lot of new features and I think you’ll be happy with all the improvements.

Best regards,
Randy Nielsen
Senior Content and Community Manager
Adobe Systems Incorporated

Optimizing FXG

FXG is a popular declarative XML syntax for defining vector graphics in applications built with Flex. FXG can also be used as an interchange format with other Adobe tools such as Illustrator or Photoshop. Here are some techniques for improving the quality of your FXG graphics and making working with FXG easier.

Composite path versus rounded rectangle
Composite paths create a cleaner look because there are no extra pixels inside the corners. Rounded rectangles, on the other hand, have extra pixels due to anti-aliasing. Rounded rectangles convert to a <Rect> element in FXG, which is preferable because a <Rect> element is easier to manipulate than a compex path.

Move alpha values from the element to the fill or stroke
When exporting FXG files from a graphics editor, the alpha property is sometimes placed on the graphic element tag. If you convert the FXG to MXML, this element uses its own DisplayObject, which can be computationally expensive. To avoid this, move any alpha properties from the element tag down to the stroke or fill. If both the stroke/fill and the element have alpha values, multiply the stroke and fill alpha values by the element’s alpha value. For example, if the stroke and element alpha values are both .5, then remove the element’s alpha property and set the stroke’s alpha to .25 (.5 x .5).

Round alpha values to 2 decimal places
Exported FXG files sometimes use percentage values for alpha values. The visual difference between an alpha value with two decimal places and a rounded alpha value is negligible. To make your code more readable, round off alpha values to 2 decimal places. For example, round an alpha value of 0.05882352941176471 to 0.06.

Remove blendMode=”normal”
By default on graphic elements, the blendMode is “auto”. When the blendMode property is “auto”, Flash Player correctly determines whether the element needs to use the “layer” blendMode based on the alpha value.

Identifying elements of an FXG file
Sometimes it can be hard to look at FXG tags and determine what that element looks like. An easy way to do this is to copy your FXG into a <s:Group> tag in an MXML application. Then, change the x values of each element so that they no longer overlap. For example, if your skin is 45 pixels wide and is comprised of three <Rect> elements, increase the x value of the second <Rect> by 50 and the third <Rect> by 100. When you compile and run the application, you can see each layer spread separately.
An alternative is to toggle the visible property of different elements so that you can isolate a particular element.

Reduce anti-aliasing due to stage quality
AIR applications are currently limited to using StageQuality.MEDIUM. When designing skins using FXG and/or programmatic graphics, watch for anti-aliasing artifacts in rounded corners.

To create the appearance of a rounded rectangle at a 1px stroke in Fireworks:

  1. Draw a filled rounded rectangle.
  2. Copy the rectangle, position it 1px down and to the left of the original rectangle and reduce its width and height by 2px.
  3. Select both rectangles, right click and choose Combine Path > Punch.

Use 45 degree angles
Try to keep all angles at 45 degrees. This helps to reduce the visual artifacts from anti-aliasing.

For more information
For more information on using FXG in your Flex applications, see Using FXG.

Creating Flex View States in ActionScript

In Flex 4, Adobe introduced new MXML language improvements that make it much easier to work with states. This support includes the dot (.) delimiter for specifying state overrides, and the new MXML excludeFrom and includeIn attributes.

The following item renderer, MySimpleCustomItemRendererMXML.mxml in the myComponents subdirectory, uses view states to control the appearance of the items in a SkinnableDataContainer container:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer 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:states>
        <s:State name="normal"/>
        <s:State name="hovered"/>
    </s:states>

    <s:Label id="labelDisplay"
        verticalCenter="0"
        left="3" right="3" top="6" bottom="4"
        fontSize.hovered='14' fontStyle.hovered="italic"/>
</s:ItemRenderer>

The following application uses this item renderer:

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

    <s:SkinnableDataContainer
        itemRenderer="myComponents.MySimpleCustomItemRendererMXML">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>

    <mx:ArrayList>
        <fx:String>Bill J Smith</fx:String>
        <fx:String>Dave Jones</fx:String>
        <fx:String>Mary Davis</fx:String>
        <fx:String>Debbie Cooper</fx:String>
        </mx:ArrayList>
    </s:SkinnableDataContainer>
</s:Application>

However, you might also want to create view state in ActionScript, either in an MXML file or in an ActionScript file. The following example uses the creationComplete event to define the view states in ActionScript:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx"
    xmlns:s="library://ns.adobe.com/flex/spark"
    creationComplete="creationCompleteHandler(event);">

    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;
            import mx.states.SetStyle;
            import mx.states.State;

            protected function creationCompleteHandler(event:FlexEvent):void {
                states = [
                    new State({name:"normal"}),
                    new State({name:"hovered",
                        overrides:[
                            new SetStyle(labelDisplay, "fontSize", 14),
                            new SetStyle(labelDisplay, "fontStyle", "italic")]
                        })
                ];
            }
        ]]>
    </fx:Script>

    <s:Label id="labelDisplay"
        verticalCenter="0"
        left="3" right="3" top="6" bottom="4"/>
</s:ItemRenderer>

In this example, you import the mx.states.State and mx.states.SetStyle classes. Every Flex component inherits the mx.core.UIComponent.states property. This property contains an Array of State objects that define the supported view states of the component. In the event handler for the creationComplete event, create an Array of State objects. The name property of the State objects defines the name of the view state.

The State.overrides property contains an Array of objects that implement the mx.states.IOverride interface. The AddChild, AddItems, RemoveChild, SetEventHandler, SetProperty, and SetStyle classes all implement this interface. In this example, you create two instances of SetStyle that override the fontSize and fontStyle styles of the Label control. You can mix objects of type AddChild, AddItems, RemoveChild, SetEventHandler, SetProperty, and SetStyle in the overrides Array.

Note that manipulating at runtime view states, containers that use view states, or properties of components that are controlled by view states can be problematic. For example, when you use view states to control the children of a container, do not add or remove container children, or change the order of children in the container, at runtime. The following container defines a Button control that appear only in State2:

<s:Group>
    <s:Button/>
    <s:Button includeIn="State2"/>
    <s:Button/>
</s:Group>

The view states infrastructure relies on the structure of the container as defined by the MXML file. Changing the child order of the container at runtime can cause your application to fail. Therefore, do not call the addElement(), removeElement(), or setElementIndex() method on the Group container at runtime, or any other method that changes the child order of the container.

For more infomration, see:

 

Stephen Gilson
Flex Doc Team

Layout mirroring feature now live

The latest release of Flex and Flash Builder include the new layout mirroring feature. This feature aims to make it simple for you to create RTL (right-to-left) applications with just a couple of settings. Read all about it in Mirroring and bidirectional text.

You can download the new releases here:

Flash Player 10.1 Admin Guide available

The outstanding Flash Platform doc blog has a link to the new admin guide for Player 10.1. This document covers tons of information including:

  • Player environment (file storage, processes, and versioning)
  • Installation
  • Administration settings (primarily privacy, security and disk space settings)
  • User-configured settings
  • Security

Much of this stuff is critical to Flex as well as Flash developers.

Layout mirroring for Flex 4.1

The layout mirroring feature is part of the upcoming 4.1 release of the Flex SDK. If you are interested, you can take a look at the first draft of the documentation for this feature. There are two parts to this:

Documentation in an HTML file
Examples in a ZIP file

Any feedback is welcome!

Flex Tutorials for Data Access with Flash Builder

We’ve just updated the Flex Tutorials for Data Access with Flash Builder. In addition to making a few corrections to the original versions, we’ve included examples of using server-side typing.

The Data Management tutorial accesses employee data from the server. The new version of this tutorial illustrates both server-side and client-side typing to define the Employee data type.

With client-side typing, you use Flash Builder wizards to introspect the data on the server and define the Employee data type in client code. With server-side typing, server code defines the Employee data type.

Both PHP and ColdFusion let you define custom data types in server code. Flash Builder recognizes the custom data type during introspection of services. You do not have to walk through the wizard screens to configure the return data type.

Whether you use server-side or client-side typing is a developer preference. Server-side typing can help enforce data integrity on the server and simplify the Flash Builder workflow. Client-side typing simplifies the service coding while using Flash Builder to define the custom data types.