Multipicker
Pickers provide a consistent user experience for selecting objects. Typically, you declare a Picker (.picker file) for a class or enumeration. This configures the captions, icons, searching, filtering, and paging of the picker dialog that displays when users need to select instances of the class or options within the enumeration. Multipicker and single picker controls can then reuse the Picker definition in portlet layouts.
A multipicker control allows you to pick many items.
The following example is a simplified version of the multipicker used to select contacts for a schedule item, and defined in ScheduleItemDetailEdit.layout
.
<Multipicker
caption="IDS_FOR"
captions="entityFullName"
icons="(image . (entity image))(data . mimeData)(type . mimeType)(icon . (entity icon))(default . "contact")"
items="(@ userParticipants)"
mode="ScheduleItem entityParticipants"
name="pickParticipantsLink"
order="(((@ entity lastName) . #t) ((@ entity firstName) . #t) ((@ entity) . #t))"
ref="mda:Entity"
/>
The multipicker control supports type-ahead, and has a Select button to open its picker dialog based on a reference to a picker (.picker file) declaration. It is bound to a collection attribute that points to an intersection class in a many-to-many relationship. It picks from a class through an intersection to create records in the intermediate intersection table.
The following illustrates the structure of a many-to-many association:
A - Class to which the containing Layout is bound.
B - Class you are picking.
AB - Intersection class between A and B.
a b - Association path between A and B through the intersection class AB.
a - Collection attribute on class A of type AB. The picker's collection is bound to this attribute.
For example:
The important properties are:
- Caption - displays on the picker dialog. This is the only property from the control that directly affects the dialog's display.
- Captions - the association path or expression to the captions for the selected items, usually displayed as chips. The path to the attribute to display is from the perspective of the intersection class. For example,
UserParticipations'entityFullName
>entityFullName
. - Icons - the association path or expression to the icons for the selected items, usually displayed as images in chips. The path to the attribute to display is from the perspective of the intersection class. For example,
(UserParticipation'entity) image)
>(entity image)
. - Items - the association path to the intersection class. For example,
(@ userParticipants)
. - Mode - when used with a multipicker, the mode declares the association from the picker class back to the class to which the multipicker's containing layout is bound, as well as the factory for creating new intersection instances. For example, when picking
UserPerson
instances to associate with aTask
through theUserParticipation
intersection class, we specify the mode's association touserParticipations
and the selection toTask
userParticipants
. - Order - the orderby statement for the selected items. The path to the attributes to sort by is from the perspective of the intersection class. For example,
(UserParticipation'entity) lastName) → ((@ entity lastName) . #t)
. - Ref - a reference to the .picker declaration. The type of the .picker must work with the type of the value property.
If you type in the list, based on the configuration above, you get:
and the selected items will look like:
Clicking the picker control's Select button displays the picker dialog as declared in the .picker file with the caption set by the picker control.
The drop-down list enables you to select additional items when required, and the pop-up picker dialog displays checkboxes rather than radio buttons (multiple selection versus single selection).
To learn more about the various properties of a multipicker control, see MultiPicker Control in the Model Description Language Reference.
Related APIs
Picker (.picker file) declaration for multi-item pickers
The picker declaration for multi-item picking is dependent on the modes. The approach for captions, icons, item creation behavior, order, and search is the same as with single-item pickers.
The following example is for the UserPerson
class.
<Picker
captions="fullNameFirstLast"
class="UserPerson"
icons="(image . image)(data . mimeData)(type . mimeType)(icon . icon)(default . "icon:person")"
order="(((@ firstName) . #t) ((@ lastName) . #t) ((@) . #t))"
search="fullTextSearch"
/>
The mode declares the association from the picker class back to the class and attribute for which the items are being picked. There may be many modes configured for multipicking; possibly as many modes as there are outgoing many-to-many associations from the picker class.
The properties for a mode used for multi picking are:
- Association - the association path from the item being picked to the intersection class. For example,
userParticipations
. - Factory - the new item factory event for new intersection instances,
<class> <event>
or<event>
if the event is on the picker class. The typical configuration is<class> <event>
. For example,UserParticipation create
. - Name - the picker mode name. It should be something meaningful from the other side of the association. It defaults to the selection, which should usually make sense. For example,
Task userParticipants
. - Selection - the class name and association attribute name from the other side of this many-to-many association. For example,
Task
userParticipants
.
The following example is for the Task
userParticipants
mode of the UserPerson
class picker.
<Mode
assoc="userParticipations"
factory="UserParticipation create"
name="Task userParticipants"
selection="Task userParticipants"
/>
Learn more about the various properties of a .picker declaration in the Model Description Language Reference.
Creating new items
When either dialog
or addEvent
are defined, an Add button will be added to the UI that allows users to create items of the same type as the current picker. addEvent
will take priority as the custom Scheme event handler, where this
is the current picker mda.Controller and (controller'isPicker)
returns #t
. If the script returns #f
or addEvent
is not defined, the *.dialog
file defined in the dialog will be used to launch the create dialog. If the script or dialog action returns a created model, it should be an instance of the same type as the originating picker. If the script returns #t
, dialog
will not be pursued further. The created model will be automatically added to the selection.
Examples
<Picker addEvent="`(mda:entity-show-add-popup this () () this)" .../>
<Picker addEvent="`(mda:entity-show-add-popup this () () this)" ... dialog="mda:PersonCreate" .../>
<Picker dialog="mda:PersonCreate" .../>
The create button will be suppressed during nested cases within the picker. In addition, it can be suppressed on a per-case basis. From the openPickerDialog
API call, set isNew/creating #f
. From the createPickerDialog
API set isNew/creating #f
on the controller. If the model is not creatable, for example, due to privilege, it may also be hidden.
New Item option for pickers in NexJ Studio
As of the NexJ CRM 9.7 release, the ability to configure the New Item option for pickers has been added to the picker UI editor in NexJ Studio (previously, and in 9.6.1.0, it was only supported through direct editing of the source code):
addEvent
This attribute provides an S-expression for custom behavior when the Add button is clicked.SCHEME@example `(mda:entity-show-add-popup this () () this)
dialog
The name of the dialog used to create new entries when the Add button is clicked (dependent on theaddEvent
definition).
The following example shows the Dialog and Add Event fields in the UI editor in NexJ Studio. The Where Clause and Order fields have also been converted into Scheme editors for consistency.
Scheme scripting in pickers
An initialization script can be added into a Picker (.picker file) to execute a scheme expression whenever the picker opens. This can be used to specify business logic in pickers and works the same as scripts in .dialog, .layout, .application files, where this
is the current picker mda.Controller.
The script will run when the picker is:
- Opened from a picker control
- Used in filters
- Opened via a script (openPickerDialog method described in UX Scripting)
To learn more about scripting and using Scheme, see Scripting and Client-side expressions.
Other considerations
Advanced picker (.picker file) declaration
Picker declarations may also specify filter and table controls that will be used in the picker dialog. These controls will be shown in the picker dialogs for both single pickers and multipickers.
The Filter control can be used to further refine the selection and has the same configuration as the filter in a layout.
The Table control overrides the generated picker table allowing it to show different columns containing the desired data and has the same configuration as the table in a layout.
The following code example shows a UserPerson
picker declaration with both a filter and table specified:
<Picker captions="fullNameFirstLast" class="UserPerson" icons="(image . image)(data . mimeData)(type . mimeType)(icon . icon)(default . "user")" order="(((@ firstName) . #t) ((@ lastName) . #t) ((@) . #t))" search="fullTextSearch"/>
<Filter name="filter"/>
<Table name="tblUserPerson" rows="(@)">
<Column caption="ids.icon" icons="(image . image)(data . mimeData)(type . mimeType)(icon . icon)(default . "user")" length="10" name="colIcon"/>
<Column caption="IDS_NAME" length="80" name="colName" values="fullName"/>
<Column caption="idsc.Position.caption" length="50" name="colPosition" values="position"/>
</Table>
</Picker>
Using pickers in filters
In addition to being used in picker and multipicker controls, pickers may be referenced in Filter Fields to provide picker capabilities for filtering lists.
Using pickers in Script
Pickers may also be used in Script. The openPickerDialog method on the controller API allows you to call a pre-defined picker from Script.
The following code enables a user to pick a number of participants in a conversation and then continuing processing based on the selection.
(define conversation (@ model item : (parameter'index)))
(define participants
(@ openPickerDialog :
"mda:ConversationParticipantPicker"
(: where `(not (in? (@) ,(map (lambda (p) (p'entity)) (conversation'activeParticipants)))))
(: factory '(ConversationParticipant createConversationParticipant))
(: values "entity")
(: parameter (list (: conversation conversation)))
)
)
(unless (null? participants)
...
openPickerDialog
also supports generic pickers. This creates a default picker for a class without the use of a pre-defined .picker file. The method supports both single and multi-picker modes. This is an experimental feature.
openPickerDialog
method in Scheme code, you must provide the definition for the picker in the meta/pickers/mda/
directory. You do not need to provide this definition when you define the picker directly in the metadata.
Custom pickers
Custom pickers are used infrequently. If the picking requirements are very specialized, there are ways to build a custom control in Application Foundation Layers (AFL). This information is not covered here, but an example can be seen in the finance-ai service.
Related links
- Working with pickers (in the Learning Center)
- MultiPicker Control and Picker file information (in the Model Description Language Reference)