Recipe: pick a partner in a form
This recipe is built on the LaravelUi5 SDK. The SDK ships the picker, its scopes and its gates, so the recipe only has to call it. Reading the docs is free; installing the SDK needs a licence.
A form needs a person: the responsible colleague on an order, the contact on a visit. The SDK's Partners app ships a partner picker for exactly this, and any app on the host can open it. The code below is the pattern the shipped Settings app uses for its partner fields.
1. The field
A pick-only input: the magnifier opens the picker, typing is blocked, the field shows the chosen name.
<Label text="Responsible" required="true" />
<Input
value="{form>/responsibleName}"
showValueHelp="true"
valueHelpOnly="true"
valueHelpRequest=".onPickResponsible"
placeholder="Pick a colleague"
/>valueHelpOnly is deprecated as of UI5 1.119 and still the only single-control pick-only input in sap.m. The shipped apps keep it on purpose; the alternative is an input plus a separate button.
2. The call
The handler opens the picker by name and scope, and awaits the selection as a promise:
import Controller from "sap/ui/core/mvc/Controller";
import JSONModel from "sap/ui/model/json/JSONModel";
import MessageBox from "sap/m/MessageBox";
import LaravelUi5 from "com/laravelui5/core/LaravelUi5";
interface ValueHelpSelection { key: string | number; text: string }
export default class OrderForm extends Controller {
public async onPickResponsible(): Promise<void> {
try {
const selection = await LaravelUi5.openValueHelp({
namespace: "com.laravelui5.partners.valuehelp.partners",
scope: "colleagues",
mode: "single",
});
if (!selection || selection.length === 0) {
return; // null: cancelled; []: confirmed without a pick
}
const picked = selection[0] as ValueHelpSelection;
const form = this.getView()!.getModel("form") as JSONModel;
form.setProperty("/responsibleId", Number(picked.key));
form.setProperty("/responsibleName", picked.text);
} catch (error: unknown) {
// A denied open arrives here, as does opening a second picker while one is open.
MessageBox.error(error instanceof Error ? error.message : String(error));
}
}
}The scope is the only thing the caller chooses. colleagues resolves on the server to the persons employed by the acting user's own organization; the client sends no filter. The Partners app ships two scopes on this picker, colleagues and userAttached (partners with a login). The call works inside the SDK shell; on Core without the shell it rejects.
3. Who may open it
Two gates decide, both on the server:
| Gate | On | In the shipped roles |
|---|---|---|
| Open | the picker's #[Access] (ability partnerPicker) | LocalAdmin |
| Read | the colleagues set's #[Read] (ability readColleagues) | LocalAdmin |
Browsing people is a key-user capability, so a user without the role gets a denial in the catch branch. Grant the role, or open a scope your users may read. Which gate does what, and why the read gate is the one that matters, is on value helps.
4. Saving the pick
The form now holds responsibleId. It goes to the server like any other field, through a Ui5Action, and the action's form request validates it again: the key came from the client, so the server does not take it on trust.
Where to go next
- Your own picker, or your own scope on this one: value helps, sections Writing one and Contributing a scope.
- How the partner model behind the picker works: partners.