Adobe
Products
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
Student and Teacher Editions
More products
Solutions
Creative tools for business
Digital marketing
Digital media
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Buy
Home use for personal and home office
Education for students, educators, and staff
Business for small and medium businesses
Licensing programs for businesses, schools, and government
Special offers
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
My products and services
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out My orders My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Review and Checkout
Adobe Developer Connection / Flex Developer Center /

Building an icon-checkbox component with Flex 3

by Mark Niemann-Ross

Mark Niemann-Ross
  • niemannross.com

Created

19 November 2007

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
components Flex 3 MXML

Requirements

Prerequisite knowledge

To benefit most from this series, it is best if you have a basic working knowledge of Flex.

User level

Intermediate

Required products

  • Flex Builder (Download trial)

Sample files

  • plugin_browser.zip (1843 KB)

Note: This article was created based on the Flex 3 beta releases. Minor changes in the description and code may be necessary before it can be applied to Flex 3.

Two-state buttons (push-on, push-off) are a fairly common component, and Adobe Flex addresses these simple needs with both the button and check box controls. Recently I needed an icon-only version, and also needed to create multiple versions of the button.

This article shows how I learned to create a custom component based on the Flex checkbox component, and some of the tricks I learned along the way.

Getting started

Whenever I write applications, I first sit down with a pencil and paper (yes, I do—literally) and sketch out what I want the finished product to look like, based on what I know it should do. The upside of this drawing is that I don't get distracted by user interface components that might be easy or fun, and instead work towards the intended functionality. The downside is that I often wind up "coloring outside the lines"—and having to look for interesting ways of accomplishing what I want to do, but it is not often what the development environment provides. I'll assume this is also your preferred method—so now, both of us are wandering into new territory.

I created the Creative Suite Plug-in Browser for customers who were looking for a solution—and I knew it needed to allow a user to search by Adobe product. I wanted to create a push button with the Adobe product icon. When a user selects an icon in the control, the icon is grayed-out, and any plug-in that only works with that Adobe product no longer displays in the list. When the user selects the icon again by clicking it, the product list display is updated. I thought that a push button with icons would be attractive, an effective use of space, good Adobe branding, and so on. Just to prove that it can be done, look at Figure 1.

Adobe Creative Suite Plug-in Browser
Figure 1. Adobe Creative Suite Plug-in Browser

Lucky me! Flex check boxes are built to be reskinned. Simply create 10 icons and I'm done!

Using the crowbar approach

First, I quickly created 10 check boxes. Here's the code for the first one:

<mx:CheckBox x="280" y="112" label="aiCB" width="60" height="60"> <mx:upIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon_disabled.jpg')</mx:upIcon> <mx:overIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon_disabled.jpg')</mx:overIcon> <mx:downIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon_disabled.jpg')</mx:downIcon> <mx:selectedUpIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon.jpg')</mx:selectedUpIcon> <mx:selectedOverIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon.jpg')</mx:selectedOverIcon <mx:selectedDownIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon.jpg')</mx:selectedDownIcon <mx:selected>true</mx:selected> <mx:width>60</mx:width> <mx:height>60</mx:height> <mx:change>promoterbotArray.refresh()</mx:change> </mx:CheckBox>

Most of this code supplies the proper icons for the various states of the check box. There are also width/height tags, and a brief chunk of code that refreshes the list anytime the button changes state.

Now do that nine more times. But wait—what's that alarm I hear? Oh yes, it's the "crappy, non-reusable-code alarm."

Experienced coders will point out several things about this method:

  • If you change the pathname of the icons, you'll face 60 corrections.
  • If you change how the buttons work, you'll face 10 corrections.
  • This is going to make messy code that is difficult to read and maintain.
  • Most importantly, your peers will laugh at you and talk trash behind your back!

Making efficient check boxes

What I really needed was to create some sort of template for this check box, and then apply changes to it. In normal JavaScript, you would typically build a function that dynamically builds a component using a set of parameters. You might even build an object and create instances of a new check box. Flex provides a really easy way of doing this called a component. Components are a lot like objects—except easier to work with. No instantiation needed: just code and go!

The Flex help files have a great description on creating custom components. I'll abbreviate the steps here:

  1. Assuming you're using Flex Builder, select File > New MXML Component. You might want to create a "components" folder in your Flex project and then put the code in that folder. Name it something creative. I called mine iconCheckbox.mxml and put it in a folder called mnrComponents.
  2. In your main source (main.mxml), you'll need to connect the two files. To do this, add a namespace tag to the Application tag at the very beginning of the code. Here's the code before and after.

    Before:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

After:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml/2006/mxml" xmlns:mnr="mnrComponents.*" layout="absolute" >

Your mx:Application tag might have other tags in it, but the important thing is that the xmlns:mnr has connected the main code with the new component. In my example, mnr is the new namespace (it can be anything that makes sense to you) and mnrComponents.* links your main.mxml with any files located in the mnrComponents directory.

When you are ready to use your new, personalized check box, you identify it with the new namespace you just created. Instead of using <mx:CheckBox>, you would use <mnr:iconCheckbox>. If you don't do anything to the component you defined in the first step above, your new check box will behave identically to the normal Flex check boxes.

But: I have big plans for this little check box…

Playing pass the icon

Most importantly, I wanted each check box to use custom icons—and I wanted to specify only the "Up" icon and the "Down" icon. I wanted the component to handle all the messy assignments to the upIcon, overIcon, downIcon, and so forth.

Passing parameters to a component is easy; I'll leave it up to you to refer to the instructions in the help file. However, passing icons proved to be somewhat tricky. I tried passing the @embed data—with no luck. I tried passing the string, but components won't embed images. It turns out you little choice but to put on the ActionScript hat.

I finally solved this with two main steps: Create a collection of "embeds" and assign them to variables, and then pass the variables to the check box component, shown in the following section.

Embed the icons

First, create an ActionScript file (File > New > ActionScript File), name it adobeProductIcons.as or whatever makes sense to you, and stash it in a project folder (I used "Actionscript_includes"). Connect it to your main.mxml with the following line, placed immediately after the <mx:Application...> tag:

<mx:Script source="Actionscript_includes/adobeProductIcons.as" />

Inside of adobeProductIcons.as, embed and bind the icons. It will look something like the following:

// Illustrator icons [Embed(source=file:////Users/mnr/Documents/adobeLogos/ai_appicon_disabled.jpg")] [Bindable] public var aiIconDisabled:Class; [Embed(source=file:////Users/mnr/Documents/adobeLogos/ai_appicon.jpg")] [Bindable] public var aiIcon:Class;

Do this for each disabled/enabled icon pair, once for each check box. Save it and close it.

Pass the icons

You'll need to create some ActionScript variables to pass the icon data to the component. At the top of iconCheckbox.mxml, right after the <mx:Application> tag, add the following:

<mx:Script> <![CDATA[ [Bindable] public var theActiveIcon:Class; [Bindable] public var theDisabledIcon:Class; ]]> </mx:Script>

This creates two variables: theActiveIcon and theDisabledIcon. Once you declare those variables, you can use them in iconCheckbox.mxml to handle the messy process of skinning the check box. Add this code right after the <mx:script> tag you added above:

<mx:upIcon>{theDisabledIcon}</mx:upIcon> <mx:overIcon>{theDisabledIcon}</mx:overIcon> <mx:downIcon>{theDisabledIcon}</mx:downIcon> <mx:selectedUpIcon>{theActiveIcon}</mx:selectedUpIcon> <mx:selectedOverIcon>{theActiveIcon}</mx:selectedOverIcon> <mx:selectedDownIcon>{theActiveIcon}</mx:selectedDownIcon>

Add a few other details

These buttons are always the same size, so you can add the following code to the component:

<mx:width>60</mx:width> <mx:height>60</mx:height>

This provides a little bonus. If you want to change the size of the icons, change the values in iconCheckbox.mxml—one change, instead of having to change each individual check box. Keep in mind that doing something like this makes this component unique to your application ("tightly coupled") because it assumes the check boxes made with this component always have a width and height of 60. I'm violating reusability guidelines in favor of this particular shortcut.

Try it!

In your main.mxml, you can see how this works. Originally, each check box required the following code:

<mx:CheckBox x="280" y="112" label="aiCB" width="60" height="60"> <mx:upIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon_disabled.jpg')</mx:upIcon> <mx:overIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon_disabled.jpg')</mx:overIcon> <mx:downIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon_disabled.jpg')</mx:downIcon> <mx:selectedUpIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon.jpg')</mx:selectedUpIcon> <mx:selectedOverIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon.jpg')</mx:selectedOverIcon> <mx:selectedDownIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon.jpg')</mx:selectedDownIcon> <mx:selected>true</mx:selected> <mx:width>60</mx:width> <mx:height>60</mx:height> <mx:change>promoterbotArray.refresh()</mx:change> </mx:CheckBox>

Now, you can do this instead:

<mnr:iconCheckbox id="aiCB" theActiveIcon="{aiIcon}" theDisabledIcon="{aiIconDisabled}"> <mx:change>promoterbotArray.refresh()</mx:change> </mnr:iconCheckbox>

This new code just makes my heart sing! I've removed about 90 lines of code from main.mxml, and my peers aren't laughing at me nearly as loud as before.

Manipulating objects outside of the component

But there's still that pesky <mx:change>promoterbotArray.refresh()</mx:change> line that needs to be repeated for each check box. Briefly, it tells the promoterbotArray that it needs to filter out the products that shouldn't be listed. Look up "DataGrid Control" in the help topics for more details. There's a lot more to it, but that's another story. Briefly, I originally tried to place it just in iconCheckbox.mxml but found that the component didn't know what I was talking about. Quelle est cette promoterbotArray, vous demandez? It turns out that since promoterbotArray was defined in main.mxml, it was "out of scope" for the component—kind of like looking for your socks in the refrigerator: you have to know where to look to find stuff.

It took a bit of digging but it turns out that components are actually nested inside of the main code. If you are familiar with JavaScript, you know that you can change scope by using the DOM addressing model. Likewise for components in Flex—with a catch. In most of the Flex documentation, the outerDocument property is used to access objects defined outside of a component. Seems logical—but it didn't work. It wasn't until I discovered parentDocument that the component worked.

I added this line to iconCheckbox.mxml and, hey-presto, it works like a charm!

<mx:change>parentDocument.promoterbotArray.refresh()</mx:change>

Of course, this really violates reusability guidelines. I've now written a component that assumes there is a particular array located in a specific location. It might be better to leave this as part of the check box definition in the "main.mxml" code. Again, I've made a tradeoff between reusability and what I view as simplicity.

Back to main.mxml

It may seem like a long trip, but this has a lot of benefits. In this case, I started off with this…

<mx:CheckBox x="280" y="112" label="aiCB" width="60" height="60"> <mx:upIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon_disabled.jpg')</mx:upIcon> <mx:overIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon_disabled.jpg')</mx:overIcon> <mx:downIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon_disabled.jpg')</mx:downIcon> <mx:selectedUpIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon.jpg')</mx:selectedUpIcon> <mx:selectedOverIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon.jpg')</mx:selectedOverIcon> <mx:selectedDownIcon>@Embed('file:////Users/mnr/Documents/adobe CS3 logos/ai_appicon.jpg')</mx:selectedDownIcon> <mx:selected>true</mx:selected> <mx:width>60</mx:width> <mx:height>60</mx:height> <mx:change>promoterbotArray.refresh()</mx:change> </mx:CheckBox>

…times 10—one for each button—cluttering up main.mxml. After all the component work, creating a check box now takes one line:

<mnr:iconCheckbox id="cbAI" theActiveIcon="{aiIcon}" theDisabledIcon="{aiIconDisabled}" />

Where to go from here

If you are going to create custom components, be sure to read the Adobe Flex  documentation chapter on creating MXML components. Especially take a look at the chapter titled "About reusable MXML components"—it explains the difference between tightly coupled and reusable components, and when they are appropriate.

Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License

More Like This

  • Introducing the MXML and ActionScript languages
  • The technologies for building Flex and Java applications
  • What's new in Flex 4.6 SDK and Flash Builder 4.6
  • Introducing Adobe Flex 4.6 SDK
  • Layout mirroring with Flex
  • Flex 3 Component Solutions excerpt: Introducing hierarchal data and components
  • Creating Flex components
  • Creating components and enforcing separation of concerns with Flex
  • Building interactive maps with Flex
  • Flex 3 Component Solutions excerpt: Audio and video components

Tutorials & Samples

Tutorials

  • Flex mobile performance checklist
  • Flex and Maven with Flexmojos – Part 3: Journeyman
  • Migrating Flex 3 applications to Flex 4.5 – Part 4

Samples

  • Twitter Trends
  • Flex 4.5 reference applications
  • Mobile Trader Flex app on Android Market

Flex User Forum

More
07/25/2011 Flash Player Debug Issues - Safari 5.1 & Chrome 13
04/22/2012 Loader png - wrong color values in BitmapData
04/22/2012 HTTPService and crossdomain.xml doesn't work as expected
04/23/2012 Memory related crashes in Flex application

Flex Cookbook

More
04/06/2012 How to detect screen resize with a SkinnableComponent
02/29/2012 Embed Stage3D content inside Flex application components
02/15/2012 Custom WorkFlow Component
02/09/2012 Using Camera with a MediaContainer instead of VideoDisplay

Products

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • Mobile Apps
  • Photoshop
  • Touch Apps
  • Student and Teacher Editions

Solutions

  • Digital marketing
  • Digital media
  • Web Experience Management

Industries

  • Education
  • Financial services
  • Government

Help

  • Product help centers
  • Orders and returns
  • Downloading and installing
  • My Adobe

Learning

  • Adobe Developer Connection
  • Adobe TV
  • Training and certification
  • Forums
  • Design Center

Ways to buy

  • For personal and home office
  • For students, educators, and staff
  • For small and medium businesses
  • For businesses, schools, and government
  • Special offers

Downloads

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy Policy and Cookies (Updated)

Ad Choices

Reviewed by TRUSTe: site privacy statement