Datagrids and ItemRenderers!
Someone just asked me how to create a link to a file inside a Flex data grid. This isn't so hard. Here is his question:
hi i would like to upload pdf and word docs to a folder on my server and i would like to link to them from a flex datagrid. how can i do that. Thanks am using coldfusion and flex 2.
The reader didn't specify how he was uploading documents, either from Flex or from an HTML page to ColdFusion. For the purposes of this post I'm going to assume that you already have files up on the server somewhere, and can write the code to return a link to the file back to Flex.
The answer is quite simple. Just create a custom itemRenderer for a data grid column that provides a link to the file for download.
First, we'll need a data provider:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable] public var fileList : ArrayCollection = new ArrayCollection([
{id: 1, file: "test.doc", location:"http://www.jeffryhouser.com"},
{id: 1, file: "test.pdf", location:"http://www.theflexshow.com"},
{id: 1, file: "test2.doc", location:"http://www.yahoo.com"}
]);
]]></mx:Script>
The data provider contains the text to display (File property) and the location of the file (location property). In a real world app this will have probably been populated by the backend (ColdFusion in this case), perhaps with a query object or with Value Objects. Next, start the DataGid:
<mx:DataGrid dataProvider="{fileList}">
<mx:columns>
<mx:DataGridColumn dataField="location" headerText="File">
The provider is the fileList arrayCollection from above. Then we list the columns. We only have one column in this case, for the location. This needs an itemRenderer and for the purposes of this example, I'll create an in-line itemRemderer:
<mx:DataGridColumn dataField="location" headerText="File">
<mx:itemRenderer>
<mx:Component>
<mx:LinkButton click="handleClick()" label="{data.file}" >
<mx:Script><![CDATA[
public function handleClick():void{
var url:URLRequest = new URLRequest(data.location);
navigateToURL(url,"_blank");
}
]]></mx:Script>
</mx:LinkButton>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
We define the DataGridColumn, with it's primary field from the data Object as location. Then we have the itemRemderer defined in-line with the component tag. The itemRenderer is based off a LinkButton. The LinkButton calls the handleClick function. This creates a URLRequest based on the location value and passes it onto the navigateToURL.
Finally just close off your open tags and end the file:
</mx:columns>
</mx:DataGrid>
</mx:Application>
And finally, you can view the sample and the source.
For more reading you should check out The SAJ's posts on navigateToURL problems with FireFox. For more on itemRenderers check out Peter Ent's series on them.





So I have a data gird that is being populated from coldFusion. The location will always be the same up to the point of the file name for example
http://www.google.com/docs/mydoc.doc
So when I select an item in the datagrid it will hit the url and append the filename to the end of the url
In my example, I Was making the assumption that the backend (CF in your case) would be returning the full path to the file, as you specify there. However, there is no reason you wouldn't be able to concatenate them in Flex if you desired; something like this:
public function handleClick():void{
var url:URLRequest = new URLRequest(data.location + data.fileName);
navigateToURL(url,"_blank");
}
Does that help?
-Nicole
Was going mad trying to work this out.... putting the <script> inside the <linkbutton> was something I never would have thought of. Brilliant (I am learn more and more every day 8->)
All item Renderers have a 'data' property, which references the object from your dataProvider. I believe it comes from the IDataRenderer ( http://livedocs.adobe.com/flex/3/langref/mx/core/I... )
Does that answer your question?
This is great, thank you!
Quick question: Is it possible to put the handleClick AS code into my <mx:Script> block at the top of the mxml file, instead of inline the datagrid?
Yes, but you won't be able to call the function directly if you take the handleClick handler outside of the inline component.
You could use outerDocument to reference the parent component ( http://livedocs.adobe.com/flex/3/html/help.html?co... ). This breaks encapsulation because it makes the inline component dependent upon it's parent.
You could also bubble an event up from the inline component, and add an event listener to the main component. This may present some issues as you try to figure out which renderer the event came from; but is a much better approach than using outerDocument because it does not break encapsulation.