PickTreePopup
Available since v3.0.1
PickTreePopup is a component that allows the user to select a value from a Popup list of entities.
Info
The following features are not available for the PickTreePopup widget in this release:
- fully or partially expanded initial load (the tree always opens collapsed)

Basics
The popup shows the records as a tree: the requirements of the Tree widget apply to the business component of the popup.
The minimal data set of a record of the popup is:
id— the identifier of the record.parentId— the identifier of the parent record. For a root record the value isnull. The backend must always return this field, and the field must be filterable, because the tree is built with the requestsparentId.specified=false(root records) andparentId.equals=<id>(child records). see more Lazy load- a name (title) field — the value shown in the tree column and picked into the field.
isLeaf— a computed boolean flag. The default value isfalse. The valuetruemeans that the record has no child records, so the expand arrow is not displayed for it.
Info
The first field of the fields array is rendered as the tree column: the expand arrow. All the other fields are rendered as ordinary columns.
parentId and isLeaf are service fields: they are declared in the popup widget with type hidden.
All tree specific settings are placed in options.tree of .widget.json.
Example
| Property | Type | Default | Description |
|---|---|---|---|
parentIdFieldKey |
String | parentId |
Name of the field that holds the identifier of the parent record. |
isLeafFieldKey |
String | isLeaf |
Name of the field that holds the flag "the record has no child records". |
searchModes |
Array of collapse, hide |
["collapse", "hide"] |
Modes of displaying the filtration result. The first item of the array is the active one. see Search modes |
onFilterApplyNestLevel |
Number | 0 |
How many levels of the navigation path are shown above a found record in collapse mode. see Search modes |
insertPosition |
start, end |
— | Where a newly created row is inserted inside its node. see Create |
selection |
node, nodeAndLeaf, leaf |
— | What the user is allowed to pick. see Selection modes |
The tree is always loaded lazily and always opens collapsed: only the root records are requested when the popup is opened, and the child records of a node are requested when the user expands it.
Info
The operation specified is used only to select the records with an empty parent. For all the other requests the operation equals is used.
This is why the field that holds the parent identifier must be filterable on the backend.
Every node keeps its own pagination state, so the records of one node are loaded page by page independently of the neighbouring nodes. see more Pagination
Example
- Root records are requested with the filter by an empty parent:
- Child records of a node are requested when the node is expanded:
How does it look?

Example
Step1 Add field with type pickTree see more Fields
{
"name": "MyExampleList",
"title": "PickTreePopup widget basic List",
"type": "List",
"bc": "myexample",
"fields": [
{
"title": "Custom Field Pick List",
"key": "customFieldPickTree",
"type": "pickTree",
"popupBcName": "myEntityPickPick",
"pickMap": {
"customFieldPickTreeId": "id",
"customFieldPickTree": "customField"
}
}
],
"options": {
"actionGroups": {
"include": [
"save"
]
}
}
}
Step2 Create popup widget .widget.json with type = "PickTreePopup".
For the tree to work correctly, the popup widget must contain the parentId and isLeaf fields. These fields should be configured as hidden.
{
"name": "myEntityPickPickPickTreePopup",
"title": "PickTreePopup widget basic",
"type": "PickTreePopup",
"bc": "myEntityPickPick",
"fields": [
{
"title": "Custom Field",
"key": "customField",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "text"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
],
"options": {}
}
Step3 Add widget and popup widget to corresponding .view.json.
{
"name": "myexamplelist",
"title": "MyExample List",
"template": "DashboardView",
"url": "/screen/myexample/view/myexamplelist",
"widgets": [
{
"widgetName": "myEntityPickPickPickTreePopup",
"position": 2,
"gridWidth": 24
},
{
"widgetName": "SecondLevelMenu",
"position": 10,
"gridWidth": 12
},
{
"widgetName": "MyExampleList",
"position": 20,
"gridWidth": 24
}
],
"rolesAllowed": [
"CXBOX_USER"
]
}
Title
Title Basic
There are 3 types of titles for a Picktree Popup:
constant title: displays a fixed piece of text which cannot be changed.constant title empty: shows no text.calculated title: displays a dynamic piece of text, meaning it can change based on business logic or data in the application.
How does it look?



How to add?
Example
Step1 Add name for title to .widget.json.
{
"title": "Constant Title",
"name": "myEntityPickPickTreePopup",
"type": "PickTreePopup",
"bc": "myEntityPickPickTreePopup",
"fields": [
{
"title": "Custom Field Pick",
"key": "customFieldPick",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "text"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
],
"options": {
"tree": {
"selection": "node"
}
}
}
Step1 Delete parameter title to .widget.json.
{
"name": "myEntityPickPickTreePopup",
"type": "PickTreePopup",
"bc": "myEntityPickPickTreePopup",
"fields": [
{
"title": "Custom Field Pick",
"key": "customFieldPick",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "text"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
],
"options": {
"tree": {
"selection": "leaf"
}
}
}
Step1 Add ${customField} for title to .widget.json.
{
"title": "customFieldPick: ${customFieldPick}",
"name": "myEntityPickPickTreePopup",
"type": "PickTreePopup",
"bc": "myEntityPickPickTreePopup",
"fields": [
{
"title": "Custom Field Pick",
"key": "customFieldPick",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "text"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
],
"options": {
"actionGroups": {
"include": [
"save"
]
}
}
}
Title Color
Title Color allows you to specify a color for a title. It can be constant or calculated.
Constant color
Constant color is a fixed color that doesn't change. It remains the same regardless of any factors in the application. Calculated color
Calculated color can be used to change a title color dynamically. It changes depending on business logic or data in the application.
Info
Title colorization is applicable to the following fields: date, dateTime, dateTimeWithSeconds, number, money, percent, time, input, text, dictionary, radio, checkbox, pickList, inlinePickList, multivalue, multivalueHover.
How does it look?

How to add?
Example
Step 1 Add custom field for color to corresponding DataResponseDTO. The field can contain a HEX color or be null.
public MyEntityPickDTO(MyEntity entity) {
this.id = entity.getId().toString();
this.parentId = entity.getParentId();
this.isLeaf = entity.getChildren().isEmpty();
this.customField = entity.getCustomField();
this.customFieldColor = "#edaa";
this.customFieldColorFieldText = "#aeda";
Step 2 Add "bgColorKey" : custom field for color and to .widget.json.
Add in title field with ${customField}
{
"name": "myEntityPickTreePopup",
"title": "FieldInput:${customFieldColorInput}, FieldText: ${customFieldColorText}",
"type": "PickTreePopup",
"bc": "myEntityPickTreePopup",
"fields": [
{
"title": "Color Input",
"key": "customFieldColorInput",
"type": "input",
"bgColorKey": "customFieldColor"
},
{
"title": "Color Text",
"key": "customFieldColorText",
"type": "text",
"bgColorKey": "customFieldColorFieldText"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
]
}
Add "bgColor" : HEX color to .widget.json.
Add in title field with ${customField}
{
"name": "myEntityPickTreePopupColorConst",
"title": "FieldInput:${customFieldColorInputConst}, FieldText: ${customFieldColorTextConst}",
"type": "PickTreePopup",
"bc": "myEntityPickTreePopupColorConst",
"fields": [
{
"title": "Color Input",
"key": "customFieldColorInputConst",
"type": "input",
"bgColor": "#edaa"
},
{
"title": "Color Text",
"key": "customFieldColorTextConst",
"type": "text",
"bgColor": "#aeda"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
]
}
Business component
This specifies the business component (BC) to which this form belongs. A business component represents a specific part of a system that handles a particular business logic or data.
see more Business component
Show condition
Fields
Fields Configuration. The fields array defines the individual fields present within the form.
- "title"
Description: Field Title.
Type: String(optional).
- "key"
Description: Name field to corresponding DataResponseDTO.
Type: String(required).
- "type"
Description: Field types
Type: String(required).
How to add?
Example
Step 1 Download plugin download Intellij Plugin
Step 2 Add existing field to an existing form widget

Add field to .widget.json.
{
"name": "myEntityPickPickPickTreePopup",
"title": "PickTreePopup widget basic",
"type": "PickTreePopup",
"bc": "myEntityPickPick",
"fields": [
{
"title": "Custom Field",
"key": "customField",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "text"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
],
"options": {}
}
Options layout
options.layout - no use in this type.
Standard Actions
Actions show available actions as separate buttons see more Actions.
Standard Actions:
Create: Action to initialize the process of creating a new recordEdit: Action to change a record of the popup (inline-form)Delete: Action to remove a record of the popupSave: Action to store the data entered or modifiedCancel-create: Action to abort the creation of a new record, discarding any input without saving
Create
Create button enables you to create a new value by clicking the Add button. This action can be performed in three different ways, feel free to choose any, depending on your logic of application:
There are three methods to create a record:
- Inline: You can add a line directly.
Info
Pagination won't function until the page is refreshed after adding records.
-
Inline-form: You can add data using a form widget without leaving your current view.
-
With view: not applicable.
Inline
With Line Addition, a new empty row is immediately added to the popup when the "Add" button is clicked. This is a quick way to add rows without needing to input data beforehand.
The position of the newly created row inside its node is defined by options.tree.insertPosition: start places it before the already loaded rows of the node, end places it after them. see options.tree
How does it look?

How to add?
Example
Step1 Add button create to corresponding VersionAwareResponseService.
@Override
public Actions<MyEntityPickPickDTO> getActions() {
return Actions.<MyEntityPickPickDTO>builder()
.create(crt -> crt.text("Add"))
.save(sv -> sv.text("Save"))
.cancelCreate(ccr -> ccr.text("Cancel").available(bc -> true))
.delete(dlt -> dlt.text("Delete"))
.build();
}
Step2 Add button create to corresponding .widget.json.
The position of a newly created row inside its node is defined by options.tree.insertPosition: start places it before the already loaded rows of the node, end places it after them.
{
"title": "PickTreePopup create",
"name": "myEntityPickPickTreeCreateInlinePopup",
"type": "PickTreePopup",
"bc": "myEntityPickPickTreePopup",
"fields": [
{
"title": "Custom Field Pick",
"key": "customFieldPick",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "input"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
],
"options": {
"actionGroups": {
"include": [
"create",
"delete",
"save"
]
}
}
}
Step3 Add fields.setEnabled to corresponding FieldMetaBuilder.
Inline-form
Create with widget opens an additional widget when the "Add" button is clicked. The form will appear in the popup, allowing you to view both the tree of entities and the form for adding a new row.
After filling the information in and clicking "Save", the new row is added to the tree.
The position of the newly created row inside its node is defined by options.tree.insertPosition: start places it before the already loaded rows of the node, end places it after them. see options.tree
How does it look?

How to add?
Example
Step1 Add button create to corresponding VersionAwareResponseService.
@Override
public Actions<MyEntityPickPickDTO> getActions() {
return Actions.<MyEntityPickPickDTO>builder()
.create(crt -> crt.text("Add"))
.save(sv -> sv.text("Save"))
.cancelCreate(ccr -> ccr.text("Cancel").available(bc -> true))
.delete(dlt -> dlt.text("Delete"))
.build();
}
public void buildRowDependentMeta(RowDependentFieldsMeta<MyEntityPickPickDTO> fields, InnerBcDescription bcDescription,
Long id, Long parentId) {
fields.setEnabled(MyEntityPickPickDTO_.customFieldPick);
}
Form that appears when you click a button
{
"title": "",
"name": "myEntityPickPickTreePopupForm",
"type": "Form",
"bc": "myEntityPickPickTreePopup",
"fields": [
{
"label": "Custom Field Pick",
"key": "customFieldPick",
"type": "input"
}
],
"options": {
"layout": {
"rows": [
{
"cols": [
{
"fieldKey": "customFieldPick",
"span": 12
}
]
}
]
},
"actionGroups": {
"include": [
"save",
"cancel-create"
]
}
}
}
Step4 Add widget.json with type Form to corresponding .view.json.
{
"name": "myexamplelistinlineform",
"title": "MyExample List",
"template": "DashboardView",
"url": "/screen/myexample/view/myexamplelistinlineform",
"widgets": [
{
"widgetName": "myEntityPickPickTreePopupForm",
"position": 0,
"gridWidth": 24
},
{
"widgetName": "myEntityPickPickTreePopup",
"position": 1,
"gridWidth": 24
},
{
"widgetName": "SecondLevelMenu",
"position": 5,
"gridWidth": 24
},
{
"widgetName": "ThirdLevelMenu",
"position": 7,
"gridWidth": 24
},
{
"widgetName": "MyExampleListInlineForm",
"position": 20,
"gridWidth": 12
}
],
"rolesAllowed": [
"CXBOX_USER"
]
}
Step5 Add button create and widget with type Form to corresponding .widget.json.
options.create: Name widget that appears when you click a button
The position of a newly created row inside its node is defined by options.tree.insertPosition: start places it before the already loaded rows of the node, end places it after them.
{
"title": "PickTreePopup create",
"name": "myEntityPickPickTreePopup",
"type": "PickTreePopup",
"bc": "myEntityPickPickTreePopup",
"fields": [
{
"title": "Custom Field Pick",
"key": "customFieldPick",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "input"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
],
"options": {
"create": {
"widget": "myEntityPickPickTreePopupForm"
},
"edit": {
"widget": "myEntityPickPickTreePopupForm"
},
"actionGroups": {
"include": [
"create",
"delete",
"save"
]
}
}
}
With view
not applicable
Edit
Edit enables you to change the field value. Just like with Create button, there are three ways of implementing this Action.
There are three methods to edit a record:
-
Inline: not applicable
-
Inline-form: You can edit data using a form widget without leaving your current view.
-
With view: not applicable
Inline
not applicable: a click on a row of the popup picks the value. A row is edited through the inline-form or right after it is created.
Inline-form
Edit with widget opens an additional widget when clicking on the Edit option from a three-dot menu.
How does it look?

How to add?
Example
Step1 Create widget.json with type Form that appears when you click a button
{
"title": "",
"name": "myEntityFormForEditPickTreeInlineForm",
"type": "Form",
"bc": "myEntityPickInlineForm",
"fields": [
{
"label": "Custom Field",
"key": "customField",
"type": "input"
}
],
"options": {
"layout": {
"rows": [
{
"cols": [
{
"fieldKey": "customField",
"span": 12
}
]
}
]
},
"actionGroups": {
"include": [
"save",
"cancel-create"
]
}
}
}
Step2 Add widget.json with type Form to corresponding .view.json.
{
"name": "myexamplelistinlineform",
"title": "MyExample List",
"template": "DashboardView",
"url": "/screen/myexample/view/myexamplelistinlineform",
"widgets": [
{
"widgetName": "myEntityFormForEditPickTreeInlineForm",
"position": 0,
"gridWidth": 24
},
{
"widgetName": "myEntityPickTreeInlineForm",
"position": 2,
"gridWidth": 24
},
{
"widgetName": "SecondLevelMenu",
"position": 10,
"gridWidth": 12
},
{
"widgetName": "ThirdLevelMenu",
"position": 17,
"gridWidth": 24
},
{
"widgetName": "MyExampleListInlineForm",
"position": 20,
"gridWidth": 24
}
],
"rolesAllowed": [
"CXBOX_USER"
]
}
Step3 Add button edit and widget with type Form to corresponding .widget.json.
options.edit: Name widget that appears when you click a button
{
"name": "myEntityPickTreeInlineForm",
"title": "PickTreePopup widget edit Picktree",
"type": "PickTreePopup",
"bc": "myEntityPickInlineForm",
"fields": [
{
"title": "Custom Field",
"key": "customField",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "input"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
],
"options": {
"edit": {
"widget": "myEntityFormForEditPickTreeInlineForm"
},
"actionGroups": {
"include": [
"save"
]
}
}
}
With view
not applicable
Delete
Delete remove an existing record.
Tips
Please note that the row you are attempting to delete may be referenced by another part of the system or a parent entity. To ensure clarity, you should handle this exception and provide a explanation to the user.
How does it look?

How to add?
Example
Step1 Add action delete to corresponding VersionAwareResponseService.
By default, the access button is available when a record exist.
@Override
public Actions<MyEntityPickPickDTO> getActions() {
return Actions.<MyEntityPickPickDTO>builder()
.create(crt -> crt.text("Add"))
.save(sv -> sv.text("Save"))
.cancelCreate(ccr -> ccr.text("Cancel").available(bc -> true))
.delete(dlt -> dlt.text("Delete"))
.build();
}
@Override
public ActionResultDTO<MyEntityPickPickDTO> deleteEntity(BusinessComponent bc) {
ActionResultDTO<MyEntityPickPickDTO> contactDTOActionResultDTO;
try {
contactDTOActionResultDTO = super.deleteEntity(bc);
repository.flush();
} catch (DataIntegrityViolationException e) {
throw new BusinessException(e).addPopup("You are trying to delete row, that is referenced from other place in system. Deletion is not available");
}
return contactDTOActionResultDTO;
}
{
"name": "myEntityPickPickPickTreePopup",
"title": "PickTreePopup widget delete Picktree",
"type": "PickTreePopup",
"bc": "myEntityPickPick",
"fields": [
{
"title": "Custom Field",
"key": "customField",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "input"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
],
"options": {
"actionGroups": {
"include": [
"create",
"save",
"delete"
]
}
}
}
Save
Save to store the data entered or modified. see information on autosave
How does it look?

How to add?
Example
Step1 Add action save to corresponding VersionAwareResponseService.
@Override
public Actions<MyExampleDTO> getActions() {
return Actions.<MyExampleDTO>builder()
.create(crt -> crt.text("Add"))
.save(sv -> sv.text("Save"))
.cancelCreate(ccr -> ccr.text("Cancel").available(bc -> true))
.delete(dlt -> dlt.text("Delete"))
.build();
}
{
"name": "MyExampleForm",
"title": "PickTreePopup widget action save",
"type": "Form",
"bc": "myexample",
"fields": [
{
"label": "Custom Field Pick List",
"key": "customFieldPickTree",
"type": "pickTree",
"popupBcName": "myEntityPickPick",
"pickMap": {
"customFieldPickTree": "customField",
"customFieldPickTreeId": "id"
}
}
],
"options": {
"actionGroups": {
"include": [
"save"
]
},
"layout": {
"rows": [
{
"cols": [
{
"fieldKey": "customFieldPickTree",
"span": 12
}
]
}
]
}
}
}
Cancel-create
Cancel-create abort the creation of a new record, discarding any input without saving
How does it look?


How to add?
Example
Step1 Add standart action cancelCreate to corresponding VersionAwareResponseService. The interface displays "cancelCreate" as the default option.
@Override
public Actions<MyEntityPickPickDTO> getActions() {
return Actions.<MyEntityPickPickDTO>builder()
.create(crt -> crt.text("Add"))
.save(sv -> sv.text("Save"))
.cancelCreate(ccr -> ccr.text("Cancel").available(bc -> true))
.build();
}
{
"name": "myEntityPickPickPickTreePopup",
"title": "Action cancel-create",
"type": "PickTreePopup",
"bc": "myEntityPickPick",
"fields": [
{
"title": "Custom Field",
"key": "customField",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "input"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
],
"options": {
"actionGroups": {
"include": [
"save",
"cancel-create",
"create"
]
}
}
}
Step1 Add action cancel to corresponding VersionAwareResponseService with postAction.
@Override
public Actions<MyEntityPickPostActionPickDTO> getActions() {
return Actions.<MyEntityPickPostActionPickDTO>builder()
.create(crt -> crt.text("Add"))
.save(sv -> sv.text("Save"))
.action(act -> act
.action("cancel", "Cancel")
.invoker((bc, dto) -> {
return new ActionResultDTO<MyEntityPickPostActionPickDTO>().setAction(
PostAction.drillDown(
DrillDownType.INNER,
"/screen/myexample/view/myexampleinlinecreatelist"
));
})
.withoutAutoSaveBefore()
)
.delete(dlt -> dlt.text("Delete"))
.build();
}
Step2 Add button or group button to corresponding .widget.json.
{
"name": "myEntityPickPostActionPickPickTreePopup",
"title": "Action cancel-create PostAction",
"type": "PickTreePopup",
"bc": "myEntityPickPostActionPick",
"fields": [
{
"title": "Custom Field",
"key": "customField",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "input"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
],
"options": {
"actionGroups": {
"include": [
"cancel",
"create"
]
}
}
}
Info
Only for Inner Business Component see more Business Component
Step1 Add standart action cancelCreate to corresponding VersionAwareResponseService.
@Override
public Actions<MyEntityPickOnCancelPickDTO> getActions() {
return Actions.<MyEntityPickOnCancelPickDTO>builder()
.create(crt -> crt.text("Add"))
.save(sv -> sv.text("Save"))
.cancelCreate(ccr -> ccr.text("Cancel").available(bc -> true))
.delete(dlt -> dlt.text("Delete"))
.build();
}
@Override
public ActionResultDTO onCancel(BusinessComponent bc) {
return new ActionResultDTO<>().setAction(PostAction.drillDown(
DrillDownType.INNER,
"/screen/myexample/view/myexampleinlinecreatelist"
));
}
{
"name": "myEntityPickOnCancelPickPickTreePopup",
"title": "Action cancel-create OnCancel",
"type": "PickTreePopup",
"bc": "myEntityPickOnCancelPick",
"fields": [
{
"title": "Custom Field",
"key": "customField",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "input"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
}
],
"options": {
"actionGroups": {
"include": [
"cancel-create",
"create"
]
}
}
}
Additional properties
Node refresh
After an action (save, delete, cancel-create) the popup refreshes only the node the record belongs to, in the same way as a Tree widget:
- the row is updated from the response of the action or, if the response does not contain it, re-read with the request
?id.equals=<id>; - the row-meta of the row is requested again;
- if the record is not returned any more, the row is removed from the tree;
- the node is collapsed and its already loaded child records are forgotten, so they are loaded again on the next expand.
Info
Sibling records and parent records are not refreshed automatically. PostAction.refreshBC is not supported for a tree in this release: the root page is loaded again, but the expanded nodes and their already loaded child records stay as they are.
Customization of displayed columns
not applicable
Filtration
Basic
see more Fields
Filtration of the popup is a standard request. The rows that match the filter are returned by the backend without any hierarchy, and the popup decides how to display them, see Search modes.
The panel above the tree shows:
Clear N filter(s)— the number of applied filters and the possibility to reset them;Shown N— how many found records are currently displayed;More M— how many found records are not displayed yet, whereMis the number of found records minus the number of shown records.
Info
With the pagination mode nextAndPreviousWithCount the /count request is not performed after filtration. Instead of the number of found records an i icon is displayed with the tooltip "Load more and show count".
FullTextSearch
FullTextSearch - when the user types in the full text search input area, then widget filters the rows that match the search query.
see FullTextSearch
The result of a full text search is displayed in the same way as the result of filtration, see Search modes.
Personal filter group
not applicable
Filter group
not applicable
Search modes
The way the result of filtration and full text search is displayed is defined by options.tree.searchModes.
There are two modes:
collapse— search results and tree. The tree displays the found records together with the records that are required for navigation: the navigation path above every found record is restoredonFilterApplyNestLevellevels up. The user can navigate through the tree, expand and collapse branches, see the neighbouring records and load additional records.hide— search results only. The tree displays only the found records, everything else is hidden. The user works with the search result only and cannot navigate through the other records of the tree.
Both modes can be available at the same time. The first item of the searchModes array is the mode that is active when the filter is applied; the user switches between the available modes in the gear menu of the popup.
Restoring the path upwards
In collapse mode the records whose parents have not been loaded yet are placed under a pseudo node. The >... button loads the missing parents with the request ?id.equals=<parentId> and moves the records into the hierarchy. One click restores up to 2 levels of nesting, so for a deep hierarchy the button has to be pressed several times.
How does it look?



How to add?
Example
Step1 Add options.tree.searchModes to corresponding .widget.json.
The first item of the array is the mode that is active when the filter is applied.
{
"name": "myexampleTreePickListPopup",
"title": "Select Departments (PickTreePopup)",
"type": "PickTreePopup",
"bc": "myexamplePick",
"fields": [
{
"title": "Department",
"key": "department",
"type": "input"
},
{
"title": "Description",
"key": "description",
"type": "input"
},
{
"title": "Code",
"key": "code",
"type": "input"
},
{
"title": "Mnemonic",
"key": "mnemonic",
"type": "input"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
}
],
"options": {
"fullTextSearch": {
"enabled": true,
"placeholder": "Find by department"
}
}
}
Pagination
Pagination is the process of dividing content into separate, discrete pages, making it easier to navigate and consume large amounts of information.
see Pagination
The popup has no navigation arrows. Instead of the "next" arrow the last row of a node is the More button, which loads the next page of the node and appends it to the already loaded records. The limit selector (availableLimitsList) is moved to the gear menu of the popup.
The More button follows the same algorithm as the "next" arrow of the three pagination modes:
| Pagination mode | When More is displayed |
Counter |
|---|---|---|
nextAndPreviousWithHasNext |
hasNext returned by the backend is true |
not displayed |
nextAndPreviousWithCount |
count is greater than the number of already loaded records |
how many records are left to load |
nextAndPreviousSmart |
the backend returned more records than the limit of the node | not displayed |
see more Pagination modes
How does it look?

How to add?
Example
The list of available limits is displayed in the gear menu of the popup.
{
"name": "myEntityPickPickPickTreePopup",
"title": "PickTreePopup title",
"type": "PickTreePopup",
"bc": "myEntityPickPick",
"fields": [
{
"title": "Custom Field",
"key": "customField",
"type": "input"
},
{
"title": "id",
"key": "id",
"type": "text"
}
],
"options": {
"pagination": {
"availableLimitsList": [
1,
2,
3
]
}
}
}
The default number of the records requested for a node is defined by the page limit, see Page limit.
Export to Excel
not applicable
Multi-upload files
not applicable
Sorting
Sorting allows the user to sort the records by a column.
see Sorting
Sorting of the popup works inside a node: the records are sorted among the children of the same parent, the hierarchy itself is not changed. In all other respects sorting is standard.
Selection modes
A value is picked by a click on the row. What exactly the user is allowed to pick is defined by options.tree.selection:
node— only the nodes can be picked.leaf— only the leaves can be picked.nodeAndLeaf— both the nodes and the leaves can be picked.
The rows that cannot be picked are still displayed and can be expanded, so the user navigates through them to the required record.
Info
The More row is a pagination control, not a record, so it cannot be picked.
How does it look?



How to add?
Example
Add in options parameter tree to corresponding .widget.json.
{
"name": "myexampleTreePickListPopup",
"title": "Select Departments (PickTreePopup)",
"type": "PickTreePopup",
"bc": "myexamplePick",
"fields": [
{
"title": "Department",
"key": "department",
"type": "input"
},
{
"title": "Description",
"key": "description",
"type": "input"
},
{
"title": "Code",
"key": "code",
"type": "input"
},
{
"title": "Mnemonic",
"key": "mnemonic",
"type": "input"
},
{
"title": "Is Leaf",
"key": "isLeaf",
"type": "hidden"
},
{
"title": "Parent Id",
"key": "parentId",
"type": "hidden"
}
],
"options": {
"fullTextSearch": {
"enabled": true,
"placeholder": "Find by department"
}
}
}