How to use the PopUpTreeGridView component
The PopUpTreeGridView
class displays a button, that when triggered, renders the items from a hierarchical data collection in a pop-up tree grid view.
⚠️ Beta Notice: This component is still quite new. Some APIs may go through minor changes in upcoming releases.
The Basics
Start by creating a PopUpTreeGridView
control, and add it to the display list.
var popUpTreeGridView = new PopUpTreeGridView();
addChild(popUpTreeGridView);
Data provider and columns
To render some data in the tree grid view, pass in a hierarchical collection that contains an object for each row.
var collection = new ArrayHierarchicalCollection([
{
dept: "Bakery",
children: [
{item: "Whole Wheat Bread", dept: "Bakery", price: "2.49"},
{item: "English Muffins", dept: "Bakery", price: "2.99"},
]
},
{
dept: "Dairy",
children: [
{item: "2% Milk", dept: "Dairy", price: "2.49"},
{item: "Butter", dept: "Dairy", price: "4.69"},
]
},
{
dept: "Meat",
children: [
{item: "Chicken breast", dept: "Meat", price: "5.90"},
{item: "Bacon", dept: "Meat", price: "4.49"},
]
},
{
dept: "Produce",
children: [
{item: "Lettuce", dept: "Produce", price: "1.29"},
{item: "Broccoli", dept: "Produce", price: "2.99"},
]
},
]);
popUpTreeGridView.dataProvider = collection;
Set the collection's itemToChildren()
method to get the children from each branch that need to be rendered by the tree grid view.
collection.itemToChildren = (item:Dynamic) -> item.children;
Next, define the columns in the tree grid view, so that it knows which fields from the data provider's items to display. One of the items from the data provider appears below.
{ item: "Broccoli", dept: "Produce", price: "2.99" }
The item has three fields, item
, dept
, and price
. Create a separate TreeGridViewColumn
for each of the fields in the item, and pass them to the columns
property.
popUpTreeGridView.columns = new ArrayCollection([
new TreeGridViewColumn("Item", (data:Dynamic) -> data.item),
new TreeGridViewColumn("Department", (data:Dynamic) -> data.dept),
new TreeGridViewColumn("Unit Price", (data:Dynamic) -> data.price)
]);
The first parameter of the TreeGridViewColumn
is the text to display in each column header. The second parameter is passed to the itemToText()
property, which is a function that returns the text to display in a cell renderer.
Items in the collection are not required to be anonymous structures, like
{ item: "Bacon", dept: "Meat", price: "4.49" }
in the example above. Class instances are allowed too (and encouraged as a best practice; you should prefer classes over anonymous structures).
Selection
Add an event listener for Event.CHANGE
to perform an action when the user selects a different item.
popUpTreeGridView.addEventListener(Event.CHANGE, popUpTreeGridView_changeHandler);
Check for the new value of the selectedItem
property in the listener.
function popUpTreeGridView_changeHandler(event:Event):Void {
var popUpTreeGridView = cast(event.currentTarget, PopUpTreeGridView);
trace("PopUpTreeGridView selectedItem change: " + popUpTreeGridView.selectedItem.text);
}
Alternatively, the value of the selectedLocation
property references the location of the items in the tree grid view's collection as an Array
of integers.
function popUpTreeGridView_changeHandler(event:Event):Void {
var popUpTreeGridView = cast(event.currentTarget, PopUpTreeGridView);
trace("PopUpTreeGridView selectedLocation change: " + popUpTreeGridView.selectedLocation);
}
Add or remove items
To add a new item at a specific location, pass an object to the data provider's addAt()
method.
var newRow = { item: "Gala Apple", dept: "Produce", price: "1.00" };
var newLocation = [3, 1];
popUpTreeGridView.dataProvider.addAt(newRow, newLocation);
In the example above, a new tab is added to the beginning.
Similarly, to remove an item, call remove()
or removeAt()
on the collection.
var locationToRemove = [3, 1];
popUpTreeGridView.dataProvider.removeAt(locationToRemove);
Cell renderers
An cell renderer is a Feathers UI component that one of the fields from a single row displayed in a TreeGridView
or PopUpTreeGridView
component. In other words, the TreeGridView
displayed by a PopUpTreeGridView
typically contains many cell renderers in a two-dimensional grid — with each one rendering a different field from each row in the collection.
Feathers UI provides a default HierarchicalItemRenderer
class, which can display data in many different ways that cover a variety of common use-cases. However, components like PopUpTreeGridView
also support custom cell renderers, which allow developers to render the tree grid view's data in infinite unique ways.
Consider a collection of items with the following format.
{ item: "Gala Apple", dept: "Frozen", price: "3.99", icon: "https://example.com/img/pizza.png" }
While the default HierarchicalItemRenderer
class can easily display some text and an image, creating a custom cell renderer for this simple data will be a good learning exercise.
A custom cell renderer designed to display this data might use a Label
to display one of the strings, and an AssetLoader
to display the image. The following example creates a DisplayObjectRecycler
which instantiates these components and adds them to a LayoutGroupItemRenderer
— a special base class for custom cell renderers.
var recycler = DisplayObjectRecycler.withFunction(() -> {
var cellRenderer = new LayoutGroupItemRenderer();
var layout = new HorizontalLayout();
layout.gap = 6.0;
layout.paddingTop = 4.0;
layout.paddingBottom = 4.0;
layout.paddingLeft = 6.0;
layout.paddingRight = 6.0;
cellRenderer.layout = layout;
var openedToggle = new ToggleButton();
openedToggle.name = "openedToggle";
cellRenderer.addChild(openedToggle);
var icon = new AssetLoader();
icon.name = "loader";
cellRenderer.addChild(icon);
var label = new Label();
label.name = "label";
cellRenderer.addChild(label);
return cellRenderer;
});
Developers are not required to use the
LayoutGroupItemRenderer
class. In fact, a custom cell renderer may be created from any OpenFL display object, including primitives likeopenfl.display.Sprite
and all other Feathers UI components.
Both PopUpTreeGridView
and TreeGridViewColumn
define cellRendererRecycler
properties. On TreeGridViewColumn
, the cellRendererRecycler
property may be used to customize the cell renderers in that specific column. On PopUpTreeGridView
, the cellRendererRecycler
property may be used to customize the default cell renderers used when a particular column doesn't have a specific cell renderer.
var column = new TreeGridViewColumn("Item", (data:Dynamic) -> data.item);
column.cellRendererRecycler = recycler;
So far, the DisplayObjectRecycler
creates the cell renderer, but it doesn't understand how to interpret the data yet. A custom update()
method on the recycler can do that.
recycler.update = (cellRenderer:LayoutGroupItemRenderer, state:TreeGridViewCellState) -> {
var openedToggle = cast(cellRenderer.getChildByName("openedToggle"), ToggleButton);
var label = cast(cellRenderer.getChildByName("label"), Label);
var loader = cast(cellRenderer.getChildByName("loader"), AssetLoader);
openedToggle.visible = state.branch && state.columnIndex == 0;
openedToggle.selected = state.branch && state.opened;
label.text = state.text;
loader.source = state.data.icon;
};
When the update()
method is called, it receives the cell renderer and an TreeGridViewCellState
object. TreeGridViewCellState
has a number of useful properties.
column
is theTreeGridViewColumn
that contains the item.columnIndex
is the position of the column within the row.data
is the row from the collection.branch
indicates if the row is a branch or not.enabled
indicates if the cell renderer should be enabled or not.location
is the position of the item within the collection.opened
indicates if a branch is opened or not.owner
is theTreeGridView
that contains the row (Note: not thePopUpTreeGridView
).rowIndex
is the position of the row within the collection.selected
is populated by comparing toselectedItem
.text
is populated usingitemToText()
In this case, the value of text
is displayed by the Label
, and the icon
field from data
(remember the example item from above, with name
and icon
fields) is displayed by the AssetLoader
. The values of branch
, columnIndex
, and opened
are used with a ToggleButton
to display whether a branch is opened or not. Obviously, we'll need an itemToText()
function to populate the text
value from the name
field.
It's always a good practice to provide a reset()
method to the DisplayObjectRecycler
, which will clean up a custom cell renderer when it is no longer used by the PopUpTreeGridView
.
recycler.reset = (cellRenderer:LayoutGroupItemRenderer, state:TreeGridViewCellState) -> {
var openedToggle = cast(cellRenderer.getChildByName("openedToggle"), ToggleButton);
var label = cast(cellRenderer.getChildByName("label"), Label);
var loader = cast(cellRenderer.getChildByName("loader"), AssetLoader);
openedToggle.visible = false;
openedToggle.selected = false;
label.text = "";
loader.source = null;
};
Warning: A
DisplayObjectRecycler
without areset()
method could potentially cause memory leaks or other unexpected behavior, if the same data needs to be used again later.
Styles
A number of styles may be customized on the sub-components of a PopUpTreeGridView
component, including styles on the button and the tree grid view.
Button
The button in a PopUpTreeGridView
component is of type Button
. Its appearance may be customized globally in a theme, or it may be customized outside of a theme on an specific, individual PopUpTreeGridView
.
See How to use the
Button
component for complete details about which styles are available for the button.
Style button globally
Use the PopUpTreeGridView.CHILD_VARIANT_BUTTON
constant in a theme to provide a function that globally styles the buttons in all PopUpTreeGridView
components.
styleProvider.setStyleFunction(
Button,
PopUpTreeGridView.CHILD_VARIANT_BUTTON,
setPopUpTreeGridView_Button_Styles);
The function should use the following signature.
function setPopUpTreeGridView_Button_Styles(button:Button):Void {
// ... set styles here
}
Style the button in a specific PopUpTreeGridView
The buttonFactory
property may be used to customize the creation of an individual button.
popUpTreeGridView.buttonFactory = () -> {
var button = new Button();
// ... set styles here
return button;
};
TreeGridView
The tree grid view in a PopUpTreeGridView
component is of type TreeGridView
. Its appearance may be customized globally in a theme, or it may be customized outside of a theme on an specific, individual PopUpTreeGridView
.
See How to use the
TreeGridView
component for complete details about which styles are available for the tree grid view.
Style tree grid view globally
Use the PopUpTreeGridView.CHILD_VARIANT_TREE_GRID_VIEW
constant in a theme to provide a function that globally styles the tree grid views in all PopUpTreeGridView
components.
styleProvider.setStyleFunction(
TreeGridView,
PopUpTreeGridView.CHILD_VARIANT_TREE_GRID_VIEW,
setPopUpTreeGridView_TreeGridView_Styles);
The function should use the following signature.
function setPopUpTreeGridView_TreeGridView_Styles(treeGridView:TreeGridView):Void {
// ... set styles here
}
Style the tree grid view in a specific PopUpTreeGridView
The treeGridViewFactory
property may be used to customize the creation of an individual tree grid view.
PopUpTreeGridView.treeGridViewFactory = () -> {
var treeGridView = new TreeGridView();
// ... set styles here
return treeGridView;
};