Recently while working on InMarket, I was tasked with displaying very large strings within a DataGridColumn to our users. The variableRowHeight property of a DataGrid will get you part of the way, but if you start to exceed a few thousand characters, you’ll find that your row has a height larger then your entire DataGrid! As a way around this we ended up using the itemEditor capabilities of the DataGrid.
To start off, first we created an itemRenderer for the DataGridColumn, which displays a maximum number of characters. If the maximum number of characters is exceeded the itemRenderer automatically truncates the string and adds “… Read More” to it.
package { import com.adobe.utils.StringUtil; import flash.text.StyleSheet; import mx.controls.dataGridClasses.DataGridItemRenderer; public class PartialTextDataGridItemRenderer extends DataGridItemRenderer { private static const MAXIMUM_NUMBER_OF_CHARACTERS:Number = 256; public function PartialTextDataGridItemRenderer() { super(); } public override function validateProperties():void { super.validateProperties(); if (listData) { text = ""; //truncate the text if needed and render text as HTML htmlText = truncateLabel(listData.label); //apply style to text so Read More link looks like a link styleSheet = getLinkStyle(); } } private static function getLinkStyle() : StyleSheet { var style:StyleSheet = new StyleSheet(); var styleObj:Object = new Object(); styleObj.fontWeight = "normal"; styleObj.fontSize = "12px"; styleObj.color = "#0000ff"; styleObj.textDecoration = "underline"; style.setStyle("a", styleObj); return style; } private static function truncateLabel(label:String) : String { if(label.length > MAXIMUM_NUMBER_OF_CHARACTERS) { label = label.substr(0,MAXIMUM_NUMBER_OF_CHARACTERS); //remove any extra whitespace at the end of the string label = StringUtil.trim(label); //ensure that label ends with ... if(label.charAt(label.length-1) == ".") { label = label + ".."; } else { label = label + "..."; } //add read more link to indicate to user that there is more //text and that it is clickable. label = label + " <a href=\"#\">Read More</a>"; } return label; } } } |
Next, for the itemEditor itemRenderer we use a TextArea that is set to not be editable. We also strip away the styling that would make it look like a TextArea embeded within the column.
package { import mx.controls.TextArea; /** * Creates an non-editable TextArea to be used as renderer and * styled so that it is seamless with the other DataGrid cells. */ public class FullTextDataGridItemRenderer extends TextArea { public function FullTextDataGridItemRenderer() { super(); this.editable = false; this.setStyle("paddingLeft",5); this.setStyle("paddingRight",5); this.setStyle("paddingTop",2); this.setStyle("paddingBottom",2); this.setStyle("backgroundAlpha",0); this.setStyle("borderStyle", "none"); } } } |
What this does is, whenever the column is clicked on, any strings that exceed the maximum length will be converted to their full length and embedded within a scrollable TextArea. It provides a seamless experience for users, by not forcing them to read a tooltip or some other dialog. Here is an example application that puts the two itemRenderers to use.
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" width="800" height="600" paddingBottom="0" paddingLeft="0" paddingRight="0" paddingTop="0" creationComplete="creationCompleteHandler(event)"> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; import mx.events.FlexEvent; [Bindable] private var gridDataProvider:ArrayCollection; /** * On creationComplete, create the data provider for the DataGrid. */ protected function creationCompleteHandler(event:FlexEvent):void { gridDataProvider = new ArrayCollection(); var longDescription:String = "Lorem ipsum dolor sit amet, consectetur " + "adipiscing elit. Maecenas pellentesque odio eget tortor feugiat " + "sit amet auctor neque eleifend. Curabitur pharetra nunc eget " + "purus hendrerit sodales. Pellentesque congue commodo felis, sed " + "volutpat sem vulputate sit amet. Nulla a dolor consectetur urna " + "laoreet rhoncus nec ut lacus. Phasellus neque felis, sagittis sed " + "lobortis sed, accumsan suscipit lectus. In nec placerat nulla. Proin " + "id sem vitae massa adipiscing luctus. Quisque vitae urna erat, a " + "ultrices est. Nulla scelerisque varius turpis et porttitor. Nullam " + "convallis elementum condimentum. Nulla ac ornare est. Phasellus " + "posuere vestibulum dolor nec cursus. "; var longShortDescription:String = "Lorem ipsum dolor sit amet"; gridDataProvider.addItem({id:1, description:longDescription, shortDescription:longShortDescription}); gridDataProvider.addItem({id:2, description:longShortDescription, shortDescription:longShortDescription}); } ]]> </mx:Script> <mx:DataGrid width="100%" height="100%" dataProvider="{gridDataProvider}" variableRowHeight="true" wordWrap="true" verticalAlign="top" editable="true" sortableColumns="false"> <mx:columns> <mx:DataGridColumn width="100" dataField="id" headerText="Id" editable="false" /> <mx:DataGridColumn dataField="description" headerText="Description" editable="true" itemRenderer="PartialTextDataGridItemRenderer" itemEditor="FullTextDataGridItemRenderer" /> <mx:DataGridColumn width="200" dataField="shortDescription" headerText="Short Description" editable="false" /> </mx:columns> </mx:DataGrid> </mx:Application> |
The source code can be downloaded at https://github.com/joshgarnett/JoshAtAdobeSourceCode/tree/master/LargeStringsInDataGrid.


