Thinking About Item Renderers
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
Comments
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
Posted by: Michael Schmalle | March 29, 2007 04:33 PM
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!
Posted by: Roman Gruhn | March 30, 2007 04:49 AM
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
Posted by: Andrew | April 1, 2007 08:48 AM
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
Posted by: Ben | April 2, 2007 11:28 AM
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
Posted by: jeff | April 3, 2007 02:35 PM
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.
Posted by: Thijs Triemstra | April 4, 2007 02:22 AM
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
Posted by: Ben | April 4, 2007 09:49 AM
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
Posted by: Ben | April 4, 2007 12:16 PM
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
Posted by: Ben | April 5, 2007 06:28 AM
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
Posted by: Vyshak | April 9, 2007 06:48 AM
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..
Posted by: Vyshak | April 10, 2007 01:53 AM
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.
Posted by: Lisa Twede | April 11, 2007 10:53 AM
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
Posted by: Abdul Qabiz | April 12, 2007 11:10 PM
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;
Posted by: Jonathan Marecki | April 19, 2007 02:14 PM
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
Posted by: anthony | April 22, 2007 06:55 AM
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
Posted by: Erik | April 24, 2007 02:06 PM
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.
Posted by: Paul Whitelock | May 10, 2007 10:34 AM
>> 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
Posted by: Paul Whitelock | May 11, 2007 11:28 AM
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.
Posted by: Sanjucta Ghose | May 14, 2007 12:25 AM
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.
Posted by: Lotte | May 15, 2007 12:20 PM
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.
Posted by: Leon | May 23, 2007 07:41 PM
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.
Posted by: Lisa Twede | May 25, 2007 10:05 AM
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.
Posted by: nwebb | May 31, 2007 08:27 AM
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
Posted by: nk | June 4, 2007 07:37 AM
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.
Posted by: Peter | June 13, 2007 04:23 PM
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.
Posted by: rod | June 25, 2007 07:56 AM
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.
Posted by: JK | June 25, 2007 09:46 PM
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.
Posted by: NR | June 26, 2007 04:00 PM
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.
Posted by: JK | July 4, 2007 04:16 AM
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.
Posted by: Bob | July 17, 2007 10:25 AM
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?
Posted by: Bob | July 18, 2007 04:12 PM
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
Posted by: Bob | July 18, 2007 05:25 PM
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
Posted by: Bob | August 1, 2007 04:10 PM
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.
Posted by: Ashish Mishra | August 3, 2007 12:21 AM
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.
Posted by: Karl | August 10, 2007 01:47 AM
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.
Posted by: Karl | August 10, 2007 11:46 PM
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
Posted by: Morgan | September 4, 2007 04:18 AM
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.
Posted by: Rudolf | September 6, 2007 06:03 AM
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.
Posted by: Roman | September 7, 2007 03:08 PM
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
Posted by: Pietro | November 8, 2007 02:12 AM
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.
Posted by: Benoit Jadinon | November 19, 2007 10:23 AM
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.
Posted by: Greg | November 20, 2007 02:20 PM
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
Posted by: Adit Shetty | November 22, 2007 02:58 AM
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"
Posted by: darko | November 22, 2007 02:06 PM
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?
Posted by: MJ | November 26, 2007 11:50 AM
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
Posted by: shaf | December 13, 2007 11:08 AM
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.
Posted by: Nikhil | January 7, 2008 10:45 PM
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.
Posted by: Evan | January 17, 2008 02:08 PM
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.
Posted by: Sathya | January 29, 2008 09:20 AM
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
Posted by: Nikhil | January 30, 2008 02:56 AM
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().
Posted by: judah | February 2, 2008 11:09 PM
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)
Posted by: judah | February 2, 2008 11:28 PM
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.
Posted by: alex | February 5, 2008 04:10 AM
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
Posted by: Larry | February 5, 2008 12:36 PM
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
Posted by: Nikhil | February 7, 2008 03:13 AM
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.
Posted by: Nikhil | February 13, 2008 09:09 PM
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.
Posted by: Anita | February 14, 2008 10:51 AM
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
Posted by: jaguirkhan | February 16, 2008 03:09 AM
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.
Posted by: Cato | February 26, 2008 12:41 AM
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.
Posted by: Nikhil | February 26, 2008 01:18 AM
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
Posted by: Tony | March 6, 2008 08:09 AM
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.
Posted by: thiru | March 11, 2008 09:11 AM
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.
Posted by: Adric | March 20, 2008 12:41 PM
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.
Posted by: Nikhil | March 24, 2008 06:08 AM
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.
Posted by: TungH2 | April 1, 2008 07:11 PM
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
Posted by: Brixel | April 10, 2008 10:13 AM