Wednesday, May 18, 2011

Controlling Text Wrapping in DataGrid Item Renderers

This article demonstrates how to control text wrapping with the DefaultGridItemRenderer or a simple custom item renderer based on GridItemRenderer.

Flex text components unconditionally display explicit or "hard" newlines that appear in their text string.  The text components can be configured to automatically insert "soft" newlines to prevent the text from  overlapping the component's left or right edges.   This layout process is called text "wrapping" or  "word wrapping" when the layout endeavors to only insert soft newlines in between words.   Note that soft newlines are displayed but are not inserted into the text string.

The TextField boolean wordWrap property and the Flash Text Engine (FTE) lineBreak style control can be used to enable wrapping.  By default wrapping is disabled.  Specifying wordWrap="true" for TextFields or lineBreak="toFit" for Spark text components like Label, enables automatic word wrapping.  To disable wrapping specify wordWrap="false" or lineBreak="explicit".

The high performance item renderers, DefaultGridItemRenderer and UITextFieldGridItemRenderer, are essentially TextFields, so the wordWrap property is used to control wrapping.  Custom item renderers that include Spark FTE text components can use the lineBreak style.   To simplify a common case, the default item renderer automatically sets wordWrap="true" when variableRowHeight="true" is  specified.

In the following DataGrid example all cells display the same long string that begins with "Lorem Ipsum ...".  The DataGrid's typicalItem, which defines each column's width and the default row height, is  defined with a string that contains a shorter string and a pair of newlines, so that it occupies three lines total:

    <s:typicalItem>
        <s:DataItem value="Lorem Ipsum sample text.&#10;newline&#10;"/>
    </s:typicalItem>

We've used the odd XML '&#10;' escape to introduce two newlines (the value of the newline character is decimal 10).

Here's the live example and the source code.

The first "Implicit wordWrap" column's renderer is DefaultGridItemRenderer (because a renderer was not specified) and it demonstrates the default behavior, which is to enable wrapping when variableRowHeight=true.

    <s:GridColumn dataField="value" headerText="Implicit wordWrap"/>


The second "Explicit wordWrap" column's DefaultGridItemRenderer overrides the wordWrap property.   If the  wordWrap property's value is set explicitly, the renderer ignores the DataGrid's variableRowHeight property.


    <s:GridColumn dataField="value" headerText="Explicit wordWrap">
        <s:itemRenderer>
            <fx:Component>
                <s:DefaultGridItemRenderer
                    color="0x1E6913"
                    wordWrap="{outerDocument.wordWrapCheckBox.selected}"/>
            </fx:Component>
        </s:itemRenderer>
    </s:GridColumn>

The third "Label Renderer" column's renderer is a custom GridItemRenderer that displays its text with an s:Label component.  We use the Label's maxDisplayedLines property to control line breaking and to include "..." truncation when the single line of text doesn't fit.  Note that maxDisplayedLines="0" means occupy as many lines as necessary.

    <s:GridColumn dataField="value" headerText="Label Renderer">
        <s:itemRenderer>
            <fx:Component>
        <s:GridItemRenderer>
                    <s:Label id="labelDisplay"
                        left="5" top="9" right="5" bottom="5"
                        maxDisplayedLines="{outerDocument.maxDisplayedLines}"/>
                </s:GridItemRenderer>
             </fx:Component>
         </s:itemRenderer>
    </s:GridColumn>

In this last column we could have forced the label's text to appear on one line by setting  lineBreak="explicit" as noted earlier.  Doing so is a little bit cheaper, since the text is simply clipped to the right edge of the label in that case.


9 comments:

  1. Hello Hans,

    this is actually not about your current post but a general question on the Spark datagrid: we're having serious issues using the selectedCells-property, our grid (50*50) uses this property in order to mark selections...selecting an area about 10*10 via selectedCells property causes the client to crash, do you have any advices?

    Thanx in advance, Florian...

    ReplyDelete
  2. We have been able to reproduce the scenario you've described and unfortunately it's due to a bug. The bug has been filed, it's https://bugs.adobe.com/jira/browse/SDK-30536. To select a contiguous block of cells you can use selectCellRegion(), which should work as expected.

    ReplyDelete
  3. Hello,

    This link for the source code under the running example is not for the right source. Thanks to give us the right code.

    ReplyDelete
  4. Oops, sorry about that (and sorry for not seeing your comment for months!). I've fixed the link.

    ReplyDelete
  5. I couldn't get the Label Renderer method to work without adding

    text="{data.value}"

    into the s:Label.

    Did I do something wrong since it didn't work without my fix, or was your example code incomplete?

    ReplyDelete
    Replies
    1. Also, if I dynamically add to the grid's dataprovider a new item that needs to be word-wrapped, the grid stops respecting the word wrap and stretches out the column.

      Have you seen this behaviour before?

      Delete
  6. Hello Hans, thanks for sharing valuable article about text wrapping in Datagrid. My question is some what same. How to wrap text in your Column Header Text if it is very large. In case of <mx:Datagrid its bit easy but i am using <s:Datagrid so no luck so far . I was trying with variableRowHeight="true" this property of <s:Datagrid but unable to do so.

    ReplyDelete
  7. Thank you so much for publishing this, I was having issues with multiline display of the columns, the "typicalItem" piece was the key. Thanks again for taking the time to write this up.

    ReplyDelete
  8. Thanks for the solution. I was using the wordWrap but I was stuck on this issue for a long time. I was missing variableHeight parameter.

    ReplyDelete