Picker

API Reference: UI.Picker

Picker is a UI View that allows you to create a list from which the user can pick a single item. There are several usages for Picker.

  • add as a child View to layout

  • show Picker as a dialog, by calling the show() method

Using with Show

Following example below is showing the picker when user press to a button. Label text is updated after user press Done OR OK buttons.

TypeScript code blocks include examples of how to implement, override and components within the theme. You can create page with the UI Editor to make your page compatible with theming and then you can implement themable components programmatically. Once the page is created with the UI Editor, it generates a class under scripts/generated/pages. You can then extend that class with the following TypeScript classes.

TypeScript
JavaScript
TypeScript
import PageSampleDesign from 'generated/pages/pageSample';
import FlexLayout = require('sf-core/ui/flexlayout');
import Application = require('sf-core/application');
import Button = require('sf-core/ui/button');
import Label = require('sf-core/ui/label');
import Picker = require("sf-core/ui/picker");
import Screen = require('sf-core/device/screen');
//You should create new Page from UI-Editor and extend with it.
export default class Sample extends PageSampleDesign {
items: string[] = [ //Text values of the picker
"item 1",
"item 2",
"item 3",
"item 4",
"item 5"
];
index: number = 0;
lblSelection: Label;
btnPick: Button;
itemPicker: Picker;
constructor() {
super();
// Overrides super.onShow method
this.onShow = onShow.bind(this, this.onShow.bind(this));
// Overrides super.onLoad method
this.onLoad = onLoad.bind(this, this.onLoad.bind(this));
this.layout.flexDirection = FlexLayout.FlexDirection.COLUMN;
this.layout.justifyContent = FlexLayout.JustifyContent.FLEX_START;
this.layout.alignItems = FlexLayout.AlignItems.FLEX_START;
}
btnPickOnPress(): void {
console.log(`Showing the picker with index ${++this.index}`);
//@ts-ignore
this.itemPicker.show(this.okCallback.bind(this), this.cancelCallback.bind(this));
}
okCallback(params: { index: number }) {
console.log('ok clicked');
this.index = params.index;
this.lblSelection.text = this.items[params.index];
return params;
}
cancelCallback(): void {
console.log('cancel clicked');
}
}
/**
* @event onShow
* This event is called when a page appears on the screen (everytime).
* @param {function} superOnShow super onShow function
* @param {Object} parameters passed from Router.go function
*/
function onShow(superOnShow: () => void) {
const { headerBar, myMenu } = this;
superOnShow();
Application.statusBar.visible = false;
headerBar.visible = false;
}
/**
* @event onLoad
* This event is called once when page is created.
* @param {function} superOnLoad super onLoad function
*/
function onLoad(superOnLoad: () => void) {
superOnLoad();
this.itemPicker = new Picker({
items: this.items,
currentIndex: this.index //restores previous selection
});
this.lblSelection = new Label({
text: ""
});
this.layout.addChild(this.lblSelection, "lblSelection", ".sf-label", {
marginTop: 100,
height: 30,
width: 100,
marginBottom: null
});
this.btnPick = new Button({
text: "Pick item",
onPress: this.btnPickOnPress.bind(this)
});
this.layout.addChild(this.btnPick, "btnPick", ".sf-button", {
marginTop: 30,
width: Screen.width - (this.layout.paddingLeft + this.layout.paddingRight) ,
height: 70
});
}
JavaScript
const Page = require("sf-core/ui/page");
const extend = require("js-base/core/extend");
const Button = require('sf-core/ui/button');
const Label = require('sf-core/ui/label');
const Picker = require("sf-core/ui/picker");
const items = [ //Text values of the picker
"item 1",
"item 2",
"item 3",
"item 4",
"item 5"
];
var Page1 = extend(Page)(
function(_super) {
_super(this, {
onShow: function(params) {
Application.statusBar.visible = false;
this.headerBar.visible = false;
}
});
var index = 0;
const lblSelection = new Label({
text: "",
marginTop: 100,
height: 30
});
this.layout.addChild(lblSelection);
const btnPick = new Button({
marginTop: 30,
text: "Pick item",
onPress: btnPickOnPress.bind(this),
height: 70
});
this.layout.addChild(btnPick);
function btnPickOnPress() {
console.log(`Showing the picker with index ${index}`);
const itemPicker = new Picker({
items: items,
currentIndex: index //restores previous selection
});
itemPicker.show(okCallback, cancelCallback);
}
function okCallback(params) {
console.log('ok clicked');
index = params.index;
lblSelection.text = items[params.index];
}
function cancelCallback() {
console.log('cancel clicked');
}
}
);
module.exports = Page1;

Using as a view

It is also possible to add the picker inside the page layout as a view. It has usages such as in forms or multiple pickers at the same time. In that case, the developer needs to add the Cancel & OK buttons manually.

In the example below, the user is setting the expiration date for the credit card.

TypeScript
JavaScript
TypeScript
import PageSampleDesign from 'generated/pages/pageSample';
import FlexLayout = require('sf-core/ui/flexlayout');
import Application = require('sf-core/application');
import Button = require('sf-core/ui/button');
import Label = require('sf-core/ui/label');
import Picker = require("sf-core/ui/picker");
import System = require('sf-core/device/system');
import Screen = require('sf-core/device/screen');
import View = require('sf-core/ui/view');
import TextAlignment = require('sf-core/ui/textalignment');
import Dialog = require("sf-core/ui/dialog");
import componentContextPatch from '@smartface/contx/lib/smartface/componentContextPatch';
//You should create new Page from UI-Editor and extend with it.
export default class Sample extends PageSampleDesign {
lblExpirationDate: Label;
pickerDialog: Dialog;
flPickerDialog: FlexLayout;
flColumns: FlexLayout;
dialogLeft: FlexLayout;
lblMonth: Label;
monthPicker: Picker;
dialogRight: FlexLayout;
lblYear: Label;
yearPicker: Picker;
lineButtons: Button;
flDialogButtons: FlexLayout;
btnOK: Button;
btnCancel: Button;
defaultBlue: string = System.OS === "iOS" ? "#007AFF" : "#00BFFF";
borderColor: string = "#c7c7c7";
MONTHS: string[] = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
YEARS: string[] = ["2018", "2019", "2020", "2021", "2022", "2023"];
constructor() {
super();
// Overrides super.onShow method
this.onShow = onShow.bind(this, this.onShow.bind(this));
// Overrides super.onLoad method
this.onLoad = onLoad.bind(this, this.onLoad.bind(this));
this.layout.flexDirection = FlexLayout.FlexDirection.COLUMN;
this.layout.justifyContent = FlexLayout.JustifyContent.CENTER;
this.layout.alignItems = FlexLayout.AlignItems.CENTER;
}
showExpirationPicker(): void {
this.pickerDialog.show();
}
okCallback(params: { index: number }): void {
this.lblExpirationDate.text = `${this.MONTHS[this.monthPicker.currentIndex]}/${this.YEARS[this.yearPicker.currentIndex]}`;
this.pickerDialog.hide();
}
cancelCallback(): void {
this.pickerDialog.hide();
}
}
/**
* @event onShow
* This event is called when a page appears on the screen (everytime).
* @param {function} superOnShow super onShow function
* @param {Object} parameters passed from Router.go function
*/
function onShow(superOnShow: () => void) {
const { headerBar, myMenu } = this;
superOnShow();
Application.statusBar.visible = false;
headerBar.visible = false;
}
/**
* @event onLoad
* This event is called once when page is created.
* @param {function} superOnLoad super onLoad function
*/
function onLoad(superOnLoad: () => void) {
superOnLoad();
this.lblExpirationDate = new Label({
text: "Expire",
onTouchEnded: this.showExpirationPicker.bind(this),
});
this.layout.addChild(this.lblExpirationDate, "lblExpirationDate", ".sf-label", {
marginTop: 100,
height: 30,
width: 100,
textAlignment: "MIDCENTER"
});
this.pickerDialog = new Dialog();
componentContextPatch(this.pickerDialog, "pickerDialog");
componentContextPatch(this.pickerDialog.layout, "pickerDialogLayout");
this.pickerDialog.layout.dispatch({
type: "updateUserStyle",
userStyle: {
backgroundColor: "rgba(80, 0, 0, 0)",
flexProps: {
alignItems: "CENTER",
justifyContent: "CENTER",
flexDirection: "ROW"
}
}
});
this.flPickerDialog = new FlexLayout();
this.pickerDialog.layout.addChild(this.flPickerDialog, "flPickerDialog", ".sf-flexLayout", Object.assign({
height: 250,
width: Screen.width - 40,
backgroundColor: "#FFFFFF",
borderRadius: 0,
borderColor: this.borderColor,
borderWidth: 0
}, System.OS === "iOS" ? {
borderRadius: 10,
borderWidth: 1,
width: 300
} : {}));
this.flColumns = new FlexLayout();
this.flPickerDialog.addChild(this.flColumns, "flColumns", ".sf-flexLayout", {
flexProps: {
flexDirection: "ROW",
},
flexGrow: 1,
marginBottom: 15
});
this.dialogLeft = new FlexLayout({
flexGrow: 1
});
this.flColumns.addChild(this.dialogLeft, "dialogLeft", ".sf-flexLayout", {
width: null,
height: null,
flexGrow: 1
});
this.lblMonth = new Label({
text: "Month",
});
this.dialogLeft.addChild(this.lblMonth, "lblMonth", ".sf-label", {
width: null,
height: 30,
textAlignment: "MIDCENTER"
});
this.monthPicker = new Picker({
items: this.MONTHS
});
this.dialogLeft.addChild(this.monthPicker, "monthPicker", null, {
width: null,
flexGrow: 1
});
this.dialogRight = new FlexLayout({
flexGrow: 1
});
this.flColumns.addChild(this.dialogRight, "dialogRight", ".sf-flexLayout", {
width: null,
height: null,
flexGrow: 1
});
this.lblYear = new Label({
text: "Year",
height: 30,
textAlignment: TextAlignment.MIDCENTER
});
this.dialogRight.addChild(this.lblYear, "lblYear", ".sf-label", {
width: null,
height: 30,
textAlignment: "MIDCENTER"
});
this.yearPicker = new Picker({
items: this.YEARS,
flexGrow: 1
});
this.dialogRight.addChild(this.yearPicker, "yearPicker", null, {
width: null,
height: null,
flexGrow: 1
});
this.lineButtons = new View();
if (System.OS === "iOS")
this.flPickerDialog.addChild(this.lineButtons, "lineButtons", ".sf-view", {
width: null,
height: 1,
backgroundColor: this.borderColor
});
this.flDialogButtons = new FlexLayout();
this.flPickerDialog.addChild(this.flDialogButtons, "flDialogButtons", ".sf-flexLayout", Object.assign({
height: 40,
flexProps: {
flexDirection: "ROW_REVERSE",
justifyContent: "FLEX_START",
alignItems: "FLEX_START"
}
}, {});
this.btnOK = new Button({
text: System.OS === "iOS" ? "Done" : "OK",
onPress: this.okCallback.bind(this)
});
this.flDialogButtons.addChild(this.btnOK, "btnOK", ".sf-button", Object.assign({
width: null,
height: null,
backgroundColor: "rgba(0,0,0,0)",
textColor: this.defaultBlue,
flexGrow: NaN
}, System.OS === "iOS" ? { flexGrow: 1 } : {}));
this.btnCancel = new Button({
text: "Cancel",
onPress: this.cancelCallback.bind(this)
});
this.flDialogButtons.addChild(this.btnCancel, "btnCancel", ".sf-button", Object.assign({
width: null,
height: null,
backgroundColor: "rgba(0,0,0,0)",
textColor: this.defaultBlue,
flexGrow: NaN
}, System.OS === "iOS" ? { flexGrow: 1 } : {}));
this.pickerDialog.layout.applyLayout();
}
JavaScript
const Page = require("sf-core/ui/page");
const extend = require("js-base/core/extend");
const Button = require('sf-core/ui/button');
const Label = require('sf-core/ui/label');
const Picker = require("sf-core/ui/picker");
const Dialog = require("sf-core/ui/dialog");
const FlexLayout = require("sf-core/ui/flexlayout");
const Color = require('sf-core/ui/color');
const System = require('sf-core/device/system');
const Screen = require('sf-core/device/screen');
const View = require('sf-core/ui/view');
const TextAlignment = require('sf-core/ui/textalignment');
const defaultBlue = "iOS" ? Color.create("#007AFF") : Color.create("#00BFFF");
const borderColor = Color.create("#c7c7c7");
const MONTHS = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
const YEARS = ["2018", "2019", "2020", "2021", "2022", "2023"];
var Page1 = extend(Page)(
function(_super) {
_super(this, {
onShow: function(params) {
Application.statusBar.visible = false;
this.headerBar.visible = false;
}
});
const lblExpirationDate = new Label({
text: "Expire",
marginTop: 100,
height: 30,
onTouchEnded: showExpirationPicker,
textAlignment: TextAlignment.MIDCENTER
});
this.layout.addChild(lblExpirationDate);
const pickerDialog = new Dialog();
Object.assign(pickerDialog.layout, {
backgroundColor: Color.create(80, 0, 0, 0),
alignItems: FlexLayout.AlignItems.CENTER,
justifyContent: FlexLayout.JustifyContent.CENTER
});
const flPickerDialog = new FlexLayout({
height: 250,
width: System.OS === "iOS" ?
300 : Screen.width - 40,
backgroundColor: Color.WHITE,
borderRadius: System.OS === "iOS" ? 10 : 0,
borderColor: borderColor,
borderWidth: System.OS === "iOS" ? 1: 0
});
pickerDialog.layout.addChild(flPickerDialog);
const flColumns = new FlexLayout({
flexDirection: FlexLayout.FlexDirection.ROW,
flexGrow: 1,
marginBottom: 15
});
flPickerDialog.addChild(flColumns);
const dialogLeft = new FlexLayout({
flexGrow: 1
});
flColumns.addChild(dialogLeft);
const lblMonth = new Label({
text: "Month",
height: 30,
textAlignment: TextAlignment.MIDCENTER
});
dialogLeft.addChild(lblMonth);
const monthPicker = new Picker({
items: MONTHS,
flexGrow: 1
});
dialogLeft.addChild(monthPicker);
const dialogRight = new FlexLayout({
flexGrow: 1
});
flColumns.addChild(dialogRight);
const lblYear = new Label({
text: "Year",
height: 30,
textAlignment: TextAlignment.MIDCENTER
});
dialogRight.addChild(lblYear);
const yearPicker = new Picker({
items: YEARS,
flexGrow: 1
});
dialogRight.addChild(yearPicker);
const lineButtons = new View({
height: 1,
backgroundColor: borderColor
});
System.OS === "iOS" && flPickerDialog.addChild(lineButtons);
const flDialogButtons = new FlexLayout({
height: 40,
flexDirection: System.OS === "iOS" ?
FlexLayout.FlexDirection.ROW : FlexLayout.FlexDirection.ROW_REVERSE
});
flPickerDialog.addChild(flDialogButtons);
const btnOK = new Button({
text: System.OS === "iOS" ? "Done" : "OK",
backgroundColor: Color.TRANSPARENT,
textColor: defaultBlue,
flexGrow: System.OS === "iOS" ? 1 : NaN,
onPress: okCallback
});
flDialogButtons.addChild(btnOK);
const btnCancel = new Button({
text: "Cancel",
backgroundColor: Color.TRANSPARENT,
textColor: defaultBlue,
flexGrow: System.OS === "iOS" ? 1 : NaN,
onPress: cancelCallback
});
flDialogButtons.addChild(btnCancel);
pickerDialog.layout.applyLayout();
function showExpirationPicker() {
pickerDialog.show();
}
function okCallback(params) {
lblExpirationDate.text = `${MONTHS[monthPicker.currentIndex]}/${YEARS[yearPicker.currentIndex]}`;
pickerDialog.hide();
}
function cancelCallback() {
pickerDialog.hide();
}
}
);
module.exports = Page1;