Many Flex apps have DataGrids. Many of those DataGrids want to display something other than plain text which requires the use of custom item renderers. I've seen lots of questions and complaining about how hard it is to make simple custom item renderers. I didn't design it to be that hard, so I decided to take some time and make some examples of how I'd do it to serve as a starting point for some of the things you want to do in DataGrids.
I found the difficulty level to be about what I expected, but along the way I reminded myself of somethings you might find useful when making your own item renderers. What follows are those things you should probably know, and then some examples.
Recycling
Custom Item Renderers does take a mental shift from other kinds of UI development in Flex. This is because item renderers need to be completely data-driven, and because they are not mapped to the dataprovider in a one-to-one fashion. A single instance of an item renderer can end up displaying the data of several different items in your data provider. It might display the first item, then the tenth, then the second as you scroll up and down in the DataGrid. We do this for efficiency reasons: if we made a renderer for every item in the data provider it would consume tons of memory. Therefore we only create item renderers that are visible, plus a few others for measurement and buffering. This has the following implications:
You cannot assume the renderer has been freshly created. When it is time to update the renderer, the components might be holding old values from the item it was rendering before.
You cannot assume that there are only as many renderers created as you see on-screen.
You cannot assume that the first renderer created is for the first visible row.
The most common error I've seen is in not resetting values. For example, if you have code that makes the text red if the value is below zero, you might write:
if (data.price < 0)
setStyle("color", 0xFF0000);
This is incorrect. It will work the first time the renderer is created since the default color is black and will work if values are greater than 0, and if the value is less than zero. But once the renderer displays a value less than zero and turns the text red, if it is later asked to renderer a different value that is greater than zero, there is no code to turn the color back to black again. What will happen is that the data will look fine until you start scrolling or receiving updates, then the red will start to appear in funny places. The correct way is to write code like this:
if (data.price < 0)
setStyle("color", 0xFF0000);
else
setStyle("color", 0x000000);
That code will reset the color to black if the price is greater than 0.
Performance
When designing custom item renderers, you should keep performance in mind. While it is simple and fast to take a Canvas, HBox or VBox and put a few components in there and have a renderer, keep in mind that containers are really big and slow and if you are going to have lots of them visible in your DataGrid, you might run into performance problems. We often don't see them because we develop on really fast machines, but you have to consider what kind of hardware your end-user will have. So, I'd discourage the use of any container from mx.containers in a custom item renderer if there's going to be more than a half-dozen on screen. Unless you are laying out more than three or four widgets in your renderer, it will be much faster to start with UIComponent and just write some logic to layout the components in their correct positions. Containers from mx.containers also factor in deferred instantiation logic, scrollbars, clipping and a bunch of other things that your probably don't need to use in your renderer.
That's why you'll see that all of the examples use ActionScript instead of MXML. Yes, that means that you can't use FlexBuilder to code the renderer, and yes, some of these examples could be done in MXML, but it is easy in MXML to do things that generate extra code that you may not need. You'll notice that I do not use databinding in these examples for the same reason. It is actually a bit wasteful (although very convenient) to use binding on something that isn't going to change or only change once or twice. Instead, I set the dataprovider on the initialize event (and would do so on a result event if I used HTTPService).
Events
One frequent complaint is that, if your renderer dispatches events, it is hard to find a way to listen to those events. This is true to a degree. We sort of figured that 80% of renderers would be passive. I'm now thinking that number is closer to 50%. However, it isn't really that hard to get events, or even to be able to hook up to those events in MXML. First, you need Flex 2.0.1 or later. While some have suggested that you use event bubbling to get events out of the DataGrid, I think that's potentially unscalable. If you don't guarantee that the event has a unique name, there could be some parent container of DataGrid that uses the same event name and you'll get runtime errors. Instead, simply dispatch an event from the owner as in:
var event:Event = new ListEvent("myCustomEventName");
event.itemRenderer = this;
owner.dispatchEvent(event);
This event is then dispatched from the DataGrid, and has a reference to the renderer (and therefore the data) that was affected. To write a handler in MXML, you simply have to subclass DataGrid and add event metadata as in:
/**
* Broadcast when the user does something in the item renderer
*/
[Event("myCustomEventName")]
/**
* Subclass of DataGrid that dispatches a custom event.
*/
public class MyDataGrid extends DataGrid ...
...
DataGridColumns
However, I want to introduce another way of handling events, and that is to use custom DataGridColumns. The DataGridColumn can act as a proxy for item renderers allowing maximum reuse by allowing the specification of parameters on the column that the renderers respond to, and by being a place to listen to for events from the columns. You'll see many of these examples use subclasses of DataGridColumn that are paired with the custom renderer. One example, the ComboBoxHeader example, uses custom events from the DataGridColumn instead of through the DataGrid.
DataProviders and Collections
It is also possible to write custom DataProviders/Collections. You don't have to work just with Arrays or XMLLists. The example NameValueTable takes a data object and displays it in a DataGrid by using a custom collection to enumerate the properties based on a ordered list of properties for the data object.
The Examples
These examples come with the usual caveats. They are unsupported, might have bugs, might not work in your app. Also note that future releases of Flex will likely have more powerful DataGrid features built-in. However, if you can't wait, maybe these examples will help.
BackgroundColor in Item Renderers
Background Color Demo
Background Color Source
While you can use a Canvas and the backgroundColor style to do this, it turns out that the default DataGridItemRenderer is based on TextField and TextField can have solid color backgrounds. This example has a custom DataGridColumn that allows customization of the background color and value as to when display the colored background.
BackgroundColor Changes When Data Changes
Blink When Data Changes Demo
Blink When Data Changes Source
This example is a variation of the BackgroundColor example where the background color is only shown briefly if the data in the renderer changes.
Text Color and Styles in Item Renderers
Text Styles Demo
Text Styles Source
This example changes the color of the text and makes the text bold based on criteria in a styleFunction that works like labelFunction. By specifying different styleFunctions you can get the color and other font styles to be different based on the data.
HTML in an Item Renderer
HTML Renderer Demo
HTML Renderer Source
I've seen many people use the Text component as a renderer for rendering HTML (the subset of HTML that Flash supports, that is). It turns out that the default DataGridItemRenderer can handle HTML with a few minor tweaks and is lighterweight than Text.
Sub-Object Item Renderers
Sub-Object Demo
Sub-Object Source
The default DataGridColumn only handles properties on the dataProvider items. It doesn't know how to look "deeper" for properties in the items' sub-objects. That's for performance reasons. Normally, we tell you to use labelFunction, which is a fine solution, but this example shows how a custom DataGridColumn and custom item renderer can also take the extra time to look at sub-objects.
Split Columns/Grouped Columns
Split Column Demo
Split Column Source
Several folks want to see a column split in two with a header over the two columns. Again, this can be done via custom DataGridColumns and custom item renderers. This example allows you to specify two custom sub-DataGridColumns that define the renderers for the sub-columns.
Custom Header Renderers (CheckBox)
CheckBox Header Renderer Demo
CheckBox Header Renderer Source
Making custom header renderers is a bit trickier, especially if they are interactive. You might need to disable certain default behavior in the DataGrid. This example shows how to get a CheckBox as the header for the column.
Custom Header Renderers (ComboBox)
ComboBox Header Demo
ComboBox Header Renderer Source
Another classic custom header is a ComboBox that allows you to pick filters for the DataGrid data. This example uses a custom ComboBox that allows specification of separators in the list of items, to mimic the look some people use in Excel. This example dispatches a custom event via the custom DataGridColumn.
List of CheckBoxes
CheckBox List Demo
CheckBox List Source
This doesn't use DataGrid, but I put it here to show one way to do this. It uses an inline item renderer to modify the data provider directly. It is tempting to use rendererIsEditor for this functionality, but it feels better if you handle the change event directly instead of relying on the editable renderer workflow which doesn't update the data provider until after you click out of the renderer.
Name Value Table/Custom Collection
Custom Collection Demo
Custom Collection Source
.
This also doesn't use DataGrid, but is a good example of how to build a custom collection. In theory, a custom collection could insert groupings into the array of email much like Outlook does. Maybe I'll prove that in an example some day, but future releases of Flex should have this functionality built-in, and there are some good versions from third-parties already. I put up this example to get you to consider using custom collections to solve some of your problems
Someday there will be other examples available as well (maybe).. Hope these help.
-Alex

Alex,
Once again I would just like to thank you for all the time your giving the community.
It's one thing to know what you are doing and it's another to get the confidence you know what you are doing by seeing what the engineers are actually doing when 'they' extend the classes that they wrote. :)
I don't think a lot of people on flex coders realize that you are a full time flex framework engineer and you still have time to give all this great advice and help out while still doing a great job programming our futures.
Once again, thanks.
Mike
Mike, we really appreciate all the work you and other community leaders do. Every once in a while my schedule opens up enough for me to keep up with FlexCoders for a bit, but eventually I get buried again have to stop for awhile and I'm glad you guys somehow find the time to consistently be there for others.
-Alex
Thanks a lot for this great blog. It helps to understand the recycling and usage of item renderer components and also made me think about those column renderers...
GREAT JOB!
It looks like there are threading problems with some of the samples:
I'm using the Text Styles sample , but with a bigger list that scrolls.
It works fine, until you start using the scroll wheel, at which point the styles get all mixed up.
I guess I'm a little surprised all the functions like getTextStyles() aren't implemented with parameters (like your styleFunction or labelFunction).
------------
Ha! Good point! I didn't follow my own instructions. The stylesFunction doesn't reset the styles. It should look more like this::
if (value {
o.color = 0xFF0000;
o.bold = false;
o.underline = false;
}
else if (value > 45)
{
o.color = 0x00FF00;
o.bold = true;
o.underline = true;
}
else
{
o.color = 0;
o.bold = false;
o.underline = false;
}
I updated the sample code. I also had to add some code to make sure the styles got fetched when changing the renderers data property.
However, I must note that this isn't a threading issue, simply one of not handling recycling as I mentioned in the blog post. There is no threading in ActionScript.
And FWIW, getTextStyles doesn't take parameters because it is part of the style system, and not a replaceable function like stylesFunction or labelFunction. That's why we override it to call stylesFunction only when you need it. Otherwise you'd pay a performance cost for generality when you don't need it.
-Alex
Hi Alex,
Thanks for these examples. It is nice to see the "recommended" way of doing these things, but I can't help but wonder why information this vital and widely applicable is showing up on an engineer's blog, 9 months after Flex was released, and only because he was lucky enough to have some free time. To me, this is the type of info that should have been featured in DevNet articles or whatever shortly after the launch.
I follow numerous blogs and MXNA pretty vigilantly and I've never seen these approaches discussed or even mentioned. Anywhere. That seems extremely unfortunate, especially if the approaches people have come up with really do suffer from performance issues as much as you think they might. I think that could potentially reflect very poorly on the platform as a whole, when in fact it is just caused by developers not knowing any better.
All gripes aside though, I look forward to examining these examples closer in the coming days. One initial question is how do we know when to use validateNow() versus validateProperties(), etc.? I was either somewhat or completely unaware of most of the validation and other methods you used to commit changes.
Thanks,
Ben
---------------
Ben,
I would have done this sooner if I had time, but we went from 2.0 to 2.0.1 to two separate hotfixes. If it hadn't been for the fact that my 3.0 feature schedule got pushed off to a different milestone, I wouldn't have gotten around to this at all.
I'd been monitoring flexcomponents, but not flexcoders due to volume of emails and it was only because I had enough time to get back on flexcoders that I saw this trend. I had figured folks had figured this stuff out because we shipped the source code, but apparently it was too deeply buried, and I don't remember these kinds of questions on flexcomponents.
So I started a blog and blogged. DevNet takes too much time so I think I'll just keep updating the blog unless you think I should really formalize this stuff.
Anyway, sorry it was late in coming.
As for your question on validateNow/validateProperties. The answer is to never call them unless you need to. Because DGItemRenderer is derived from UITextField is has different behavior than UIComponent, so validateProperties is the equivalent of commitProperties. And validateNow() forces validation in the same frame which is expensive unless you are the leaf node of the display tree.
Thanks for using Flex and helping out on the lists. We really appreciate your time and feedback.
-Alex
Hi alex, thanks for these examples. In regards to your checkbox in the datagrid header, I really wish you took this to the next level. A very common use case is to allow a user to select all rows via checkbox (as you've shown), and to allow individual selection of rows. Once selected, allow the user to delete the selected rows. I've been trying to solve this for too long, and would greatly appreciate a write up, and demo.
Thanks
------------
Jeff, for spam control, your comments aren't posted until I "approve" them and I was out all day.
Anyway, your scenario is interesting, not sure how soon i can get to it. You might post it on FlexCoders and see if someone else can figure it out sooner.
In general, the principle should merge the checkbox list example with the checkbox header example. The checkbox list example shows that you can/should manage the selected state as a field in the dataprovider.
-Alex
Hi Alex, thanks for the examples, can't have enough of them!
I found a small bug that I thought was worth reporting because I think people eventually want to use this feature of the DataGrid as well. So, in the "Split Columns/Grouped Columns" example, when you click the header to sort the column it throws an error, something about not being able to find the 'history' column or property..
Cheers
--------
Thanks for the heads up. I'll take a look at if I get the chance. I expect that you can steal the code from CheckBoxHeader that turns off the sorting.
Jeff, I wrote a post about that scenario a while back at http://www.returnundefined.com/2006/11/creating-truly-reusable-renderers-with-classfactory/. It doesn't include code to delete the items, and uses a different approach than the one Alex demonstrated here, but it should get you pretty close to your goal. To delete the items you'd just want to iterate over your dataProvider and remove any that had the property your checkbox sets.
Alex, I would be interested to get your opinion on the approach I took. It varies significantly from your approach, but still seems valid because itemRenderers seem to be the main purpose of using ClassFactory. Am I wrong on this? Should the strategy I used be avoided?
Thanks,
Ben
------------
Hmm... I looked at your example quickly so I might have missed something..
ClassFactory is used in many places like Charts and some of our other components. It provides another level of indirection over specifying a class to use as a "plug-in" of sorts. Any time I want to abstract the viewer from the thing data views, I will likely use IFactory, but you don't have to use ClassFactory, sometimes you'll want to make your own IFactory implementation.
It looks like you tried to do that in your HeaderRenderer, but I think it isn't getting used if you assign it via ClassFactory. I'd think you could remove implement= and newInstance() and things like that.
However, the basic approach is fine. I think mine is better mainly because I wrote it, but also because custom headers allows strong typing of the extra properties that you need. It's pretty easy to have a typo in a {} object declaration. Second, a custom column would require one less external variable to retain the selected state of the checkbox.
To be picky, I still wouldn't use an HBox as the outer, it is pretty heavy, and I wouldn't use binding, it is also heavy. I'd just listen to the appropriate events and set properties as necessary. I think your bindings may cause memory leaks if you end up trying to dump the renderers from memory. I don't think I saw an unwatch() call.
-Alex
Hi Alex, sorry for bombarding your comments, but I just went back and looked at the docs. They show/recommend overriding the data setter and/or using ClassFactory as myself and others have been doing, so I'm a bit confused about why you recommend a different approach. Are these simply your preferred way of implementing renderers or does your approach come with advantages? I'm also not sure how your approach could be applied to more stylized renderers like a horizontally centered CheckBox, or a renderer that contains a small animation.
I am really just trying to understand these topics as thoroughly as possible because my current and future Flex work uses renderers very extensively.
Thanks,
Ben
-------------
In the software industry, I'm almost an old fogey. I've been around since DOS and floppy disks, 640Kb and assembly code. Because of that, I'm a code minimalist, and am wiling to take a few extra steps to make things small and fast.
I'm also one of the people on call when a customer has performance or size problems.
So given that, my design bias is toward slightly more sophisticated things that don't follow the recipe nicely but come out optimized for one thing or another, and often don't optimze for development time.
That puts us in a bind. As a new platform we want it to be really easy and fast to develop code and learn how to customize things in Flex. If we make the docs thicker with stuff like my item renderer post, we risk folks saying that Flex is too hard to learn, that there are too many patterns, etc. If we had the time, there'd be an advanced guide, an "Inside Flex" book like "Inside Windows" etc. Good folks like Colin Moock and Chafic Kazoun and others are cranking out great books like this as we speak, but they are also targeting the masses which is what we need to get a beachhead as a platform.
So the best I can do is blog on occasion. The examples in LiveDocs are perfectly fine and were reviewed by me before publishing. They just aren't optimized because they are meant to solve a problem in a cleanly defined pattern that can be repeated in other scenarios. And for most folks, it will take them 10 minutes to center an image by putting it in a Canvas or HBox and 10 hours to figure out how to subclass Image to do the same. That 10 minute solution is critical to proving to their managers that Flex is great, and my hope was, by the time they really need to optimize, it will only take 2 hours since they've learned the other 8 hours of stuff along the way.
Unfortunately, my recent stint on FlexCoders has caused some worry that there's still a big gap for a lot of people between doing things in MXML and doing things in AS. So I tried to close that gap with my blog posts, yet I can see there's still more that is needed. I hope I can find more time to put up more samples.
Because I've got 20+ years of experience and 15+ of object oriented programming, whenever Flex doesn't do something I want, I always find the right base class and start subclassing. Others want to use MXML which is fine if that's your comfort zone, but if you need speed or smaller size, many times you gotta go lower-level. That's hard for many and I hope some of these examples can help out.
Thanks for being a helpful and active member of our community. We really appreciate the support and feedback.
-Alex
Thanks for the detailed responses, Alex. I completely agree that getting people productive quickly is paramount, and seems to be one of the things driving the buzz around Flex. Having that context, I see why articles like these wouldn't have been appropriate at launch time.
I look forward to learning more about optimization and the finer details of how the framework works.
Thanks again,
Ben
Hi Alex..
Thanks a lot for ur examples. I tried out the color change in cells after editing. but am facing a problem that, whenever i use the horizontal scroll bar to edit next column, the colors get messed up. Can u please give a solution for this?
------------
Vyshak,
Well, I'm not quite sure what your scenario is as I don't think I know what you mean by "horizontal scroll bar to edit next column". So you can provide more details if you wish. However, I must make clear that these examples are "unsupported". I'll try to fix things if I have time, but my main job is to develop new features for Flex 3.0. These examples were intended to serve as a starting point for your own solutions. Hopefully you can find the problem yourself, or post your example to FlexCoders and maybe others can help.
-Alex
Hi Alex,
Thanks for ur reply apart from your busy schedule. I made it and now its working fine. Thanks a million again for providing such a wonderful article. it helped me a lot..
Super helpful blog! Thank you thank you.
Can you think of a way to make the CheckBoxHeaderRenderer center horizontally?
-------------
Glad we could help. You should be able to use or borrow from the CenteredWidgets example.
Alex,
Good to see you blogging.
Indeed, very interesting post. Not many people know about different patterns (algorithms/design) used in Flex framework. It really helps to come up with best-practices, when you (an Architect of Flex framework) suggests recommended ways and also explains things (design, decisions etc).
Thanks for taking time out and making such posts..
regards
-abdul
Alex,
I am trying to create a datagrid that will change the column headers dynamically throughout my application. I know how to add rows dynamically but how do you create columns dynamically??
Thanks for taking the time to help us who are still learning this great language.
Jon
-----------
Columns are different. Rows are represented by collections like ArrayCollection, but the set of columns is just a plain array and not a collection.
The rules for many array properties in Flex and Flash is to get a copy of the array, change it and set it again. If you just change members of the array, the component probably won't see it as there is no way to watch for changes to array members (well, there is, but it is too much overhead).
So the pattern looks something like this:
// get the current array of columns
var cols:Array = dg.columns;
// create new column
var col:DataGridColumn = new DataGridColumn();
col.dataField = ...
col.headerText = ...
....
// add to end, can use splice or something else
cols.push(col);
// shove the whole modifed array into the datagrid
dg.columns = cols;
Hi alex i've decided to use your list of checkboxes demo to create something similar for a form im using which enables the user to select a list of courses that they can enrol on to. i am using amfphp to retrieve the data into an array collection.
so far i've managed to get the list of courses to show but how do i bind the checkboxes to the data in the array collection?
-----------------
Normally, you set selectedField to the name of the property that represents the checkbox
Thanks for contributing this great blog for those of us who are new, these kinds of advanced Flex tips and suggestions are exactly what many of us need.
I have a question about your design decisions in BlinkWhenChangedRenderer: early in the blog post you mention that ItemRenderers may be recycled across different rows -- but you are saving row-specific state in the BlinkWhenChangedRenderer. Isn't it possible for #validateNow() to be invoked on a BlinkWhenChangedRenderer for a row when that renderer's "lastUID" ivar is set to the lastUID of a different row?
----------------
Yes, it is possible so the code doesn't blink in that case (of course there could be a bug
Thanks for the information that you've been posting -- it's really helped me a lot. I do have a problem though with the "Text Color and Styles in Item Renderers" example and I'm wondering if you might know how to solve it.
I need to change the text style in one column whenever an item renderer in another column updates the icon that is displayed in that column.
I've implemented the code for the "Text Color and Styles in Item Renderers" example but the text style only appears to be visually applied when the next "change" event occurs.
For example, when I click in a row and a DataGrid "change" event is dispatched a function is called that changes a dataField value resulting in an icon being updated in a column. This works fine. However, in my text column when the ComputedStylesRenderer calls the stylesFunction and the stylesFunction returns an object with the new style based on what is being displayed in the icon column, the text in the ComputedStylesColumn does not change until another row in the DataGrid is selected.
I'd like to change the style for the text in the ComputedStylesColumn at the same time that the icon column is updated so that they are in sync.
Is there some way to force the text in the ComputedStylesColumn to be drawn with the new style as soon as stylesFunction returns the new style information?
Thanks for any ideas!
------------------
In theory, a call to invalidateDisplayLIst should shake things up and cause a redraw.
>> In theory, a call to invalidateDisplayLIst should shake things up and cause a redraw.
Originally I tried calling invalidateDisplayList from a number of places (including in the ComputedStylesRenderer) but the updated text style is not displayed until a new row is selected in the DataGrid. I also tried updating the data in the cell to see if that would force the style to be applied, but that didn't work either.
It looks to me like it is not possible to dynamically change the text style using the ComputedStylesRenderer technique (a different DataGrid row must be selected before the style is shown). Of course it could be that I just haven't looked under the right rock yet :-)
-----------------
You might need to call validateNow on the renderer instead. We're in a busy period right now, but maybe I'll get a chance to look in a couple of weeks. If you have a simple test case, zip it, rename it so our filter doesn't catch it, and email it to me
Hi Alex,
Thanks for all the stuff you have been posting. Your Split Columns/Grouped Columns example is something I was looking for for a long time.
I was playing around with custom item renderers and item editors editors and noticed that if I use a custom item renderer the DataGridEvent.reason is not set properly on the itemEditEnd event. Could you shed some light on that?
For example I have a datagrid with 2 columns A & B. Column B has a custom renderer. If I try to handle the itemEditEnd event when the user finishes editing column A by clicking on column B then the event.reason that is set on the DataGridEvent is DataGridEventReason.OTHER instead of DataGridEventReason.NEW_COLUMN
as expected.
-------------------------
Maybe the .editable field isn't set right? I won't have time to look into this for a while, but you can send me a test case if you want.
Hi Alex, thanks a lot for your great examples. I've got a question for the SplitColumn example. If you try to sort it (as Jeff has spotted) it doesn't know how to sort on "history". Your suggestion was to use the CheckBoxHeader example but that turns the sorting off completely. How would I be able to sort the rows by selecting the by "High" or "Low" child header? Any help with this would really be great! Thanks!
------------------
We're in a busy period right now so I can't actually take the time to work on this, but I would get the HEADER_RELEASE event, call preventDefault() and then sort based on the values of xmouse and ymouse. Good luck.
Hi Alex,
thanks for your great demo. I tried to bind a link to a column header for the datagrid. it would open a new window of the link. Do you have any idea about it?
Thank you!
---------------------
Should be possible. If you use LinkButton instead of CheckBox in the CheckBoxHeader and call navigateToURL, it should do what you want.
I have a DataGrid with editable columns. If the user enters a value that is too high, I would like the cell to behave similarly to the way other controls behave when you set the errorString property to an error message. I tried making an item renderer that extends TextInput, and it works, but when you tab out of cells the itemEditorItemEditBeginHandler function in DataGrid.as blows up because the _editedItemPosition is null.
Any advice?
----------------------
The model we have for that is that you validate the input on ITEM_EDIT_END and call preventDefault() if the data isn't valid. You can additionally tell the renderer that the data is bad so it can display itself in some other way.
I haven't seen the issue with _editedItemPosition being null although the latest hotfix has one additional protection against that.
Feel free to post a mini-example on FlexCoders.
Hi Alex, thanks so much for all your posts so far. I discovered your blog earlier today and have not stopped reading since.
This one is particularly interesting to me. I've been using event-bubbling to capture events from custom item renderers until now, but I'll certainly re-evaluate my approach to both dispatching events and building custom renderers after reading this.
a small request ... would you consider enabling your future flash examples with the 'view-source' option enabled? If you just need to glance over the code to get the gist it's so much easier than having to d/l, unzip and load up in some text viewer.
Cheers again,
Neil
----------
I'll look into it.
Hi Alex, great info thanks. One small thing that's puzzling me is this - when you mention event dispatching from a custom renderer you use this code:
var event:Event = new ListEvent("myCustomEventName");
event.itemRenderer = this;
owner.dispatchEvent(event);
ListEvent doesn't appear to be dynamic or specify an "itemRenderer" property so I get a compiler error. Could you clarify what to do here? Thanks
-----------------
mx.events.ListEvent does have a itemRenderer property
Alex-
Great article.. it helped out a bunch. I have a custom renderer that I'm creating with a ClassFactory and it is working great but I can't figure out how to delete everything from memory once I'm finished with it.. I removed everything from the list and set the dataProvider to null but it still lives in memory.. any ideas?
Thanks,
Peter
------------------------
The new beta has a memory profiler that can help you track this down. Typically though, you have to make sure listeners are removed as well as other references.
Thanks for the articles! I'm a newbie with flex, just wondering if you can help me. I want to get some information from a web service and use that information to create URL links, the web service returns the label and the URL. Need to open the link when user clicks on it. I was thinking of using a one column datagrid, I thought initially that this is the best way to go - but now I'm finding it very difficult to do. How would you do this??
-----------------
Probably many ways to do this. Look at the Repeater examples. You could use Text components or LinkButtons in the Repeater.
DataGrid would work, but may not be the UI you want.
In "Split Columns/Grouped Columns", how should I make multiple columns instead of just giving left and right columns?
----------------------
In the same way I split into two columns, you can certainly split into three or more.
These examples are wonderful, the certainly address many issues that seem to be almost universal throughout the flex/as community. Thanks again, Alex.
Just like JK, I am also trying to split columns into more than 2(left and right). But I was wondering how you would do it dynamically with a value determined by user or at run time? I am still very new to flex and any sort of coding example would be much appreciated.
-----------------
I don't have time to put together code right now. Basically, I would change the leftColumn/rightColumn in the custom Column to be an array. The column header and renderers would go through the array and create headers and renderers for each column in the array. You would specify the column in the main app just like you do for the column set in the main datagrid.
If you have questions, post to FlexCoders, there are plenty of folks there who can help.
Hi Alex thanks for the samples. In split columns, when I try to apply itemRenderer for SplitDataGridChildColumn, it is not getting affected. Any idea to overcome will help me.
Thanks.
--------------------
It looks like there is a bug in SplitDataGridItemRenderer. Around line 135 or so, it is using headerRenderer instead of itemRenderer. See if that gets it to work for you.
Hi Alex,
Great stuff here, really helpful. I am trying to do a filtering combobox at the top of a column on a datagrid, just like your example, but I am having trouble using remote data in the combobox and datagrid instead of static arrays within the code. Once I call my HTTPService, I get nothing back unless I change the code from:
paddingTop="0" paddingBottom="0" verticalAlign="middle" >
to:
paddingTop="0" paddingBottom="0" verticalAlign="middle" >
in which case, I get data for the grid but not the combobox, obviously.
Any suggestions?
Thanks!!!
----------------
You want to assign the columns[0].dataProvider (and the dg dataprovider) when the results of the server request come back. You probably have a result="..." handler for your HTTPService.
Hi Again,
Thanks for the tip! You were right, and now I get data in the grid -- but in the ComboBox I just get [object Object]. I added a custom labelFunction there, but my every attempt just results in [object Object] in that combobox.
It seems like the ComboBoxHeaderColumn wants a labelField as well, but even if I add that var to the ComboBoxHeaderColumn function in ComboBoxHeaderColumn.as, I still get the same result. Sorry to bug you with this, but I am stumped. Can you help?
Hi Yet Again,
Great news: I figured it out. I had to add the following:
in ComboBoxHeaderColumn.as:
public var comboBoxLabelField:String;
in dg.mxml:
dg1.columns[0].comboBoxLabelField= "myDBvalue";
and in ComboBoxHeaderRenderer.as, within the override public function set data(value:Object):void:
labelField = _data.comboBoxLabelField;
Now I have the labelField for the ComboBox and the dataField for the DataGridColumn in one element.
Sorry for the extra posts, but I thought I ought to share my findings!
This does bring to mind a question: is it possible to sort a column by clicking on the ComboBox at the top of that column, and then open the ComboBox and sort the grid by selecting a value from the ComboBox drop-down? If you know, please share. If not, I'm gonna try it anyway and see how it goes.
Thanks again for the great blog.
--------------
You should be able to customize sorts and filters based on the ComboBoxHeader
OK, sorry to bug you again, but I have hit a wall with trying to get a ComboBox to both filter and sort.
I like the way the PopUpMenuButton offers the ability to fire off one event when you click the button, and drops down a menu only if you click the arrow at the right. Is there any way to modify the ComboBox (or ComboBoxHeaderRenderer in this case) to emulate this behavior? I'd love to have the ComboBoxHeaderRenderer sort its column when clicked to the left of the arrow, and drop down a menu when the arrow is clicked that has a list of items which filter the datagrid when clicked (which I am already doing with the drop-down items, I just can't separate the arrow from the rest of the button).
Any suggestions you can offer would be greatly appreciated!
--------------------------
You might try putting a PopUpMenuButton next to a Label or DataGridItemRenderer in the header
Hi Alex,
Is there anything which can display the complete HTML contents in Flex along with images and all.
-----------------
Not in the web player. Apollo/AIR will have an HTML component. Also google HTMLComponent as some folks use a floating IFrame over their Flex app.
Hi Alex,
Thank you for posting these great examples. I've implemented the Background Color Renderer and the Html Renderer and made a few modifications to suit my live data application. All is working perfectly.
I just have one question, is it possible to show a hand cursor when mousing over data in the datagrid? I can achieve this with an inline mxml itemrenderer but it would be a lot more efficient if I could achieve it using a custom renderer.
Thanks in Advance,
Karl
--------------
I'd check out buttonMode.
Hi Alex,
Thanks for your response. Which component would you recommend to use as a renderer that has both backgroundcolor and buttonmode properties? It can be achieved by using a canvas and text but I was hoping for a more lightweight solution.
Your suggestions would be much appreciated.
Thanks,
Karl
---------------
I would use UICompnent to wrap the DataGridItemRenderer.
Hi,
Great examples but the one with a headerrenderer with checkbox throws a RTE when clicking the header. I'm on Moxie M2, maybe thats why, since it seems to be working in your demo.
//Morgan
-------------------
These examples are not guaranteed in all scenarios. I'll have to remember to update them when Moxie ships
Hi Alex,
I spent 4 days trying to optimize the scrolling speed issue in my DG and finally you saved my life. I am now using a mix of your BackgroundColor and TextColor renderers you have posted. The display response is now amazing.
Now I am trying to include a graphic property in order to be able to draw either a rectangle filled with gradient or a circle. Unfortunately I can't figure it out.
UpdateDisplayList do not work with DatagridItemRenderer and as far as I understood the it reacts as a Textfield. Even if I am using CSS styles I can not implement backgroundImage or backgroundGradientColors.
Would you have any tips? How could I extend that renderer to use graphics?
Many thanks.
Regards, Rudolf.
--------------
The most lightweight think you could do is subclass Sprite, implement IListItemRenderer (and maybe IDropInListItemRenderer) and draw your graphic in there.
The fastest thing to do might be to take a Label, leave the text blank and draw the graphic in the .graphics layer.
Alex,
Thanks for the blog, I've found it very useful.
I extended Split Column example to support multiple columns (more then two) and published code at: http://blog.widget-labs.com/2007/09/07/split-column-datagrid/
(I noticed several other people asked about multiple column split)
------------
THanks for helping out.
Hi Alex,
I have a question, is it possible to hide/show left or right SplitDataGridChildColumn?
When I set visible property to false of SplitDataGridChildColumn, it remains visible... Could you help me?
Thanks,
Pietro
--------------------
Not in my example, but I'm sure it is possible to modify the example to do so. I don't have time to help you out right now. You might be better just hiding the single versions of the columns and showing them when you hide the split column
hi, has noted before, the event type should be ListEvent in order to be able to set it the itemRenderer property, you should correct this in your post, thanx
var event:ListEvent = new ListEvent("myCustomEventName");
-----------------------
so noted.
Dear Alex,
Thank you for your article. I consider it very useful.
In your Sub-Object Demo example you showed me another solution to the issue of indicating to DataGridItemRenderer which sub-object to display. My purpose is to create efficient way to render columns (create pivot table) containing information about quantity of product (each product listed in separate row) to be delivered(or not) in certain delivery (list of unique deliveries list in ascending arrival date order).
The pattern for adding columns is obvious for me. It worked with container based DataGridItemRenderer that implemented “mx.controls.listClasses.IDropInListItemRenderer, mx.core.IFactory”.
But as you wrote - container are heavy.
In your example you set deepDataField and itemRenderer in the .
In a modified version instead of hard written code for the column I have function that adds given number of columns. The problem is that “col.itemRenderer =” part raises in the Flex Builder “Implicit coercion of type DeepDataGridItemRenderer to an unrelated type mx.core:IFactory”.
Is that correct? or What should be tweaked to make this addColumn function work with the your example action script code?
public function addColumns(cols_no:Number):void
{
var cols:Array = dg1.columns;
var i:int;
for (i=0; i var col:DeepDataGridColumn = new DeepDataGridColumn();
col.headerText = 'D'+ i;
col.dataField = "deliveries";
col.deepDataField = "deliveries.D"+i;
col.itemRenderer = new DeepDataGridItemRenderer();
cols.push(col);
}
dg1.columns = cols;
}
Best regards,
Greg
------------------------
MXML compiler autogenerates some code and turns:
itemRenderer="DeepDataGridItemRenderer"
into
itemRenderer = new ClassFactory(DeepDataGridItemRenderer)
The -keep option in MXML will reveal most of this code-gen.
I have a datagrid which has a certain number of rows.
Selecting a row should bolden the text in that row.On selecting any other row, previously selected row text should get unboldened.
In flex 1.5 it was easily achievable by handling this situation in setValue() but in Flex2.0 im totally confused on how to go about.Please help?
----------------
The same way I changed colors in the examples, should allow you to change to bold
Hi
grate info on DataGrid renderes. Thanks.
I wonder how I can use sorting when ther is an custom renderer in the heder of DataGrid?
---------
You would display your own sort arrow and/or provide sorting ui in the renderer. For example, one of the combobox entires would be "alphabetical"
Hi Alex,
Thanks for your great examples!.
I use your ComboBoxHeader with few modifications. Everything works well but my concern is about memory usage. When I run the profiler on my application it shows me multiple instances of ComboBoxHeaderRenderer and the garbage collector never remove them from memory. I try your sample and it shows me 4 instances only at initialization.
Why? Is there any way to delete those instances? Even when my datagrid is removed by the popUpManager the memory is not released.
Thanks
--------------
Are you saying my example leaks, or just yours?
Hi Alex, I'm trying to use the text styles and color and it works but I have a question. If I wanted to have a separate button that modified the price of a particular item in my array, the datagrid doesn't seem to take the color that would reflect the new price. I've tried to use validateNow() on the datagrid with no luck. Do you know of a way that this can be done? Thanks.
---------------
call invalidateList() on the dataGrid
Hi,
I am new to flex and trying to understand the inner working on DataItemRenderer(s) and DataGrids. I went through the Flex Framework code. But even then I couldn't find answers to some of the questions. Like why _listData property could be null and when we have _data property not avalable but _listData property available. Basically the difference between _listData and _data is not very clear to me. Any pointers would be of great help
------------------
data is the item in the dataProvider that the renderer should display. It can be null if there is no data or there are null items in the dataprovider.
listData is a data structure that describes more information about the data and the list class such as its UID, what itemToLabel returned and for DataGrids infomrmation about the column that the renderer is in.
Hi,
Just getting into itemRenderers with Flex (v3 beta 3) and finding some odd behavior with a scrolling tile grid that has an itemRenderer set, though it does make sense within the context of the discussion of recycling.
My renderer has a text field and an image. When I scroll the TileList and then scroll back to the previous position, the items seem to be overlapped - the text gets all munged together from what was there previously. Not doing anything special in my renderer, do I need to be?
Thanks
----------------------
Sounds like you might be making new children in the renderer instead of reusing old ones or destroying the old ones? This is a better discussion for FlexCoders.
hi Alex,
Thanks for your blink example. It helped us a bunch on one of our projects. I have a question though. I have been able to use the blink on a particular cell coz we are using Item Renderer for a cell here, but can we do the same for an entire row. I want the entire row to blink and not just one cell. Please let me know if this is achieveable. If yes, then how do we do it.
Thanks in advance !
Cheers !!
------------
You could blink all cells on a row, or you can add make a more complex renderer that can draw outside its boundaries. It might be easier just to blink all cells in a row.
Hi,
Thanks for the great post. I am worling on a Grid in which I have to provide the custom sorting. I am able to do that by using header_release event and by calling the event.preventDefault(). Now the issue is since I am using the event.preventDefault(), placeSortArrow() method of DataGrid is not being called and I can not call it since this is a private method. So I am not seeing any sortArrow in my columns. Any pointers regarding this will be of great help.
--------------
I would use a custom header renderer that had its own way of displaying the sort. The DataGrid will show the sort arrow if it sees a single SortField in the sort so your sort is more complex and may need a different UI anyway
Let's say you have a function in your main application file you want to reference. How do you reference it from within your itemRenderer component. Everything I try results in a 1069 error.
ReferenceError: Error #1069: Property myFunction not found on myApplication and there is no default value.
-------------------
Depends on how you wrote it. If it is an inline renderer (with mx:Component) then use outerDocument.myFunction(). If it is in a separate MXML file, use parentDocument.myFunction(), and if it is an AS file, use owner.document.myFunction().
In my last question I asked how to access a function defined in the main application from within my itemRenderer component. Well, it turns out that unless the function (in the main application) is public it will not find it, thus creating the error.
Here is the item renderer:
(mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" horizontalAlign="center")
(mx:Script)
(;
}
]])
(/mx:Script)
(mx:Button label="Edit" click="{handleClick(event)}"/)
(/mx:HBox)
Hi, I'm a newbie in flex. How can you make a linkbutton functioning like a Vscrollbar. I mean two linkbuttons. 1 for scrolling up and 1 for scrolling down and vice versa. And when I click and hold the up linkbutton it must scroll continuously. Because as I'm doing a work around for this i cannot do the scroll when i click and hold the linkbutton. you must click it again and again to continue scroll. thanks in advance.
----------------------
set autoRepeat=true on the LinkButton and listen for buttonDown instead of click.
Hi Alex
Great information. Does the datagrid allow you to simply enter data starting with a empty grid and then dropping down to next row after entering data on the line above and continuing entering rows of data?
---------------
You can do that, but it isn't built in. Check FlexCoders or search the internet for an example
Hi,
Alex, thanks for all your help. I have one more question regarding the performance of DataGridItemRenderer.
I have a datagrid with 6 columns and one of the column ( column number 5) can have a value as "Unallocated" .
When this value is "Unallocated" I have to change it to "Unallocated [u]Allocate To Team[/u]"
This "Allocate To Team" should be be a link and the whole text "Unallocated Allocate To Team" should be part of a single cell.
To solve this issue, I wrote a custom renderer which extends from HBOx and has two label fields - one label for 'Unallocated' text and the other one for 'Allocate To Team' link text. ( Users should be able to click on 'Allocate To Team' but not on 'Unallocated' text). A pop-up will appear in my application when the users will click on 'Allocate To Team' link.
This works fine but is very-very poor in performance. So I was thinking about extending from DataGridItemRenderer as you have mentioned in your previous posts.
So I am setting the htmltext property using the following code --
htmlText = cellValue + " Allocate To Team";
I can see this text as link in the DataGrid cell. But when I click on this link, nothing happens. Any pointers regarding this will be of great help.
-------------------
You probably have to set selectable=true on the subclass
Hi,
Thanks for the tip. setting 'selectable = true' worked for me. Thanks, I have one more question regarding rendering.
let's say in the DataGrid, I have two columns EmployeeName and Department. Now let's assume EmployeeName is 'Nikhil' and 'Nikhil' is in two departments 'Department1' and 'Department2'.
I have this requirement that if in a grid we have two rows with similar values, for example row 1 has 'Nikhil','Department1' and row 2 has 'Nikhil', 'Department2'. Now if these two rows comes in the grid one after the other, then in the second row we should not display the employee-name and should just display the department. Basically we are trying to group the data on employee names. So the data should be displayed like
Nikhil,Department1
------,Department2
Rikhil,Department1
But if these two rows doesn't come one after the other, if the users does a sort on say Department then these two rows might not come one after the other. If this happens then I have to display the complete information.The data could be like this.
Nikhil,Department1
Rikhil,Department1
Nikhil,Department2
So if I am rendering some row, I should know the data in the row above this row. But as you mentioned in your posts that the rendering happens in the random order. Is there a way to solve the above mentioned issue. To force rendering in a pre-defined order or in some other way.
-------------
Yes, if your data is in an Array. It'll work for XML as well, but it is a bit slower. You need to find a way to compute the index of the item the renderer is displaying. One way is to use the listData.rowIndex + owner.verticalScrollPosition. Then get the previous item from the collection and check its values.
Alex,
Thanks for the amazing blog!
I had a question about checkbox itemrenderers. In my application, I basically want to use checkboxes as row selection indicators - they're not fed by data. What is the best way to handle this? Some options I see are -
a)Trigger row selected on a checkbox select. This way the checkbox selection is always tied into the grid's selectedItems.
b)Store row indices on checkbox select. and write a method, say getCheckedItems to return this array of indices.
Which route would you recommend or are there better alternatives?
Thanks!
-------------
I haven't cooked up an example for that, but it is a common request. Google around and see if you can find a working example.
Last time I thought about it, I would change the selectedIndices of the List as the checkboxes got checked.
Hi Alex,
I need to how to show a hand cursor when mousing over data in the datagrid.Help me to find out solution for that.
---------------
useHandCursor=true
Hi Alex, first off all I have to Thank you gays for the solution on this itemrendere, Flex 1,5 was a pain in the a..!
I Have a question for you, I would like to subclass the datagrid to make it dispatch when the user clikc's on a row that have no data at all, exsample I have a datagrid that have a dp.lengt == 4. and the rowCoundt == 10, I want to know if the user clikc's on the six last rows. Can you point me the rigth direction ?
By the way I realy admire your work :)
Cato
---------------------
Alex responds:
I think you'll get mouseDown events in the dead area and if mouseEventToItemRenderer is null and event.target is ListBaseContentHolder you know you're in the dead area.
Hi,
Alex thanks for your help. I am able to solve two issues in my grid with your help.
This time I have a question about itemEditors ( I am not sure who else to ask this question). In my page, I have two grids top and bottom grid. Now If the user clicks on any row in the top grid, I have to display the corresponding items in the bottom grid.
One of the columns in the top grid is editable. Now the problem is if the user clicks on this column, the item editor should open but that doesn't happen and the user has to click one more time on the same cell to open item editor. I tried to debug the application and found out the following issue.
As soon as the user clicks on the editable cell, the item editor opens. But since I rebuild the bottom grid as soon as the selection is changed in the top grid. So probably the focus moves from the top grid to the bottom grid and the item editor instance is destroyed. If the user again clicks on the same cell, the selection is not changed and the bottom grid is not re-created. So the foucs doesn't move and we can see the itemeditor.
The user wants to see the itemEditor in a single click and not on two clicks. Is there a way to do this?
--------------
Alex responds:
Unless you are calling setFocus on the bottom grid, focus should remain on the top grid that got clicked on. I would try to find out why focus is changing. Or is it because focus was already in the bottom grid and it tried to retain the focus?
In theory, there should be enough FocusEvents being dispatched to determine that you've lost focus to the other grid and a call to setFocus on the topgrid and maybe setting editedItemPosition might fix it.
Hi Alex:
Thanks so much for posting this invaluable information. Like others, I am also battling performance problems with a large datagrid.
My question is: How can I extend the MultiLineHTML example to insert an html link into the text cell (i.e: adobe), then traverse to it when selected?
Thanks,
Tr
--------------------
Alex responds:
In theory, you should be able to add that to text cell and it should just work. If you have problems, try it with a default cell and a single-line link, then post to FlexCoders if you have problems
Hi Alex
Thanks for the article, since we are scratching our head, why the application is taking so much of memory some times event the computer get crashed , or its showing the system a lot.
Now I figured out that because of the MXML based Itemrendere we are using causes this crash.
The application we are developing has a custom tilelist component, which loads a mxml heavy itemrenderer which is used to display the powerpoint slides(ranges from 60 to 120) jpg images, there are rules to be applied so lots of drawing api code is used to draw lines, and we are selecting the itemrenderers in different combinations like if u select one item and if it belongs to a family of bundles say 8 all are getting selected, for highlighting the selection we will be drawing 8 yellow rectangles, and other 2 type of complicated bundle rules.
As per our requirement we increase the size of the tilelist component, so that it does not unload the items which is not visible, we are manipulating the parent of the tilelist the canvas to display scrollbar for scrolling the tilelist component itself. So say if the tilelist has 50 items , all the 50 items are always in memory.
When I used profile to see whats happening, each itemrenderers, has more then 200 items it. , initially the application was developed using flex 2.0, then 3 days after reading some blogs we ported to flex 3.0 to see any improvement but nothing much.
I don’t know why adobe did not handled this kind of a big problem, its not removing the old items, don’t know from where its get created
actually in design time the itemrender has 8 image component to display 7 thumb nail images according to the rules set for each itemrender in runtime, 3 canvas , 4 hbox and 1 vbox and 3 spacers for alignments.
I taken ur advice to convert it into actionscript class, I like to have ur advice so that, whenever each itemrenderer is loaded into the tilelist component the Page File usage of the windows will not rice my 10 md which never reduce and on each drag and drop the Page File usage of the windows should not increase 15 to 20 mb,even on every action CPU usage should not touch 100%.
Please suggest me how to go about creating custom actionscript based Itemrenderer which does not take more memory.
Thanks
Thiru
---------------------
Alex Responds:
The Flex 3 Profiler should help you see where your memory is going. It sounds like you're loading a lot of bitmaps, and will be expensive. Fetching bitmaps that are higher resolution than the screen is wasteful. If you can generate lower resolution bitmaps on the server, that might be a good thing to do. Our friends at Scene7 have made a business out of it.
I was having trouble getting my custom itemRenderers to work on the children (I'm operating off the version from widget-labs which supports an X number of children).
Basically, when it assigned the data to the existing child renderer, it was using the parents data field instead of the childs. I changed this:
childRenderer.data = data[column.dataField];
To this:
childRenderer.data = data[childColumn.dataField];
And that seemed to fix it.
Hi,
I have a datagrid in which I have to display some text. This text will be in some cells and the other cells will be blank. Now this text is long like "planned milestone achieved".
The requirement is to keep all the cells of fixed size and this text should overlap over the adjacant right cells.
Let's say that cell of column number X and row number Y is represented as cell(X,Y)
The requiremnt is that the text in cell (1,1) (Ist column of 1st row) can extend on cell(2,1) and cell(3,1)...The cell(1,1) should not expand.
Is this possible?
-----------------------
Alex responds:
Possible, but tricky. You should see if the AdvancedDataGrid has the kind of columnspan support you want. If it doesn't, the fact is that all cells are children of the same parent and you can change their z-order and width after the DataGrid lays out the cells.
hi Alex and everybody
thank you all of you because everything post here.I've just finished my project 'Smart Stock Client' using Flex and item renderer of Alex.There is a link to my website http://210.86.239.213/SmartStock/SmartStockClient.html,please check and feedback to me at tungh2@gmail.com.Thanks again.
Hey Alex,
You responded to a post ( Posted by: Nikhil | January 30, 2008 02:56 AM ), question being how to target a function in the main application from the itemRenderer.
I have a similar situation, but I need to target a function in the component itself ( the component is a tree component ), from the itemRenderer, which is an AS file. I can't seem to target functions from the component I'm in. Do I have to go all the way out to the main application and back in through a reference to the component, or is there a direct way I can see stuff in that component?
--------------------------
Alex responds:
After commitProperties, the owner property should be referencing the tree
Alex, thanks for all the postings here. I have a question regarding scrolling. I used a custome list item renderer that has variable rowHeights. When I scroll up and down the list, data displayed is messed up as I can see old data value still overlapping with the new data. How can I solve this problem? Thanks for your help.
---------------------
Alex responds:
That still sounds like you're having recycling issues. Make sure that the component fully validates in one pass. If you're loading external images, that will be a problem since the load won't finish within the validation pass. Some folks use SuperImage from quietlyscheming.com to get around that, but there's lots of other ways you can end up with a two-pass validation so I'd check for that first. Adding traces to updateComplete will tell you how often they get called.
Hey alex,
You wont believe how much frustrating itemrenderers have been for me lately. But your post clarified all the questions/funny situations I have been through. I found your post a lil late but anyways its still not that late..
Your writeup is simple excellent and will tune to it more often now.
The next thing I am going to do is to find out other adobe's flex engineer's blogs. No one can beat those details man!!!
Thanks once again man!
Hi,
I need to add a combo box to one of the column in Advanced Data Grid &
populate it with some data from a data source.
When an item is selected from the combo box I need to send a HTTP
request, but using a value in another column of the same advanced data
grid.
I have used a itemRenderer and added a hbox & combo box in it. But I
am not able to read the value of another column. Can you please help me
and let me know how would I read the value in another column?
Thanks in advance.
---------------
Alex responds:
Please ask on FlexCoders Yahoo Group
hey?
how can i have two link button in single column throuh item render?
please help me
---------------
Alex responds:
You might be better off asking on FlexCoders.
Alex,
RE: Sub-Object Item Renderers
Can you please let us know how to extend ComboBox/CheckBox editors if the objects are nested ?
Thank you
prahari
----------------------
Alex responds:
Probably have to subclass and override the data setters and maybe commitProperties
Hi Alex,
Thanks for the examples!
Combo Box Header Renderer works well, but there is something fishy happening behind the scenes - I have noticed that ComboBoxHeaderRenderer class gets created twice at startup and than, as you use the combo, new instances are being created... in a little while I ended up with over 30 instances of ComboBoxHeaderRenderer in your example (running Profiler in Flex Builder 3). Garbage Collection doesn't get rid of them.
Why is the DataGrid not reusing a single instance?
I noticed this when I put a listener in the header... I can work around that, but it is bit scary to have so many header instances flying around...
Take care!
----------------------------
Alex responds:
Header renderers get recycled just like other renderers. Probably more often than necessary though. If they are not getting GC'd then there's a bug somewhere that needs fixing. The profiler will show who is holding onto those renderers.
Hi Alex,
Thanks for the examples!
Thanks for the examples!
Thanks for the examples!
:)
one question, in my case... i have a String "123,3$ {^P}" like data in datacolumn and the String must be renderizer like a text = 123,3$ + image = ^P is up green arrow.
¿is it posible?
In my case i was trying do the next:
public class LabelImageRenderer extends DataGridItemRenderer
...
but DataGridItemRenderer has only text or htmlText
and i need aggregate a image.
how can i extend DataGridItemRenderer to add image?
i was trying create a component DataGridItemRenderer adding
but this adds can not be watching in the item render.
¿any idea?
have i to change my idea to solve?
Alex ...
Many thanks. I'm using your datagrid technique to render a master/detail view by means of a list with a custom renderer which is itself inline-rendered in a column, e.g.:
borderThickness="0" targetField="endDate" nOffers="{data.NOfferPeriods}"/>
The list contains dates, 1..n dates per datatable row.
All goes well until it's time to set the depth of the visible list. The renderer, below, successfully receives the list depth from the custom tag, and sets it on its parent, however the visible result is that the first row's list depth is carried over to all other lists in all other rows.
I'm trying to stay stateless per your suggestion, but must be missing something. Can you offer any guidance, or alternative approaches?
The relevant section of the list renderer is:
override public function validateProperties():void
{
if (!listData)
{
return super.validateProperties();
}
var ukDisplayDateFmt:DateFormatter=new DateFormatter();
ukDisplayDateFmt.formatString="DD/MM/YYYY";
// Deal with row count in a stateless way
ukDisplayDateFmt.formatString="DD/MM/YYYY";
var listControl:Object = listData.owner as ListBase;
var targetField:String=listControl.targetField;
listData.label=ukDisplayDateFmt.format(data[targetField]);
var n:int = listControl.nOffers;
if (n==0){
listControl.rowCount=1; // ensure space if somehow depth fails
} else {
listControl.rowCount=n;
}
return super.validateProperties();
}
-------------
Alex responds:
Sorry, I'm not sure I understand what you mean by depth. Try posting on FlexCoders. You'll get more folks to help there.
And the answer to the variable depth of the list problem is (duh) that the surrounding datatable must be set with:
variableRowHeight="true"
4 hours to find, 4 seconds to fix. Sigh.
Hi,
I am new to flex and facing some problem.
I have an Advanceddatagrid that act as an itemrenderer that within another datagrid upto 3 levels.
ADG1 -> ADG2 -> ADG3
But the data displayed is not easily readable.
The Problem is Whenever I expand the innergrid I need to change the size of the outergrid row also, So that scrollbar doesn’t appear in the innergrid. I am unable to figure out how to change the size of the outer grid whenever I expand or collapse the inner grid.
Please Help.
------------------
Alex responds:
I'd re-think your UI. Ask ADG questions on Sameer Bhatt's blog
Hi Alex,
I have a small bit of a problem, we are writing a application which has few datagrid (approx 10+) splattered across the application and I was thinking if there a way to set up teh generic renderer which can be used for all these DGs, example i want all the datagrids to show the negative number in RED, however i feel writing the same renderer might not be worth it.
is it possible ?
------------------------
Alex responds:
Not sure I understand. Renderers can certainly be re-used in multiple DGs. Most of the examples in the blog implement IDropInListItemRenderer and can be reused
Hi Alex, I am new to Flex. I am having 3 columns with textinput item renderer in 2 columns and Combobox in the 3rd column.
In the itemEditEnd handler, I have called event.preventDefault() function to prevent the updation of dataprovider. I want this dataprovider to be updated with the new values, on a Button Click.
I am unable to figure out how to achieve this. Please help.
----------------------
Alex responds:
Try asking on FlexCoders. You'll get better response that way.
Alex,
Great blog! Thank you for the excellent examples and explanations. I used your textStyles example to apply a custom style function to a data grid (since I only have the standard version of FlexBuilder, thus no AdvancedDataGrid).
In my case, I wanted to set all of the text in one specific row of the grid to gold, but wanted all other rows to behave according to the css (i.e., white text that turns gray when moused over, orange when selected).
I was able to adapt your computeStyles function to set the text gold or white according to the data value... but that was overriding the css specs for mouseOver and selectedItem styles.
A slight change fixed the problem -- rather than having computeStyles always return a textFormat, it returns null for all rows except my special gold row; I also added a test in ComputedStylesRenderer.getTextStyles, to simply return super.getTextStyles() when styleFunction returns null. Now my datagrid behaves exactly as I wanted it to. Thanks again.
About performance, Thanks.
I use HBox as root tag in my item renderer of tilelist.
And it wastes more than 8 seconds , I'm going to optimize it.
I am trying to implement some sort of Gantt chart with the difference that the cells should display a vertical stack of variable height buttons.
My first naive approach was an itemRenderer with a VBox and a set of dynamically generated buttons. Each cell has a dynamic number of buttons, and each button has a dynamic height. In other words, the rows height is dynamic.
While my VBox/Buttons implementation works for few rows and columns, the performance degraded quickly. I need about 20 rows by 50 columns. The total number of buttons would be in the 200 (many cells have no data to show, while some have a few).
The reason for the buttons is to represent a value (which could be a simple rectangle) and also to provide a place holder for a URL link.
What could I use instead of the VBoxes? and instead of the Buttons?
Thanks,
Thierry
-----------------
Alex responds:
A container like VBox thinks about whether it needs scrollbars, clipping, background colors, borders, etc. If you don't need that, then a simple UIComponent with a custom updateDisplayList that lays stuff out vertically will be much faster
hi Alex,
I have enjoyed reading this blog and it has helped me solve most of my
problems(well, flex that is).
I have an application which displays an
arbitrary number of Datagrids based incoming XML data. the Datagrids are
completely dynamic so are built entirely in actionscript. what i can't
seem to figure out is how to set the datagrid width as a percentage
instead of a pixel value in actionscript. is there a straightforward way
of doing this or do i have to create a subclass of Datagrid with the width
set to 100%?
Thanks for all the great info.
--------------------------
Alex responds:
From actionscript, you set the percentWidth=100 instead of the width property
Alex,
worked great - as long as i set the percentWidth after all the columns are defined. thx. such a quick and easy solution, but i didn't know that percentWidth existed. can you recommend a good book that contains this type of information as well as some of the more esoteric internal workings of flex ?
thx again.
----------------------
Alex responds:
I haven't read most of them, but I reviewed Chafic's book so I guess I gotta recommend it: Programming Flex 3: The Comprehensive Guide to Creating Rich Internet Applications with Adobe Flex
Hi Alex, very cool!!
i've two question
i've a datagrid...how disable user interaction when a row is an empty row?
how can i resize columns width depends on cells content? a very long word cuold be cutt off...i would have an auto resize at the datagrid creation...
thanks
Regards
Lollo
---------------------------
Alex responds:
There's a disabling List Selection post.
Resizing columns to content is going to be slow if you have a lot of rows, but its on my list to show how to do it someday
Looking at any pointers in how to create column filters/show-hide much
like in ExtJS Grid. After reading this (very imformative) blog I'm a little overwhelmed at how complicated this might be to accomplish.
http://extjs.com/deploy/dev/examples/grid-filtering/grid-filter.html
Is there any 3rd party ADG grid component that enhances the out of the
box ADG functionality? Specifically adding some line of business
abstractions like column type (Text/Date/Number) and
filtering/grouping widgets that an end user can use.
Here is how I plan to accomplish some of the features:
- Column Type
-- add a sortCompareFunction based on column meta data
- Arrow icon
-- add Arrow icon to column header that would have handle click event
- Context menu
-- add menu control to support multi panel context menus. This will
require the ability to format menus with checkboxes (never done this)
Thoughts on this approach?
(same msg as on flex coders)
---------------------
Alex responds:
Hopefully someone on FlexCoders will help you
Hi
I am using the code from your example http://blogs.adobe.com/aharui/ComboBoxHeader/dg.swf in my code. But i noticed one thing, that if you open the combo box using [Cltr+down Arrow] then the drop down list is not displayed at proper place. The drop down list is displayed in extreme left though combo box is at extreme right.I was able to reproduce same issue in your code. Can you please give me some pointers so that i can fix this?
Thanks
ilikeflex
-----------------------------
I can't figure out how you got focus to the combo w/o opening it with the mouse. When I do that, the combo shows up where it should.
Hi
Steps to Reproduce-
1. Click on combo box
2. Select any value
3. Data is filtered according to selected value
3. Now open combo box with [Cltr + Down Arrow] Key
Notice: Drop Down List is not displayed at proper place.
Are you able to reproduce now?
Thanks
ilikeflex
-------------------------
Alex responds:
OK, got it. Not sure when I'll have time to look into it
After pulling my hair out trying to get Split Columns to work, I found that AdvancedDataGrid does SplitColumns natively
http://www.adobe.com/livedocs/flex/3/html/help.html?content=advdatagrid_02.html
--------------------------------
Alex responds:
Yes. I did mine before ADG got established.
I've been able to implement a custom Text Color Item Renderer for a datagrid based off of your post. I've added 2 classes, a ComputedStylesColumn and ComputedStylesRenderer and I can successfully implement this in the mxml file, but I was hoping to build my datagrids dynamically with actionscript.
the mxml that works:
Code:
local:ComputedStylesColumn headerText="Price" dataField="price" stylesFunction="computeStyles" itemRenderer="ComputedStylesRenderer" />
I've been able to reconstruct most things in actionscript except for the itemRenderer="ComputedStylesRenderer".
when I try this:
Code:
var custColumn1:ComputedStylesColumn = new ComputedStylesColumn();
custColumn1.dataField = "price";
custColumn1.headerText = "Price";
custColumn1.width = 75;
custColumn1.stylesFunction = computeStyles;
Everything works except:
Code:
custColumn1.itemRenderer = ComputedStylesRenderer();
"Implicit coercion of a value of type ComputedStylesRenderer to an unrelated type mx.c
--------------
Alex responds:
If you use the -keep option in MXMLC you can see what the actionscript equivalent is. In this case it is:
custColumn1.itemRenderer = new ClassFactory(ComputedStylesRenderer);
Hi Alex,
The sample 'HTML in an Item Renderer' was very useful. But my HTML text got some links and these links not working when I click on them.
Please see my HTML text
hello
Could you please advise what would I need to do to make the links working?
Many Thanks
------------------------
Alex responds:
This code and any other code on my blog is unsupported. I would set a breakpoint on Anchor.as:mouseClickHandler and see that is going wrong.
hi alex,
i am trying to implement a datagrid with rows that expand on cliking to show edit and delete buttons on a row basis. do i have to use itemrenderer for this?
thanks
----------------
Alex responds:
I would either use an itemRenderer or float a popup over the row. Depends on what you want it to look like. Changing the width of the DG to show the buttons will be hard. Changing row height is easier.
Hey Alex, thanks for this post (some two years on). So I have a coupla little niggling things to ask about:
I don't know if this is expected behaviour, but when I implemented your very first example (background colour) the text wasn't being rendered although the background colour was appearing just fine. This was due to the embedded font in the stylesheet, which I'd applied to the DataGrid. Without the embedded font (or without the extended DataGridItemRenderer) it works fine.
I can get around this by explicitly stating in the DataGridColumn that fontFamily="Arial". This doesn't strike me as a particularly elegant solution when trying to use stylesheets. :) Have you any tips on what I'm missing?
Secondly, the vertical grid lines are lost when scrolling. These lines go on the left-most pixel in the renderer, beneath the TextField (except for the first column). Previously, when I'd made the DataGridRenderer extend Label it was simple enough to shift it one pixel right, but I can't manage that same feat here. Suggestions?
-----------------
Alex responds:
The "fontFamily" style should inherit so I'd expect the renderer to pick it up unless it got blocked or changed at some other place like on the column.
DataGridItemRenderer is fast because it isn't a container. It can only draw text and no other graphics and can't have children. If you need to draw more than text then you have to use UIComponent or Label.
>>I had figured folks had figured this stuff out because we shipped the source code
I think this perspective is perhaps an influence in why Flex at times is very difficult/time consuming to use.
You as a software engineer is trying to write a component framework and components and have indepth knowledge. The rest of us are trying to use your solution to write solutions for our customers, under time/budget constraints. We use a component framework so we *don't have to* know the details of the source code (at least for routine functionality). Any important details and constraints should be in the products documentation. For every ten hours of documenation you can provide, it probably saves the development community a half million. If adobe wants to see great flex applications penetrate the market faster.. they should keep this in mind.
I am not critizing you personally, this seems to be a trend at adobe in general... they should be allocating you time to contribute material such as this to the documentation team. I for one would appreciate it. You've done a great job here in your blog.
I like flex, it is a great product but I am a bit disappointed at *how complex* some common functionality is to implement and how hard it is to find details to write the solution. The success of this product is not *how great* it is internally or how quickly new releases are pumped out: the success is determined by how well *we other software engineers* can use it.
You might want to put a note in at the top of the "Text Color and Styles in Item Renderers" example that AdvancedDataGridColumn has a styleFunction parameter. I started going down the path of using your code before I realized it had been integrated into ADG.
Of course, there might be some other stuff you have implemented in ADG or even in DataGrid for those who don't have Pro. Would be a good update when you get time for it.
Hi,
I am trying to implement a List with one itemrenderer for the first element and a 2nd itemrenderer for the rest of the elements. I only found a way to specify 1 single ietmrenderer for the whole list. Is there a way to achieve this?
Alternatively, I guess I could use datagrid with single column and use a header itemrenderer to do this. However, I just need a flat list and using datagrid seems overkill...any thoughts?
Thanks!
----------------------
Alex responds:
I might just put a button at the top of the list to act as the header. There is a method called createItemRenderer you can override to try to get a different renderer for the first item.
Hi Alex,
Is there an event that will fire for every change in the dataprovider? I tried dataChange() but then I ended up piggy backing on a image source change. I haven't tried, but once the data changes, then I want to make a change. For example a user arrive triggering an effect, then I want to set the users state to active, so that the effect won't trigger. Is there a good way to do that? Thanks.
-------------------
Alex responds:
collectionChange fires for changes to the dataProvider. See mx.events.CollectionEvent
Jason, AdvancedDataGridColumn's styleFunction is really slow. I had a huge performance issue I was trying to nail down and it turned out to be the styleFunction. I wasn't event doing anything fancy. just bold and color. I'm now investigating the itemRenderer route.
Wooosh...just wasted an hour looking for a HTML cell renderer. Your renderer is very helpful, i just used it to build a HTML cell renderer for AdvancedDataGridColumn.
Thanks!
Cheers
Hi Alex,
See I have a AdvancedDataGrid , inside one TileList as ItemRenderer and inside one more itemrender one custom itemrendere, the problem is the rows of the adavnceddatagrid is taking the not the actual size of tile list , even of the list is not there , it takes some default value. I am screwed I dont how to set the rowheight according to the TileList renderer size , please please giv me solution ...........
-----------------------
Alex responds:
I would ask on the Adobe forums. More folks can help there. It usually comes down to setting the measuredHeight or explicitHeight of the custom renderers correctly.
At last I got to solve the pblm , what I did was according to the Itemrenderer data size , measured the height and assigned to the Advanced Data Grid rowHeight . Anyway problem solved , thanks for responding to my query
Alex, bud, I have tried everything. I am trying to change the dataField property of a datagrid column based on the value of another datagrid column. I have tried updating values in custom Datagrid component, using labelfunction, using itemrenderer, etc... no luck... right now I have have an creationcomplete (tried init) event in the parent component to the datagrid that sets 'if (dg.selecteditem[Column]=="value") dg.selecteditem[Column2].dataField="value"; that does not work either...
can you help?
--------------------
Alex responds:
Not sure why you're referencing selectedItem. I would think you would want the columns property. The DataGrid does not watch for changes in the columns so you often have to copy the columns and reset the entire array of columns
Hi Alex,
I am trying to build a datagrid which shows a hierarchical data. It works okay. But when I add a cell renderer (combobox), the renderder is not working. The same renderer works in a flat datagrid. Do you have any example of such thing.
Thanks so much!
Nancy
Here's the code,
[Bindable]
private var hierarchicalTablData:Object =
{chassis_card:"Chassis-lab", Summary:"true", children: new ArrayCollection([
{chassis_card: "Card1", s_capacity:"700MB", target:"chs1/card1",children: new ArrayCollection([
{chassis_card: "100MBvNIC", Summary:"true", cardType:"1GB", s_capacity:"100MB"},
{chassis_card: "200MBvNIC", cardType:"1GB", s_capacity:"200MB"}])},
{chassis_card:"Card2", s_capacity:"400MB",target:"chs1/card1",Summary:"false", children: new ArrayCollection([
{chassis_card:"100MBvNIC", cardType:"1GB", s_capacity:"100MB", attributes:"Read Only"},
{chassis_card:"500MBvNIC", Summary:"true", cardType:"1GB", s_capacity:"500MB"}])},
{chassis_card: "Card3", s_capacity:"800MB",target:"chs1/card1",children: new ArrayCollection([
{chassis_card: "200MB", cardType:"1GB", s_capacity:"200MB"},
{chassis_card: "Card4", s_capacity:"7GB",target:"chs1/card1",children: new ArrayCollection([
{chassis_card: "1GBvNIC", cardType:"10GB", s_capacity:"1GB"},
{chassis_card: "2GBvNIC", cardType:"10GB", s_capacity:"2GB"}])}])}
])};
chs1/card1
chs2/card2
chs2/card2
chs3/card1
chs3/card1
------------------
Alex responds:
Ask on an Adobe forum or on Sameer Bhatt's blog
Alex,
Thank you for your very helpful advice. Please help me with this one. I have a datagrid with regular entry columns and some columns with combobox itemrenderers. I validate data for changes in the combobox cells in a method that is triggered by the list event. If the data is bad I set the errorString for the combobox cell via the event.currentTraget.errorString. I validate the text entry cells in a method triggered by the DataGridEvent. I need to clear the errorString property for a combobox cell during the DataGridEvent but I can't seem to access the errorString property while in the DataGridEvent process for the text entry cell. Any ideas? Thanks very much for your help.
Hi Alex,
Can we initialize a variable inside a custom item renderer from outside mxml? Plz let me know if it is posible.
Thanks
Sachin
One way is to have a "valid" flag in the data items and have the combobox renderer check that and clear its errorstring.
It is probably possible, but will likely be fragile if there is scrolling, and indicates that there might be something wrong with the design. Renderers should pull data from the outside, it should almost never be pushed in.
Alex,
I've been using your renderers for a while now and love them. However, I've recently upgraded to the new Flash Builder Beta and when I compile in Flex 4.0, I get an odd behavior. When I initialize the comboBoxDataProvider directly in a result event, it no longer redraws the list of values. If I interact with the datagrid (resize the column, for example), the data then shows correctly.
I've queried around and played with some of the invalidateDisplayList(), etc. But I'll admit I really don't understand the examples.
I assume Adobe's done something slick to optimize the way the combobox refreshes and under what conditions, but I'm at a loss to know where I should tweak the code to make this happen.
I've been digging on the forums and haven't found anything, so I'm posting here on the chance you still monitor this thread.
Thanks advanced.
Owen
If you can create a simple example, post it on a forum.
Great article, i'm a fan of your articles. As i'm new to this I get confused on when to use what. Could you explain when to use an ItemRenderer vs RendererProviders. I cannot seem to find any articles on RendererProviders. The two examples below are my most common uses other that trying to display "warning" or "error" icons for different rows in an advancedDataGrid based on input. (i'm working on this now). I know this might seem alot to ask, if anything can you reference me to another article.
I used a rendererProvider to create different cells in the same column in an advancedGridData to be either a label or link based on input data.
I used an in-line item renderer to initially check or uncheck checkbox's in an advancedDataComponent column based on input data.
I have a dataGridColumn with many columns.I have to give color to 4 columns only.My problem is i am able to color the whole datagridColumn at a stretch,but my requirement is to color only those rows within a column which has data.I tried using ItemRenderer namely CellColorRenderer .
public class CellColorRenderer extends Label {
public static var colorObjectMap:Object=new Object;
public static var bidColor:uint; //Specifies the colors
public static var askColor:uint; //Specifies the colors
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
var g:Graphics = graphics;
g.clear();
/* Set the background color based on the datafield. */
var dgListData:DataGridListData = listData as DataGridListData;
var dataGrid:DataGrid = dgListData.owner as DataGrid;
var column:BlinkWhenChangedColumn = dataGrid.columns[dgListData.columnIndex];
g.beginFill(bidColor, 0.5);
g.drawRect(0, 0, unscaledWidth, unscaledHeight);
g.endFill();
}
}
I use another itemRenderer BlinkWhenChangedRenderer inorder to blink the data available in these columns.I could see that only one among the two item renderers work at a time.I was able to color the columns but the data in the datagrid column did not blink .
public class BlinkWhenChangedRenderer extends DataGridItemRenderer
{
private var lastText:String = null;
private var lastUID:String = null;
private var timer:Timer=null;
public function BlinkWhenChangedRenderer()
{
super();
timer=new Timer(AppConstants.TIMER_DELAY);
timer.addEventListener("timer", doRest);
}
override public function validateNow():void
{
var needBlink:Boolean = false;
super.validateNow();
if (!listData)
{
background = false;
return;
}
var dgListData:DataGridListData = listData as DataGridListData;
var dataGrid:DataGrid = dgListData.owner as DataGrid;
var column:BlinkWhenChangedColumn = dataGrid.columns[dgListData.columnIndex];
if (dgListData.uid == lastUID)
{
if (lastText != dgListData.label)
{
needBlink = true;
}
}
if (needBlink)
{
timer.stop();
background = true;
if(dgListData.label>lastText){
// backgroundColor = 0x047616;
backgroundColor = parseInt(AppConstants.UP_COLOR);
textColor=0xFFFFFF;
}else{
//backgroundColor = 0xFF0000;
backgroundColor = parseInt(AppConstants.DOWN_COLOR);
textColor=0xFFFFFF;
}
timer.start();
}
lastUID = dgListData.uid;
lastText = dgListData.label;
}
private function doRest(event:Event):void{
background = false;
textColor=0x000000;
}
}
please help me with a solution.
rendererProvider is only in AdvancedDataGrid and allows you to create different renderers based on the data.
The same itemRenderers are normally created for every item in the dataProvider
That is just too hard to read. You'll get faster help if you ask on the Adobe forum
Hi
I face a problem that must be related to this issue.
I have a custom item renderer that has a list in it. each list consists of name of persons.
I use the drag option to drag-drop items from list to list ( from a list in an item renderer to the list of a different item renderer)
Now, when i drag "regularly" all works fine, but when i drag to an item renderer that is "Far" down the list , the drop is no taking place and the list of "Items" is empty.
i assume that the problem is that when i drag to a cell that is far down, the item renderer is "re-used" and the data is no longer valid.
from looking in the framework code i see that the dragged items are placed in the DragManager so i am not sure what is wrong here.
ant ideas?
Use List Base controls inside Item Renderers
Solves Drag and Drop problems in this case
http://www.softologia.com/node/28
Great Blog. Hopefully I didn't miss it in this article, but is there a way to make itemRenderers only called once. I have 65 columns on a grid for a client (don't ask me why) and everytime I scroll or move the cursor on the grid it calls the itemRenderer and I would prefer it didnt after the first call/setup of the cells.
ItemRenderers are always recycled. Your other options are a repearter in a container or an extra wide datagrid partially clipped by a container. However, I would be wary of the memory usage.
I'm trying to use one itemRenderer to handle different data objects. Is there a way to see if a field in the data object doesn't exist and bypass a check for it. Below I check for field value.Key.toString() == "Y"... But if Key doesn't exist, how do I bypass the check without abending on a not found.
[AS]
private static const CONST_YES:String = "Y";
override public function set data(value:Object):void
{
check_img.visible = false;
check_img.includeInLayout = false;
trace("icon renderer");
if (value.Exclude.toString() == CONST_YES )
{
check_img.visible = true;
check_img.includeInLayout=true;
}
if (value.Key.toString() == CONST_YES)
{
check_img.visible = true;
check_img.includeInLayout = true;
}
}
[/AS]
How do i split a column to 3 sub columns, I tried creating a centerColumn with the example you provided, but I was not able to see the seperator drawn between the second and third sub columns and also the second and third columns overlap. Please help
I just copied the same example you gave for the split column, but i get the error
ReferenceError: Error #1069: Property history not found on String and there is no default value.
at SplitDataGridItemRenderer/commitProperties()[C:\...\SplitDataGridItemRenderer.as:165]
at mx.core::UIComponent/validateProperties()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:5807]
at mx.managers::LayoutManager/validateClient()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:811]
at mx.controls::DataGrid/http://www.adobe.com/2006/flex/mx/internal::setupRendererFromData()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\DataGrid.as:1650]
at mx.controls::DataGrid/commitProperties()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\controls\DataGrid.as:1608]
at mx.core::UIComponent/validateProperties()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:5807]
at mx.managers::LayoutManager/validateProperties()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:539]
at mx.managers::LayoutManager/doPhasedInstantiation()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\LayoutManager.as:659]
at Function/http://adobe.com/AS3/2006/builtin::apply()
at mx.core::UIComponent/callLaterDispatcher2()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8628]
at mx.core::UIComponent/callLaterDispatcher()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:8568]
this is a great post do you have any example of validating that has already gotten to the the datagrid. im looking to validate data.lenght in a data grid.
thanks
Juan
if ("Key" in value)
{
if (value.Key.toString() == CONST_YES)...
Sorry, these examples are generally unsupported. You'll have to debug in, learn the code, and figure out why.
You might be able to get some help from one of the forums.
I don't have any examples of that. Ask on one of the forums.
Hi
i wanted to add checkboxes in combobox and select multiple checkbox as i like.so plz help me,i m able to add checkbox as itemrenderer but not able able to select multiple
In the example on my blog, you can select as many checkboxes as you want
Alex, I was able to split a column into 3 columns, but i have a problem with rendering the right column alone again, if the right column value is 0, I wanted to make the color green or else Red. I get whole of the right column along with the header changing the color, but i want to color based on the value of the right column. I was not able to find any help from any forums, this has taken me almost a week so far. Please kindly help. I need to figure this out ASAP. No go till now. Please help
I can't guarantee that I can look at this. You'll have better luck on the forums if you post a small test case. I'm having trouble understanding what you are seeing. Make sure if you color backgrounds that you understand how to deal with recycling.