Create and Filter patterns

The FormKit API includes a set of UITableViewCells that should be used in the Fiori Design Language to construct table views for creating or editing business objects, or to build filter controls. Each cell implements the FUIFormCell protocol and invokes an optional onChangeHandler closure to handle value changes.

FormKit cells are used in Filter and Create Floorplans.

FormKit Image

Interface

All cells in FormKit implement the FUIFormCell protocol. FUIFormCell is generic for its value property, and has an associatedtype: ValueType, that allows the value to be accessed with type safety.

FUITitleFormCell - displays the title of the form. The cell can be marked as editable to allow user editing of the title (for example, the “Work Request” cell in the above image):

    let cell = tableView.dequeueReusableCell(withIdentifier: FUITitleFormCell.reuseIdentifier, for: indexPath) as! FUITitleFormCell
    cell.value = "Work Request"
    cell.isEditable = false
    return cell

FUINoteFormCell - the user can enter notes in the cell (for example, the cell between “Work Request” and “Request ID” in the above image):

    let cell = tableView.dequeueReusableCell(withIdentifier: FUINoteFormCell.reuseIdentifier, for: indexPath) as! FUINoteFormCell
    cell.placeholder.text = "Description"
    cell.value = self.noteText
    cell.onChangeHandler = { [unowned self] newValue in
        self.noteText = newValue
    }
    return cell

FUIKeyValueFormCell - the user can enter text in the cell:

Key Value Form Cell

    let cell = tableView.dequeueReusableCell(withIdentifier: FUIKeyValueFormCell.reuseIdentifier, for: indexPath) as! FUIKeyValueFormCell
    cell.keyName = "Note"
    cell.placeholder.text = "Description"
    cell.value = myObject.descriptionText1
    cell.isTrackingLiveChanges = true
    cell.isEditable = false
    cell.onChangeHandler = { [unowned myObject] newValue in
        myObject.descriptionText1 = newValue
    }
    return cell

FUIFilterFormCell - allow users to select one or multiple values from a value set:

Filter Form Cell

    let cell = tableView.dequeueReusableCell(withIdentifier: FUIFilterFormCell.reuseIdentifier, for: indexPath) as! FUIFilterFormCell
    cell.valueOptions = buttonTitles.flatMap { $0.map { $0.value }}
    cell.keyName = "Sort By"
    cell.value = self.selectedValue
    cell.allowsMultipleSelection = true
    cell.allowsEmptySelection = false
    cell.onChangeHandler = { [unowned self] newValue in
        self.selectedValue = newValue
    }
    return cell

FUIListPickerFormCell - provides a key/value pair that displays the key and value of the cell. For single selection, set its allowsMultipleSelection property to false:

List Picker Form Cell Single Selectable

    var selectedValue: [Int] = [0]

        // A property cell with list picker
        let cell = tableView.dequeueReusableCell(withIdentifier: FUIListPickerFormCell.reuseIdentifier, for: indexPath) as! FUIListPickerFormCell
        cell.keyName = "Work Group"
        cell.value = selectedValue
        cell.valueOptions = ["Construction", "Repair", "Engineering", "Vendor"]
        cell.allowsMultipleSelection = false
        cell.valueLabel.text = descriptionForSelectedStrings(cell.valueOptions, at: selectedValue)
        cell.onChangeHandler = { [unowned self] newValue in
            self.selectedValue = newValue
        }
        return cell

When this cell is selected, a table view displays the available options for the user to choose:

List Picker Form Cell Single Selectable

A FUIListPickerFormCell can also be set as multiple selectable in the app by setting its allowsMultipleSelection property to true, as follows in the UITableViewController:

List Picker Form Cell Multiple Selectable Table

    let valueOptions12 = ["One", "Two", "Three", "Four", "Five", "Six", "Seven"]
    var propValue12 = [1, 3, 6]

    //...

        // A property cell with list picker
        let cell = tableView.dequeueReusableCell(withIdentifier: FUIListPickerFormCell.reuseIdentifier, for: indexPath) as! FUIListPickerFormCell
        cell.keyName = "Choose Multiple"
        cell.value = propValue12
        cell.valueOptions = valueOptions12

        // Developer is responsible for setting the text for the valueTextField of the FUIListPickerFormCell.
        // Here, function descriptionForSelectedStrings just returns the
        // comma separated selected string.
        cell.valueLabel.text = descriptionForSelectedStrings(valueOptions12, at: propValue12)
        cell.allowsMultipleSelection = true
        cell.listPicker.prompt = "Please select multiple items"
        cell.onChangeHandler = { [unowned self] newValue in
            self.propValue12 = newValue
        }

        return cell

List Picker Form Cell Multiple Select Cell

When the cell is tapped, a multiple select table with specified optional values is displayed:

List Picker Form Cell Multiple Select Table

A developer could customize the cells displayed in the selection table by setting the dataSource property of the listPicker property of the FUIListPickerFormCell, as described below:

      let propKey11 = "List Picker with Object Cells"
      var propValue11: [Int] = []

      // ObjectCellListPickerDataSource implements ListPickerDataSource and ListPickerSearchResultsUpdating
      let listPickerDataSource11 = ObjectCellListPickerDataSource(40)

      // ...


          // A FUIListPickerFormCell with FUIObjectTableViewCell
          let cell = tableView.dequeueReusableCell(withIdentifier: FUIListPickerFormCell.reuseIdentifier, for: indexPath) as! FUIListPickerFormCell

          cell.keyName = propKey11
          cell.value = propValue11
          cell.valueLabel.text = listPickerDataSource11.descriptionForSelectedItems(at: propValue11)

          cell.listPicker.dataSource = listPickerDataSource11
          cell.listPicker.searchResultsUpdating = listPickerDataSource11
          cell.listPicker.prompt = "Please select multiple items"
          cell.listPicker.register(FUIObjectTableViewCell.self, forCellReuseIdentifier: FUIObjectTableViewCell.reuseIdentifier)
          cell.allowsMultipleSelection = true
          cell.allowsEmptySelection = true
          cell.onChangeHandler = { [unowned self] newValue in
              self.propValue11 = newValue
          }

          return cell

When the cell is tapped, a multiple select table with FUIObjectTableViewCell is displayed:

List Picker Form Cell Object Cell Table

A search bar could be added to the FUIListPickerFormCell in the selection table view by setting isSearchEnabled, dataSource and listPickerResultsUpdating. Optionally, a barcode scanner could be added to the search bar by setting the isBarcodeScannerEnabled property of the searchBar property, as follows:

    let propKey7 = "Choose Multiple"
    var propValue7: [Int] = []
    let listPickerDataSource7 = StringListPickerDataSource(options: ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"])

    // ...

        let cell = tableView.dequeueReusableCell(withIdentifier: FUIListPickerFormCell.reuseIdentifier, for: indexPath) as! FUIListPickerFormCell

        cell.keyName = propKey7
        cell.value = propValue7

        cell.allowsMultipleSelection = true
        cell.allowsEmptySelection = false
        cell.valueLabel.text = descriptionForSelectedStrings(cell.valueOptions, at: propValue7)

        cell.listPicker.dataSource = listPickerDataSource7
        cell.listPicker.searchResultsUpdating = listPickerDataSource7
        cell.listPicker.prompt = "Please select multiple items"
        cell.listPicker.isSearchEnabled = true
        cell.onChangeHandler = { [unowned self] newValue in
            self.propValue7 = newValue
        }

        cell.listPicker.searchBar?.isBarcodeScannerEnabled = true
        cell.listPicker.searchBar?.barcodeScanner?.scanMode = .EAN_UPC
        cell.listPicker.searchBar?.barcodeScanner?.scanResultTransformer = { (scanString) -> String in
            return self.transformStringToSearchBar(scanResultString: scanString)
        }

        return cell

List Picker Form Cell with Search Bar

When the cell is tapped, the multiple selection table is shown with a search bar under the navigation bar.

List Picker Form Cell Object Cell Table

When the user starts typing in the search bar, the displayed list is filtered.

List Picker Form Cell Table with Active Search Bar

When the barcode scanner icon is tapped, the barcode scan view is displayed. Note that the barcode scanner icon is not displayed when the device does not support a camera, for example, when it’s running on a simulator. Also, the icon is not displayed when the search bar is active.

List Picker Form Cell Barcode Scan

FUIDatePickerFormCell - provides a key/value pair that displays a key and a date as the property value. When this cell is selected, a UIDatePicker displays to allow the user to select a date. The app can provide a DateFormatter to customize how the date displays:

Date Picker Form Cell

    var propValue4: Date = Date()

    // ...

        let cell = tableView.dequeueReusableCell(withIdentifier: FUIDatePickerFormCell.reuseIdentifier, for: indexPath) as! FUIDatePickerFormCell
        cell.key = "Appointment Date"
        cell.value = propValue4
        cell.onChangeHandler = { [unowned self] newValue in
            self.propValue4 = newValue
        }
        return cell

FUIDurationPickerFormCell - provides a key/value pair that displays a key and a TimeInterval as the property value. When this cell is selected, a UIDatePicker displays to allow the user to select a duration. The app can provide a text formatter to customize how the duration displays (for example, the formatter by default is “%d Hrs %d Min”):

Duration Picker Form Cell

    var propValue10: TimeInterval = 3900

    // ...

        let cell = tableView.dequeueReusableCell(withIdentifier: FUIDurationPickerFormCell.reuseIdentifier, for: indexPath) as! FUIDurationPickerFormCell
        cell.keyName = "Duration"
        cell.value = propValue10
        cell.onChangeHandler = { [unowned self] newValue in
            self.propValue10 = newValue
        }
        return cell   

FUIValuePickerFormCell - provides a key/value pair that displays a key and a String as the property value. When this cell is selected, a UIPickerView displays to allow the user to select a value:

Value Picker Form Cell

    let priceTitles = [[5: "5"], [10: "10"], [15: "15"], [20: "20"], [25: "25"]]

    // ...

        let cell = tableView.dequeueReusableCell(withIdentifier: FUIValuePickerFormCell.reuseIdentifier, for: indexPath) as! FUIValuePickerFormCell
        cell.keyName = "Maximum Price"
        cell.valueOptions = priceTitles.compactMap { $0.first?.value }
        cell.value = priceTitles.index { $0.first!.key == self.myObject.price }!

        // MARK:  implement an `onChangeHandler`
        cell.onChangeHandler = { [unowned self] newValue in
            self.myObject.price = self.priceTitles[newValue].first!.key
        }

        return cell

FUISwitchFormCell - the property for this cell is a boolean value that uses a standard UISwitch to display the value. The user can change the value by tapping the switch:

Switch Form Cell

    var isConfirmed = false

    // ...

        // A FUISwitchFormCell
        let cell = tableView.dequeueReusableCell(withIdentifier: FUISwitchFormCell.reuseIdentifier, for: indexPath) as! FUISwitchFormCell
        cell.key = "Confirmed"
        cell.value = isConfirmed
        cell.onChangeHandler = { [unowned self] newValue in
            self.isConfirmed = newValue
        }
        return cell

FUISliderFormCell - the property for this cell is a float value. Users select a value from a continuous range using the slider. Also set a unit if needed (default unit is “mi”):

Slider Form Cell

    let cell = tableView.dequeueReusableCell(withIdentifier: FUISliderFormCell.reuseIdentifier, for: indexPath) as! FUISliderFormCell
    cell.keyName = "Distance"
    cell.minimumValue = 0
    cell.maximumValue = 30
    cell.value = myObject.distance

    // MARK:  implement an `onChangeHandler`
    cell.onChangeHandler = { newValue in
        self.myObject.distance = newValue
    }

    return cell

FUIAttachmentFormCell - a cell to which photos or selected files can be added as attachments:

        let cell = tableView.dequeueReusableCell(withIdentifier: FUIAttachmentsFormCell.reuseIdentifier, for: indexPath) as! FUIAttachmentsFormCell
        cell.attachmentsController.delegate = self
        cell.attachmentsController.dataSource = self
        cell.attachmentsController.reloadData()
        cell.attachmentsController.maxItems = 8
        return cell

The application needs to add the following to its info.plist in order to access the camera and photo library:

    <key>NSCameraUsageDescription</key>
    <string>Please permit access to camera</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>Please permit access to photo library</string>

Each UITableViewController is allowed to have only one FUIAttachmentFormCell.

FUISegmentedControlFormCell - A type of FUIPropertyFormCell, representing a key/value pair of the cell. The user can select a value by clicking the button. The cell is editable by default and can be set to isEditable to disable user interaction.

Slider Form Cell

    var selectedItemIndex = 1

    // ...

        let cell = tableView.dequeueReusableCell(withIdentifier: FUISegmentedControlFormCell.reuseIdentifier, for: indexPath) as! FUISegmentedControlFormCell

        cell.valueOptions = ["Low", "Medium", "High"]
        cell.keyName = "Key"
        cell.value = selectedItemIndex

        cell.onChangeHandler = { [unowned self] newValue in
            self.selectedItemIndex = newValue
        }
        return cell

Usage

Implement a UITableViewController that hosts the cells and constructs a Create Window view similar to the one in the example above:

The UITableViewController must subclass FUIFormTableViewController.

    class MyFormTableViewController: FormTableViewController {
    ...
    }

Register the reuse identifiers of all needed FUIFormCells, and enable auto-dimension row height calculation.

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(FUITitleFormCell.self, forCellReuseIdentifier: FUITitleFormCell.reuseIdentifier)
        ...
        self.tableView.estimatedRowHeight = 200
        self.tableView.rowHeight = UITableViewAutomaticDimension
    }

Reuse the registered cells in tableView(_:cellForRowAt:), and bind the form data to the cell views:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // An simple key-value property cell
        let cell = tableView.dequeueReusableCell(withIdentifier: FUISimplePropertyFormCell.reuseIdentifier, for: indexPath) as! FUISimplePropertyFormCell
        cell.key = "Location"
        cell.value = "127 Higgins Drive, Palo Alto"
        // MARK:  Implement `onChangeHandler` closure to process the new value entered by the user
        cell.onChangeHandler = { newValue in
            myObject.value = newValue
        }
        return cell
    }
  • This protocol is to be implemented by all the form cells except FUIAttachmentsFormCell, including:

    • FUIDatePickerFormCell
    • FUIDurationPickerFormCell
    • FUIFilterFormCell
    • FUIKeyValueFormCell
    • FUIListPickerFormCell
    • FUINoteFormCell
    • FUISegmentedControlFormCell
    • FUISimplePropertyFormCell
    • FUISliderFormCell
    • FUIValuePickerFormCell
    • FUISwitchFormCell
    • FUITitleFormCell

    Note

    All FUIFormCell implementations listed above have the selectionStyle properties set to .none. Therefore, developers will not be able to set highlighted on these cells.

    See more

    Declaration

    Swift

    public protocol FUIFormCell : AnyObject, FUIInlineValidation
  • When FUIFormCells are to be used in an application, application’s implementation of UITableViewController that hosts these FUIFormCells must be a subclass of this FUIFormTableViewController. FUIFormTableViewController hides all the complications and interactions for handling all different types of FUIFormCells.

    Application’s implementation of the UITableViewController needs to only implement the following functions:

    
     class FormCellTestTVC: FUIFormTableViewController {
        override func viewDidLoad() {
            // MUST: Call viewDidLoad function of super class.
            super.viewDidLoad()
    
            // Register FUIFormCells that will be used
            self.tableView.register(FUITitleFormCell.self, forCellReuseIdentifier: FUITitleFormCell.reuseIdentifier)
            ...
        }
    
        override func numberOfSections(in tableView: UITableView) -> Int {
            // Return how many section in the table
            return ...
        }
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            // Return number of rows in each section
            ...
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            // Return the cell to be used at the IndexPath specified
            let cell = tableView.dequeueReusableCell(withIdentifier: FUITitleFormCell.reuseIdentifier, for: indexPath) as! FUITitleFormCell
            cell.value = "Work Request"
    
            cell.isEditable = true
            // MARK:  implement onChangeHandler
            cell.onChangeHandler = { newValue in
                myObject.title = newValue
            }
            return cell
        }
    
    

    In addition, if there are some other actions on the table view, it is required that the action functions should also call function endEditing of the table view with the force parameter to true so that all editing cells have its onChangeHandler called. For example, the function didSaveTapped below is the action when the “Save” button tapped:

        @IBAction func didSaveTapped(_ sender: AnyObject) {
            self.tableView.endEditing(true)
    
            // save object ...
        }
    
    
    See more

    Declaration

    Swift

    open class FUIFormTableViewController : UITableViewController, FUIFormCellResponderDelegate, FUIFormCellNavigationDelegate
  • The reusable UI component implemented as an UITableViewCell to allow user to enter a value, using a UITextField.

    FUITitleFormCell

    The developer should set the following properties on the cell, in their implementation of UITableViewDataSource cellForRow(at:) function:

    • value: The value of the property, as String

    And an onChangeHandler:

    • onChangeHandler: a handler closure, which is invoked on changes to the value

    Optionally, the developer may provide:

    • isEditable: Indicates if the cell’s value may be modified. Defaults to true.

    Color settings:

    Setting tintColor for valueTextField for a state using setTintColor(_:for:) api. Currently disabled and normal are supported.

     cell.setTintColor(UIColor.red, for: .normal)
    

    Remark

    The font-color attribute will be overridden by tint-color-disabled attribute when cell is switched to disabled state. DO NOT set textColor for valueTextField when cell is in disabled state!

    The following is an example of usage in an application UITableViewController:

    Important

    The app’s UITableViewController must subclass FUIFormTableViewController
    override func viewDidLoad() {
       super.viewDidLoad()
       self.tableView.register(FUITitleFormCell.self, forCellReuseIdentifier: FUITitleFormCell.reuseIdentifier)
       // ...
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
       let cell = tableView.dequeueReusableCell(withIdentifier: FUITitleFormCell.reuseIdentifier, for: indexPath) as! FUITitleFormCell
    
       cell.value = myObject.title
       cell.isEditable = true
    
       // MARK:  implement onChangeHandler
       cell.onChangeHandler = { newValue in
            myObject.title = newValue
       }
       return cell
    }
    

    ## Theming

    Supported TableViewCell class paths:

     fdlFUITitleFormCell {}
    

    Supported TableViewCell attributes:

     background-color (Color)
     background-color-disabled (Color)
     background-color-readonly (Color)
    

    Supported TextField class paths:

     fdlFUITitleFormCell_valueTextField
    

    Supported TextField properties:

     font-color: Color;
     font-color-disabled: Color;
     font-color-readonly: Color;
     placeholder-color: Color;
     font-style: UIFontTextStyle;
     font-style-disabled: UIFontTextStyle;
     font-style-readonly: UIFontTextStyle;
    
    See more

    Declaration

    Swift

    open class FUITitleFormCell : FUIInlineValidationUIControlTintTableViewCell, FUIFormCell, UITextFieldDelegate, FUIStateReadOnly
  • The reusable UI component implemented as an UITableViewCell to display or edit a key-value pair property.

    The developer should set the following properties on the cell, in their implementation of UITableViewDataSource cellForRow(at:) function:

    • keyName: The key name of the property.
    • value: The value of the property.

    And an onChangeHandler:

    • onChangeHandler: a handler closure, which is invoked on changes to the value

    Optionally, the developer may provide

    • isEditable: Indicates if the cell’s value may be modified. Defaults to true.

    • isStacked: A boolean value to determine if the cell should use a stacked or linear layout. If the device’s accessibility settings font size is increased, the cell will force a stacked layout. By default, this property is set to true.

    • maxKeyWidth: The maximum width of the key with a linear layout - By default, the width is 115 for compact and 160 for regular. The set value must meet the minimum default threshold.

    • alternativeInputButton: An FUIButton that manages an alternative method to fill the textField.

    • isAlternativeInputEnabled: A Bool that shows or hides the alternativeInputButton. This button will be displayed if isAlternativeInputEnabled and isEditable are true.

    • isReadOnly: Indicates if the cell is read-only or not. The default is false.

    • isTrackingLiveChanges: Indicates if the onChangeHandler will be invoked for every letter entered. The default is false.

    • isCharCountEnabled: A Boolean value to enable a character counter and show the updated character count number during editing. The default is false.

    • maxTextLength: The maximum length of the text.

    • allowsBeyondLimit: A Boolean value to determine whether the user can continue to input text even after maxValueTextLength has been reached. If it is true, it will be in an error state with an error message and a semantic negative color when the text input exceeds maxTextLength. The default is false.

    • showsErrorInValidationMsg: A Boolean value to determine whether an error message will be shown in the validationMessage or in the errorView in the same layout as the hintView. The default is true.

    • hasError: A Boolean value to indicate if there is an error in the text input value. It will be in an error state with an error message and a semantic negative color if it is true. The default is false.

    Color settings:

    Manage the color of the control by setting the textColor and tintColor programmatically.

    The following is an example of usage in an application UITableViewController:

    Important

    The app’s UITableViewController must subclass FUIFormTableViewController
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(FUITextFieldFormCell.self, forCellReuseIdentifier: FUITextFieldFormCell.reuseIdentifier)
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: FUITextFieldFormCell.reuseIdentifier, for: indexPath) as! FUITextFieldFormCell
    
        cell.keyName = "Editable"
        cell.value = myObject.productName
    
        // MARK:  implement onChangeHandler
        cell.onChangeHandler = { newValue in
            myObject.productName = newValue
        }
    
        // MARK: Implement alternative input, i.e. use OCR to capture input
    
        cell.isAlternativeInputEnabled = true
        let inputImage = FUIIconLibrary.system.camera
        cell.alternativeInputButton.setImage(inputImage.withRenderingMode(.alwaysTemplate), for: .normal)
        cell.alternativeInputButton.didSelectHandler = { [weak self, weak cell] (button) in
    
            //Import SAPML to use OCR capability
            let textRecController = FUITextRecognitionViewController()
            textRecController.recognitionView.observationHandler = { [unowned textRecController] observations in
                let filteredObservations = <#filter out unwanted text#>
                textRecController.recognitionView.showTexts(for: filteredObservations)
                let areObservationsValid = <#filteredObservations meets desired criteria#>
                if areObservationsValid {
                    DispatchQueue.main.async {
                        cell?.value = filteredObservations.map { $0.value }.joined(separator:" ")
                    }
                    return true
                }
                return false
            }
    
            textRecController.onClose = {
                self?.dismiss(animated: true)
            }
            self?.present(UINavigationController(rootViewController: textRecController), animated: true)
        }
    
        return cell
     }
    

    ## Theming

    nuiClass:

     fdlFUITextFieldFormCell {}
    

    Supported TEXT class paths:

     fdlFUITextFieldFormCell_keyText {}
     fdlFUITextFieldFormCell_valueText {}
    

    Supported TEXT properties:

     font-color: Color;
     placeholder-color: Color;
     font-style: UIFontTextStyle;
    

    Supported BUTTON class paths:

     fdlFUITextFieldFormCell_alternativeInputButton {}
    

    Supported BUTTON properties:

     background-color: Color;
     font-color: Color;
    
    See more

    Declaration

    Swift

    open class FUITextFieldFormCell : FUIInlineValidationDrawingTableViewCell<FUITextFieldContentView>, FUIFormCell
    extension FUITextFieldFormCell: FUITintAttributesProvider
  • The reusable UI component implemented as an UITableViewCell to allow user enter notes.

    FUINoteFormCell

    This is the new implementation to replace the previous implementation of FUINoteFormCell. The cell height is automatically adjusted to allow the whole content to be displayed. However, the cell height is also limited to the height of the screen above the soft keyboard height.

    Developer could use to UITableViewDelegate‘s func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat to set a fixed height for the cell. Or, use minNumberOfLines and maxNumberOfLines properties to limit the cell height.

    The character counter can be enabled by setting isCharCountEnabled. It will show the updated the character count number during editing or has been entered. The message will be shown if the maxNoteTextLength reached. The user can continue input the text if allowsBeyondLimit is true. It will show the text input field in error state with an error message and a semantic negative color. If allowsBeyondLimit is false, it will auto-stop user input when maxNoteTextLength is reached.

    The application can validate the user input value and show error message by setting hasError and errorText. The text input field in error state with an error message and a semantic negative color. The error message can be shown in the validationMessage if showsErrorInValidationMsg is true. Otherwise, the error message will be shown in the errorView in the same layout as the hintView.

    Usage

    let cell = tableView.dequeueReusableCell(withIdentifier: FUINoteFormCell.reuseIdentifier) as! FUINoteFormCell
    cell.onChangeHandler = { [unowned self] newValue in
        self.noteText = newValue
    }
    cell.placeholder.text = "Enter Description"
    cell.value = noteText
    cell.isTrackingLiveChanges = true
    

    Theming

    Supported TEXT class paths:

       fdlFUINoteFormCell_valueText {}
       fdlFUINoteFormCell_placeholder {}
    

    Supported TEXT properties:

       font-color: Color;
       font-style: UIFontTextStyle;
    

    Supported TINTABLE class paths:

       fdlFUIKeyValueFormCell_valueText {}
    

    Supported TINTABLE properties:

       tint-color { -disabled }: Color;
       font-style { -disabled }: UIFontTextStyle;
    
    See more

    Declaration

  • A customized UITableViewCell, which contains a UILabel and a UITextView. It takes text as input.

    FUIKeyValueFormCell

    This is a new implementation to replace the previous implementation of FUIKeyValueFormCell. It has a keyName field and an editable value text field to let user entered the value for this property. This cell height is automatically adjusted to allow the whole content to be displayed. However, the cell height is also limited to the height of the screen above the soft keyboard height.

    Developer could use to UITableViewDelegate‘s func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat to set a fixed height for the cell.

    The character counter can be enabled by setting isCharCountEnabled. It will show the updated character count number during editing, or the number of characters that have been loaded from the back end. An error message will be shown if the maxNoteTextLength is reached. It will also show the text input field in error state and a semantic negative color. The user can continue to input text if allowsBeyondLimit is true. If allowsBeyondLimit is false, it will auto-stop user input when maxNoteTextLength is reached.

    The application can validate the user input value and show an error message by setting hasError and errorText. The text input field will be displayed in an error state with an error message and a semantic negative color. The error message can be shown in the validationMessage if showsErrorInValidationMsg is true. Otherwise, the error message will be shown in the errorView in the same layout as the hintView.

    Usage

    let cell = tableView.dequeueReusableCell(withIdentifier: FUIKeyValueFormCell.reuseIdentifier) as! FUIKeyValueFormCell
    cell.onChangeHandler = { [unowned self] newValue in
        print("value: \(newValue)")
        self.value = newValue
    }
    cell.keyName = "Project Title"
    cell.placeholder.text = "Please enter a title"
    cell.value = value
    cell.isTrackingLiveChanges = true
    return cell
    

    Theming

    Supported TEXT class paths:

    fdlFUIKeyValueFormCell_title {}
    fdlFUIKeyValueFormCell_valueText {}
    fdlFUIKeyValueFormCell_placeholder {}
    fdlFUIKeyValueFormCell_subtitle {}
    

    Supported TEXT properties:

    font-color: Color;
    font-style: UIFontTextStyle;
    

    Supported TINTABLE class paths:

    fdlFUIKeyValueFormCell_title {}
    fdlFUIKeyValueFormCell_valueText {}
    

    Supported TINTABLE properties:

    tint-color { -disabled }: Color;
    font-style { -disabled }: UIFontTextStyle;
    
    See more

    Declaration

    Swift

    open class FUIKeyValueFormCell : FUINoteFormCell
    extension FUIKeyValueFormCell: FUIPropertyFormCell
  • The reusable UI component implemented as an UITableViewCell to allow user to choose a boolean value using a switch for a property.

    FUISwitchFormCell

    The developer should set the following properties on the cell, in their implementation of UITableViewDataSource cellForRow(at:) function:

    • keyName: The key name of the property
    • value: The value of the property, as Bool
    • isEditable: Indicates if the cell’s value may be modified. Defaults to true.

    And, an onChangeHandler:

    • onChangeHandler: a handler closure, which is invoked on changes to the value

    The following is an example of usage in an application UITableViewController:

    Important

    The app’s UITableViewController must subclass FUIFormTableViewController
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(FUISwitchFormCell.self, forCellReuseIdentifier: FUISwitchFormCell.reuseIdentifier)
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: FUISwitchFormCell.reuseIdentifier, for: indexPath) as! FUISwitchFormCell
        cell.keyName = "Confirmed"
        cell.value = myObject.isConfirmed
        cell.onChangeHandler = { newValue in
            myObject.isConfirmed = newValue
        }
    
        return cell
    }
    

    Theming

    Supported style classes and attributes.

    fdlFUISwitchFormCell {
       // Table view cell related attributes.
       // ...
    }
    
    fdlFUISwitchFormCell_title {
       // Font attributes
       font { -style | -name | -size }
       font-color
    
       // Number of lines
       text-line-clamp
    
       // Text alignment
       text-align
    }
    
    fdlFUISwitchFormCell_switch {
       tint-color
       // Knob color
       thumb-color { -enabled-selected | -enabled-unselected | -disabled-selected | -disabled-unselected }
       // Track color
       track-color { -enabled-selected | -enabled-unselected | -disabled-selected | -disabled-unselected }
       // Border color
       border-color { -enabled-selected | -enabled-unselected | -disabled-selected | -disabled-unselected }
       // View opacity
       view-alpha { -enabled-selected | -enabled-unselected | -disabled-selected | -disabled-unselected }
    }
    

    Note: As of iOS SDK 9.0, the version of fdlFUISwitchFormCell_switch described above is preferable to the version of fdlFUISwitchFormCell_switch described below (to achieve maximum UX design compliance).

    fdlFUISwitchFormCell_switch {
       tint-color
       on-tint-color
    }
    
    See more

    Declaration

    Swift

    open class FUISwitchFormCell : FUIInlineValidationDrawingTableViewCell<FUISwitchFormView>
  • A customized UITableViewCell, which contains a UILabel, a UITextField and a UISlider. It allows users to select a single value from a continuous range of values.

    FUISliderFormCell

    The developer should set the following properties on the cell, in their implementation of UITableViewDataSource cellForRow(at:) function:

    • keyName: The key name of the property
    • value: The value of the property, as Float
    • minimumValue: The minimum value of the selection range.
    • maximumValue: The maximum value of the selection range.

    And an onChangeHandler:

    • onChangeHandler: a handler closure, which is invoked on changes to the value.

    Optionally, the developer may set:

    • unit: The unit of value. Default is mi.
    • isEditable: Indicates if the cell’s value may be modified. Defaults to true.

    Color setting:

    Setting text color of filter buttons for a state using setTintColor(_:for:) api. Currently .disabled and .normal are supported.

    cell.setTintColor(UIColor.red, for: .normal)
    

    The following is an example of usage in an application UITableViewController:

    Important

    The app’s UITableViewController must subclass FUIFormTableViewController
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(FUISliderFormCell, forCellReuseIdentifier: FUISliderFormCell.reuseIdentifier)
        // ...
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
        let cell = tableView.dequeueReusableCell(withIdentifier: FUISliderFormCell.reuseIdentifier, for: indexPath) as! FUISliderFormCell
        cell.keyName = "Distance"
        cell.minimumValue = 0
        cell.maximumValue = 30
        cell.value = myObject.distance
    
        // MARK:  implement an onChangeHandler
        cell.onChangeHandler = { [weak self] newValue in
            self.myObject.distance = newValue
        }
    
        return cell
    }
    

    Theming

    Supported style classes

    fdlFUISliderFormCell
    fdlFUISliderFormCell_keyLabel
    fdlFUISliderFormCell_valueTextField
    
    See more

    Declaration

    Swift

    @IBDesignable
    open class FUISliderFormCell : FUIInlineValidationTableViewCell, FUIPropertyFormCell
  • The reusable UI component implemented as a UITableViewCell, allowing a user to select range values from the slider, which can be controlled using a single thumb or double thumbs.

    The developer should set the following properties on the cell in their implementation of the UITableViewDataSource cellForRow(at:) function:

    • title: The key name of the property.
    • minimumValue: The minimum value of the slider.
    • maximumValue: The maximum value of the slider.

    And an onChangeHandler:

    • onChangeHandler: a handler closure, which is invoked on changes to the value

    Optionally, the developer may provide

    • isEditable: Indicates whether the cell’s value can be modified. The default is true.
    • lowerValue: The minimum value the user can select.
    • upperValue: The maximum value the user can select.
    • isRangeSelection: Determine the slider whether show one thumb or two thumbs. Default is true.
    • subtitle: the hint text.
    • interval: the minimum value of the slider as it changes. The default is 1.
    • isContinuous: whether value change events are generated any time. The default is true.

    The following is an example of usage in an application UITableViewController:

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(FUIRangeSliderFormCell.self, forCellReuseIdentifier: FUIRangeSliderFormCell.reuseIdentifier)
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: FUIRangeSliderFormCell.reuseIdentifier, for: indexPath) as! FUIRangeSliderFormCell
    
        cell.title = "Range Label"
        cell.maximumValue = 50
        cell.minimumValue = 10
        cell.subtitle = "Hint Text"
        cell.isEditable = true
        cell.upperValue = 40
        cell.lowerValue = 20
        cell.isRangeSelection = true
    
        // MARK:  implement onChangeHandler
        cell.onChangeHandler = { (lower, upper) in
            // ...
        }
    
        return cell
     }
    

    ## Theming

    nuiClass:

     fdlFUIRangeSliderFormCell {}
    

    Supported keyView:

     fdlFUIRangeSliderFormCell_keyText {
     font-color { -highlighted | -disabled } (Color)
     font-style { -highlighted | -disabled } (UIFont.TextStyle)
     }
    

    Supported slider:

     fdlFUIRangeSliderFormCell_slider {
     track-tint-color { -disabled } (Color);
     track-selection-color { -disabled } (Color);
     thumb-tint-color { -disabled } (Color);
     }
    

    Supported textfields:

     fdlFUIRangeSliderFormCell_textFields {
     font-color { -disabled } (Color)
     font-style { -disabled } (UIFont.TextStyle)
     border-color { -highlighted | -readonly } (Color)
     }
    

    Supported hintText:

     fdlFUIRangeSliderFormCell_hintText {
     font-color { -disabled } (Color)
     font-style { -disabled } (UIFont.TextStyle)
     }
    
    See more

    Declaration

    Swift

    open class FUIRangeSliderFormCell : FUIInlineValidationDrawingTableViewCell<FUIRangeSliderContentView>
  • A UITableViewCell subclass, which allows a user to view or select from a list of strings, using a Fiori-styled segmented control.

    FUISegmentedControlFormCell

    The value property of the cell is equal to the selectedSegmentIndex in the segmented control.

    Specifying the height for segments by setting segmentHeight api. By default it is set to nil which means segment will adjust its height to fit content.

    Color setting:

    Setting text color of buttons in the cell for a state using setButtonAttributes(_:for:) api. Currently disabled, normal and selected are supported.

    let attributes = FUISegmentedControlButtonAttributes()
    attributes.titleAttributes = ...
    attributes.borderColor = ...
    cell.setButtonAttributes(attributes, for: .normal)
    

    Code usage:

    // Optionally, create an array of value option to localized string mappings
    let buttonTitles: [[String: String]] = [["LO": "Low"], ["MED": "Medium"], ["HI": "High"]]
    
    // Register FUISegmentedControlFormCell in viewDidLoad() method in the controller.
    override func viewDidLoad() {
    super.viewDidLoad()
    self.tableView.register(FUISegmentedControlFormCell.self, forCellReuseIdentifier: FUISegmentedControlFormCell.reuseIdentifier)
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: FUISegmentedControlFormCell.reuseIdentifier, for: indexPath) as! FUISegmentedControlFormCell
    
    cell.valueOptions = buttonTitles.flatMap { $0.map { $0.value } }
    cell.keyName = "Priority"
    cell.value = myObject.priority  // String value in the valid options set: ["LO", "MED", "HI"]
    
    // MARK: implement onChangeHandler
    cell.onChangeHandler = { newValue in
    myObject.priority = buttonTitles[newValue].first!.key  // lookup valid String value, from the buttonTitles array
    }
    
    return cell
    }
    

    Theming

    Supported style classes

    fdlFUISegmentedControlFormCell
    fdlFUISegmentedControlFormCell_keyLabel
    
    See more

    Declaration

    Swift

    open class FUISegmentedControlFormCell : FUIInlineValidationDrawingTableViewCell<FUISegmentedControlFormView>
  • A UITableViewCell subclass, which allows a user to read or enter a set of values, using a grid of buttons. Commonly used for composing filters.

    FUIFilterFormCell

    The developer should set the following properties on the cell, in their implementation of UITableViewDataSource cellForRow(at:) function:

    • keyName: The key name of the property.
    • value: An array of the selected indexes in the control. Uses the same index as the valueOptions array.
    • `valueOptions: A String array, of titles for the buttons in the control

    And an onChangeHandler:

    • onChangeHandler: a handler closure, which is invoked on changes to the value

    Optionally, the developer may provide

    • allowsMultipleSelection: Indicates if multiple buttons may be selected simultaneously (true). If false, the control behaves in “radio” mode. Defaults to true.
    • allowsEmptySelection: Indicates if the control allows zero items to be selected (true). If false, then once a value has been selected by the developer or user, taps by the user on the last selected item will be ignored, instead of de-selecting the item. Defaults to true.
    • isEditable: Indicates if the cell’s value may be modified. Defaults to true.

    Color setting:

    Setting text color of filter buttons for a state using setTintColor(_:for:) api. Currently disabled, normal and selected are supported.

     cell.setTintColor(UIColor.red, for: .normal)
    

    The following is an example of usage in an application UITableViewController:

    Important

    The app’s UITableViewController must subclass FUIFormTableViewController
     // optionally, create an array of value option to localized string mappings
      let buttonTitles: [[String: String]] = [["radius": "Distance"], ["price": "Price"], ["rating": "Ratings"], ["avail": "Availability"]]
    
     // Register FUIFilterFormCell in viewDidLoad() method in the controller.
     override func viewDidLoad() {
         super.viewDidLoad()
         self.tableView.register(FUIFilterFormCell.self, forCellReuseIdentifier: FUIFilterFormCell.reuseIdentifier)
     }
    
     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
         let cell = tableView.dequeueReusableCell(withIdentifier: FUIFilterFormCell.reuseIdentifier, for: indexPath) as! FUIFilterFormCell
    
         cell.valueOptions = buttonTitles.flatMap { $0.map { $0.value }}
         cell.keyName = "Sort By"
         cell.value = [1]
         cell.allowsMultipleSelection = true
         cell.allowsEmptySelection = false
    
         // MARK:  implement onChangeHandler
         cell.onChangeHandler = { [weak self] newValue in
            self.applyFilter(forDimensions: newValue)      // here, the cell input is set to a filter function
         }
    
        return cell
     }
    
    

    ## Theming Supported style classes

     fdlFUIFilterFormCell
     fdlFUIFilterFormCell_keyLabel
     fdlFUIFilterFormCell_item_contentView
     fdlFUIFilterFormCell_item_titleLabel
     fdlFUIFilterFormCell_item_contentView_selected
     fdlFUIFilterFormCell_item_titleLabel_selected
    
    See more

    Declaration

  • A UITableViewCell subclass, which allows a user to read or enter a value, using a date picker.

    FUIDatePickerFormCell

    The developer should set the following properties on the cell, in their implementation of UITableViewDataSource cellForRow(at:) function:

    • keyName: The key name of the property.
    • value: The value of the property, as Date

    And an onChangeHandler:

    • onChangeHandler: a handler closure, which is invoked on changes to the value

    Optionally, UITableViewController could provide

    • dateFormatter: A developer-defined UIDateFormatter, for transposing between Date type and String.
    • datePickerMode: The UIDatePickerMode for the date picker. Default is .dateAndTime. Note that .countDownTimer mode is not supported. Use the FUIDurationPickerFormCell for duration values.
    • isEditable: Indicates if the cell’s value may be modified. Defaults to true.

    Color setting:

    Setting text color of filter buttons for a state using setTintColor(_:for:) api. Currently .disabled, .normal and selected are supported.

    cell.setTintColor(UIColor.red, for: .normal)
    

    The following is an example of usage in an application UITableViewController:

    Important

    The app’s UITableViewController must subclass FUIFormTableViewController
    let dateFormatter = DateFormatter()
    
    override func viewDidLoad() {
    super.viewDidLoad()
    
    dateFormatter.dateFormat = "dd-MM-yyyy"
    self.tableView.register(FUIDatePickerFormCell.self, forCellReuseIdentifier: FUIDatePickerFormCell.reuseIdentifier)
    // ...
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cell = tableView.dequeueReusableCell(withIdentifier: FUIDatePickerFormCell.reuseIdentifier, for: indexPath) as! FUIDatePickerFormCell
    cell.keyName = "End Date"
    
    cell.dateFormatter = dateFormatter
    cell.datePickerMode = .date
    cell.value = cell.dateFormatter.date(from: myObject.endDate)   // "02-17-2017"
    
    // MARK:  implement onChangeHandler
    cell.onChangeHandler = { newValue in
    myObject.endDate = cell.dateFormatter.string(from: newValue)
    }
    
    return cell
    }
    
    

    Theming

    Supported style classes

    fdlFUIDatePickerFormCell
    fdlFUIDatePickerFormCell_keyLabel
    fdlFUIDatePickerFormCell_valueLabel
    fdlFUIDatePickerFormCell_selectedBackgroundView
    fdlFUIDatePickerFormCell_valueLabel_selected
    
    See more

    Declaration

    Swift

    @IBDesignable
    open class FUIDatePickerFormCell : FUIInlineValidationTableViewCell, FUIPropertyFormCell
  • A UITableViewCell subclass, which allows a user to read or enter a value, using a duration picker.

    FUIDurationPickerFormCell

    The developer should set the following properties on the cell, in their implementation of UITableViewDataSource cellForRow(at:) function:

    • keyName: The key name of the property
    • value: The value of the property, as TimeInterval

    And an onChangeHandler:

    • onChangeHandler: a handler closure, which is invoked on changes to the value

    Optionally, the developer may provide

    • minInterval: The minute interval to be used in the picker.
    • isEditable: Indicates if the cell’s value may be modified. Defaults to true.

    Color configuration:

    Call setTintColor(_:for:) to configure tint color for disabled, normal, selected UIControlState. Setting tintColor is equivalent to call setTintColor(color, for: UIControlState.normal).

    • disabled: Color to be used when control is disabled.
    • normal: Color to be used when control is enabled.
    • selected: Color to be used when control is selected.

    The following is an example of usage in an application UITableViewController:

    Important

    The app’s UITableViewController must subclass FUIFormTableViewController
     override func viewDidLoad() {
         super.viewDidLoad()
         self.tableView.register(FUIDurationPickerFormCell, forCellReuseIdentifier: FUIDurationPickerFormCell.reuseIdentifier)
         // ...
     }
    
     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
         let cell = tableView.dequeueReusableCell(withIdentifier: FUIDurationPickerFormCell.reuseIdentifier, for: indexPath) as! FUIDurationPickerFormCell
         cell.keyName = "Duration"
         cell.value = myObject.eventDuration  // in seconds
    
         // MARK:  implement an onChangeHandler
         cell.onChangeHandler = { newValue in
            myObject.eventDuration = newValue
         }
    
         return cell
     }
    

    ## Theming Supported style classes

     fdlFUIDurationPickerFormCell
     fdlFUIDurationPickerFormCell_keyLabel
     fdlFUIDurationPickerFormCell_valueLabel
     fdlFUIDurationPickerFormCell_valueLabel_selected
    
    See more

    Declaration

    Swift

    @IBDesignable
    public class FUIDurationPickerFormCell : FUIInlineValidationTableViewCell, FUIPropertyFormCell
    extension FUIDurationPickerFormCell: UIPickerViewDataSource
    extension FUIDurationPickerFormCell: UIPickerViewDelegate
  • A customized UITableViewCell, which contains a UILabel, a UITextField and a UIPickerView. It allows users to select a single value from a set of options using a spinning wheel.

    FUIValuePickerFormCell

    The developer should set the following properties on the cell, in their implementation of UITableViewDataSource cellForRow(at:) function:

    • keyName: The key name of the property
    • valueOptions: A set of options that users can chose from.
    • value: The value of the property, as Int

    And an onChangeHandler:

    • onChangeHandler: a handler closure, which is invoked on changes to the value.

    Optionally, the developer may set

    • isEditable: Indicates if the cell’s value may be modified. Defaults to true.

    Color setting:

    Setting text color of filter buttons for a state using setTintColor(_:for:) api. Currently .disabled, .normal and selected are supported.

    cell.setTintColor(UIColor.red, for: .normal)
    

    The following is an example of usage in an application UITableViewController:

    Important

    The app’s UITableViewController must subclass FUIFormTableViewController
    override func viewDidLoad() {
    super.viewDidLoad()
    self.tableView.register(FUIValuePickerFormCell, forCellReuseIdentifier: FUIValuePickerFormCell.reuseIdentifier)
    // ...
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cell = tableView.dequeueReusableCell(withIdentifier: FUIValuePickerFormCell.reuseIdentifier, for: indexPath) as! FUIValuePickerFormCell
    cell.keyName = "Maximum Price"
    cell.valueOptions = ["5", "10", "15", "20", "25"]
    cell.value = 0
    
    // MARK:  implement an onChangeHandler
    cell.onChangeHandler = { [weak self] newValue in
    self.myObject.price = self.priceTitles[newValue].first!.key
    }
    
    return cell
    }
    

    Theming

    Supported style classes

    fdlFUIValuePickerFormCell
    fdlFUIValuePickerFormCell_keyLabel
    fdlFUIValuePickerFormCell_valueTextField
    fdlFUIValuePickerFormCell_valueTextField_selected
    
    See more

    Declaration

    Swift

    @IBDesignable
    open class FUIValuePickerFormCell : FUIInlineValidationTableViewCell, FUIPropertyFormCell, UIPickerViewDataSource, UIPickerViewDelegate
  • The reusable UI component implemented as an UITableViewCell to display a key-value pair property, which is integrated with a FUIListPicker controller for displaying a list of values.

    ### Single-line version

    FUIListPickerFormCell-single

    ### Multi-line version

    FUIListPickerFormCell-multi

    The developer should set the following properties on the cell, in their implementation of UITableViewDataSource cellForRow(at:) function:

    • keyName: The key name of the property.
    • value: The default selections.
    • valueOptions: The list of optional values user may choose from.
    • allowsMultipleSelection: Indicates if user can select multiple values. Default is true, meaning by default user may select multiple values.
    • isEditable: If the selection(s) could be modified or not. The default is true.
    • listPicker: The FUIListPicker for this FUIListPickerFormCell.

    Note that the display of the selections in the valueLabel is the responsibility of the developer if the dataSource property of the listPicker is set. Developer is to set the text of the valueLabel to reflect the selections. Otherwise, if developer sets valueOptions and leaves dataSource of listPicker to nil, then the text in valueLabel will be set internally.

    Here are the code snippets in app’s UITableViewController implementation: (The app’s UITableViewController needs to be a subclass of FUIFormTableViewController.)

    
            var propValue7: [Int] = [1, 3, 6]
            var valueOptions7 = ["One", "Two", "Three", "Four", "Five", "Six", "Seven"]
            var listPickerDataSource7 = StringListPickerDataSource(options: valueOptions7)
    
            override func viewDidLoad() {
                super.viewDidLoad()
                self.tableView.register(FUIListPickerFormCell.self, forCellReuseIdentifier: FUIListPickerFormCell.reuseIdentifier)
                // ...
            }
    
            override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                // ...
                let cell = tableView.dequeueReusableCell(withIdentifier: FUIListPickerFormCell.reuseIdentifier, for: indexPath) as! FUIListPickerFormCell
                cell.keyName = "Choose Multiple"
                cell.value = propValue7
                cell.allowsMultipleSelection = true
                cell.valueLabel.text = descriptionForSelectedStrings(valueOptions7, at: propValue7) // See below
    
                cell.listPicker.dataSource = listPickerDataSource7
                cell.listPicker.searchResultsUpdating = listPickerDataSource7
                cell.listPicker.isSearchEnabled = true
                cell.listPicker.prompt = "Please select multiple items"
    
                cell.listPicker.searchBar?.isBarcodeScannerEnabled = true
                cell.listPicker.searchBar?.barcodeScanner?.scanMode = .EAN_UPC
                cell.listPicker.searchBar?.barcodeScanner?.scanResultTransformer = { (scanString) -> String in
                    return self.transformStringToSearchBar(scanResultString: scanString)
                }
                // MARK:  implement onChangeHandler
                cell.onChangeHandler = { [weak self] newValue in
                    self.propValue3 = newValue
                }
                return cell
                // ...
            }
    
            func descriptionForSelectedStrings(_ options: [String], at indexes: [Int]) -> String {
                return options.enumerated().filter({ (index, element) -> Bool in
                    return indexes.contains(index)
                }).reduce ("") { string, element in
                    return string.isEmpty ? element.1 : "\(string), \(element.1)"
                }
            }
    
    

    ## Theming

    Supported UILabel class paths:

     fdlFUIListPickerFormCell_keyLabel {}
     fdlFUIListPickerFormCell_keyLabel-disabled {}
     fdlFUIListPickerFormCell_valueLabel {}
    

    Supported UILabel properties:

     font-color: (Color)
     font-style: (UIFontTextStyle)
    

    Supported UIView class paths:

     fdlFUIListPickerFormCell_selectedBackgroundView {}
    

    Supported UIView properties:

     background-color: (Color)
    
    See more

    Declaration

    Swift

    open class FUIListPickerFormCell : FUIInlineValidationTableViewCell, FUIPickerFormCell
  • FUIInlineSignatureFormCell is a UITableViewCell subclass, which enables the drawing and capturing of a user’s signature.

    Usage Example:

    let cell = tableView.dequeueReusableCell(withIdentifier: FUIInlineSignatureFormCell.reuseIdentifier, for: indexPath) as! FUIInlineSignatureFormCell
    cell.value = self.signatureImage
    cell.onChangeHandler = { [unowned self] newValue in
        self.signatureImage = newValue
        if let image = newValue {
            // save the signature image
            saveSignatureImage(image: image)
        }
    }
    return cell
    

    Theming

    See Theming support in FUIInlineSignatureFormView.

    See more

    Declaration

    Swift

    public class FUIInlineSignatureFormCell : FUIInlineValidationDrawingTableViewCell<FUIInlineSignatureFormView>, FUITableAndCollectionCellUpdate
  • The protocol defines the properties and functions for listing the options in an UITableView for the corresponding ListPickerFormCell.

    See more

    Declaration

    Swift

    @objc
    public protocol FUIListPicker
  • An object that adopts the FUIListPickerDataSource protocol is responsible for providing the data and views required to display the list of options available in FUIListPickerFormCell or FUIListPickerTableViewController.

    The data source could be sectioned by implementing the following function:

    func numberOfSections(in listPicker: FUIListPicker)  -> Int
    

    Important

    Only data source using unique identifier could be sectioned. That is, the property isDataSourceRequiringUniqueIdentifiers of the FUIListPicker is true.

    Implementation Note:

    The list picker will not show any item if any of the required functions is not implemented.

    The following optional functions are required to be implemented for data source not using unique identifier:

    func numberOfRows(in listPickerTableView: UITableView) -> Int
    
    func listPickerTableView(_ tableView: UITableView, cellForRowAt index: Int, isFiltered: Bool) -> UITableViewCell
    

    The following optional functions are required to be implemented for data source using unique identifier but not sectioned:

    func numberOfRows(in listPickerTableView: UITableView) -> Int
    
    func listPickerTableView(_ tableView: UITableView, cellForRowAt index: Int, isFiltered: Bool) -> UITableViewCell
    
    func listPickerTableView(_ tableView: UITableView, cellForItemWithUniqueIdentifier uniqueIdentifier: String) -> UITableViewCell
    
    func listPickerTableView(_ tableView: UITableView, uniqueIdentifierForItemAt index: Int) -> String
    
    func listPickerTableView(_ tableView: UITableView, indexForUniqueIdentifier uniqueIdentifier: String) -> Int
    

    The following optional functions are required to be implemented for data source using unique identifier and sectioned:

    func numberOfSections(in listPicker: FUIListPicker) -> Int
    
    func listPickerTableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    
    func listPickerTableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath, isFiltered: Bool) -> UITableViewCell
    
    func listPickerTableView(_ tableView: UITableView, uniqueIdentifierForItemAtIndexPath indexPath: IndexPath) -> String
    
    func listPickerTableView(_ tableView: UITableView, cellForItemWithUniqueIdentifier uniqueIdentifier: String) -> UITableViewCell
    
    func listPickerTableView(_ tableView: UITableView, indexPathForUniqueIdentifier uniqueIdentifier: String) -> IndexPath?
    
    See more

    Declaration

    Swift

    @objc
    public protocol FUIListPickerDataSource
  • An implementation of FUIListPickerSearchResultsUpdating protocol is responsible to maintain a filtered list of options, based on the search string specified, for the corresponding FUIListPickerDataSource implementation.

    Implementation Note:

    Depending on the FUIListPickerDataSource, different optional functions in the corresponding FUIListPickerSearchResultsUpdating are required to be implemented. The list picker will not show any item if any of the required functions is not implemented.

    The following optional functions are required to be implemented for data source not using unique identifier:

    func listPicker(_ listPicker: FUIListPicker, filteredDataSourceContainsItemAt unfilteredIndex: Int) -> Bool
    
    func listPicker(_ listPicker: FUIListPicker, unfilteredDataSourceIndexOfItemAt filteredIndex: Int) -> Int
    

    The following optional functions are required to be implemented for data source using unique identifier but not sectioned:

    func listPicker(_ listPicker: FUIListPicker, filteredDataSourceContainsItemWithUniqueIdentifier uniqueIdentifier: String) -> Bool
    

    The following optional functions are required to be implemented for data source using unique identifier and sectioned:

    func listPicker(_ listPicker: FUIListPicker, filteredDataSourceContainsItemWithUniqueIdentifier uniqueIdentifier: String) -> Boo
    
    See more

    Declaration

    Swift

    @objc
    public protocol FUIListPickerSearchResultsUpdating
  • This FUIListPickerTableViewController is to show a list of table view cells to let user select one of the cell. Developer needs to provide implementation of FUIListPickerDataSource, and FUIListPickerSearchResultsUpdating if search is enabled, in order to use FUIListPickerTableViewController.

    If the isDismissedOnSelection property is set to true, and the allowsMultipleSelection property is set to false, then when user selected one cell by tapping the displayed cell, the onSelectionHandler property will be invoked to notify the user selection. The table view will then be dismissed.

    There will be a “Done” button shown in the navigation bar if the isDismissedOnSelection property is set to false or the allowsMultipleSelection property is set to true. The onSelectionHandler property will be invoked after user tapped the “Done” button if the allowsMultipleSelection property is set to false, or the onMultipleSelectionHandler property will be invoked if the allowsMultipleSelection property is set to true. Then the table view will be dismissed.

    There will be a “Select All” button in the “All” section header, if multiple selections is allowed and not all items are selected. All items are selected when the “Select All” button is tapped. Once all items are selected, the button title will change to “Deselect All”. All items are de-selected when “Deselect All” button is tapped.

    Also, a “Deselect All” button will be in the “Selected” section header when multiple selections is allowed. The “Selected” section will appear if the items in the list could not be displayed in one screen, and there are one or more items selected. All selected items will be de-selected when “Deselect All” button is tapped.

    Here is a code snippet of a typical usage:

    
    let listPickerTableViewController = createInstanceFromStoryboard()
    var listPicker = listPickerTableViewController.listPicker
    
    listPicker.title = "Magic School"
    listPicker.register(FUIObjectTableViewCell.self, forCellReuseIdentifier: FUIObjectTableViewCell.reuseIdentifier)
    listPicker.dataSource = self.objectCellListPickerDataSource
    listPicker.prompt = "Select One"
    listPicker.estimatedRowHeight = 98
    
    listPicker.isSearchEnabled = true
    listPicker.searchResultsUpdating = self.objectCellListPickerDataSource
    listPicker.isBarcodeScannerEnabled = true
    listPicker.barcodeScanMode = .all
    listPicker.barcodeScanResultTransformer = { (scanString) -> String in
    return "S"
    }
    
    listPickerTableViewController.onSelectionHandler = {
    self.select1Result.text = self.objectCellListPickerDataSource.descriptionForSelectedItems(at: [$0])
    }
    listPickerTableViewController.showsCancelButton = true
    listPickerTableViewController.isDismissedOnSelection = false
    
    // Select item at index 4 as default, which is the 5th item.
    listPickerTableViewController.selectItem(4)
    
    let navController = UINavigationController(rootViewController: listPickerTableViewController)
    self.present(navController, animated: true, completion: nil)
    
    

    Theming

    Supported style classes

    fdlFUIListPickerTableViewController
    fdlFUIListPickerTableViewController_cancelItem
    fdlFUIListPickerTableViewController_sectionHeaderTitleLabel
    fdlFUIListPickerTableViewController_listTextLabel
    
    See more

    Declaration

    Swift

    open class FUIListPickerTableViewController : UITableViewController, UISearchResultsUpdating, UISearchBarDelegate, FUIBarcodeScanViewControllerDelegate
    extension FUIListPickerTableViewController: UISheetPresentationControllerDelegate
    • The reusable UI component implemented as an UITableViewCell to manage selecting attachments.

    FUIAttachmentsFormCell uses a FUIAttachmentsViewController to display the title of the cell and a collection of icons to represent the attachments. The attachment icon size may change, depends on the system font size settings. The controller arranges the attachment icons in such a manner that as many icons to be fitted in a row, and as many rows to display all the attachment icons. It will also try to make the row spacing equal to the spacing between icons. However, the row spacing is limited to 20 pixels maximum.

    Developers should use the property attachmentsController to provide attachment information; the delegate, the dataSource and the list of FUIAttachmentAction implementations for the desired type of attachments. The app can use the built-in types or implement additional types as desired.

    Important

    the cell’s parent UITableViewController should subclass FUIFormTableViewController.

    Color settings:

    Setting tintColor for add button for a state using setTintColor(_:for:) api. Currently normal and .selected are supported.

     cell.setTintColor(UIColor.red, for: .normal)
    

    There are three built-in FUIAttachmentAction:

     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
         let cell = tableView.dequeueReusableCell(withIdentifier: FUIAttachmentsFormCell.reuseIdentifier, for: indexPath) as! FUIAttachmentsFormCell
         cell.attachmentsController.delegate = self
         cell.attachmentsController.dataSource = self
    
         let addPhotoAction = FUIAddPhotoAttachmentAction()
         addPhotoAction.delegate = self
         cell.attachmentsController.addAttachmentAction(addPhotoAction)
    
         let takePhotoAction = FUITakePhotoAttachmentAction()
         takePhotoAction.delegate = self
         cell.attachmentsController.addAttachmentAction(takePhotoAction)
    
         let filePickerAction = FUIDocumentPickerAttachmentAction()
         filePickerAction.delegate = self
         cell.attachmentsController.addAttachmentAction(filePickerAction)
    
         return cell
     }
    
     var attachmentURLs: [URL] = [URL]()
    
    // MARK: FUIAttachmentsViewControllerDataSource methods
    func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, iconForAttachmentAtIndex index: Int) -> (image: UIImage, contentMode: UIViewContentMode)? {
        let urlString = self.attachmentURLs[index].absoluteString
        guard let image = self.attachmentThumbnails[urlString] else {
            return nil
        }
        return (image!, .scaleAspectFill)
    }
    
    func numberOfAttachments(in attachmentsViewController: FUIAttachmentsViewController) -> Int {
        return attachmentURLs.count
    }
    
    func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, urlForAttachmentAtIndex index: Int) -> URL? {
        return attachmentURLs[index]
    }
    
     func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, titleForAttachmentAtIndex index: Int) -> (image: UIImage, contentMode: UIViewContentMode)? {
         return "attachment title"
     }
    
     func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, subtitleForAttachmentAtIndex index: Int) -> (image: UIImage, contentMode: UIViewContentMode)? {
         return "attachment subtitle"
     }
    
     func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, footnoteForAttachmentAtIndex index: Int) -> (image: UIImage, contentMode: UIViewContentMode)? {
         return "attachment footnote"
     }
    
    // MARK:  FUIAttachmentsViewControllerDelegateMethods
    func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, couldNotPresentAttachmentAtIndex index: Int) {
    
    }
    
    func attachmentsViewController(_ attachmentsViewController: FUIAttachmentsViewController, didPressDeleteAtIndex index: Int) {
        self.attachmentURLs.remove(at: index)
        self.tableView.reloadSections(IndexSet(integer:attachmentSection), with: .automatic)
    }
    
     func focusOnNewAttachment() {
         DispatchQueue.main.async {
             if let cell = self.tableView.visibleCells.last as? FUIAttachmentsFormCell { // find the attachment cell
                 if let newDoc = cell.accessibilityElements?.last {
                     UIAccessibility.post(notification: .layoutChanged, argument: newDoc)
                 }
             }
         }
     }
    
    //MARK: FUIAddPhotoAttachmentActionDelegate
     func addPhotoAttachmentAction(_ action: FUIAddPhotoAttachmentAction, didSelectPhoto asset: PHAsset, at url: URL) {
        setupThumbnails(url, with: asset)
        self.addAttachmentURL(url)
    }
    
    //MARK: FUITakePhotoAttachmentActionDelegate
    
    func takePhotoAttachmentAction(_ action: FUITakePhotoAttachmentAction, didTakePhoto asset: PHAsset, at url: URL) {
        setupThumbnails(url, with: asset)
        self.addAttachmentURL(url)
    }
    
    
    func addAttachmentURL(_ url: URL) {
        self.attachmentURLs.append(url)
        DispatchQueue.main.async {
            self.tableView.reloadSections(IndexSet(integer:self.attachmentSection), with: .automatic)
            self.tableView.scrollToRow(at: IndexPath(row: 0, section: self.attachmentSection) , at: .middle, animated: true)
            if UIAccessibility.isVoiceOverRunning {
                focusOnNewAttachment()
            }
        }
    }
    
     func setupThumbnails(_ url: URL, with asset: PHAsset) {
         let imageManager = PHImageManager.default()
         imageManager.requestImage(for: asset, targetSize: CGSize(width: 80, height: 80), contentMode: .default, options: nil, resultHandler: { image, array in
             self.attachmentThumbnails[url.absoluteString] = image
             DispatchQueue.main.async {
                 self.tableView.reloadSections(IndexSet(integer:self.attachmentSection), with: .automatic)
                 self.tableView.scrollToRow(at: IndexPath(row: 0, section: self.attachmentSection) , at: .middle, animated: true)
             }
         })
     }
    
     //MARK: FUIDocumentPickerAttachmentActionDelegate {
     var documentPicker: UIDocumentPickerViewController {
         return UIDocumentPickerViewController(documentTypes: ["public.data"], in: .import)
     }
    
     func documentPickerAttachmentAction(_ action: FUIDocumentPickerAttachmentAction, didPickFileAt url: URL) {
         if let savedUrl = saveFileToTempFolder(url) {
             self.addAttachmentURL(savedUrl)
         }
         self.tableView.reloadSections(IndexSet(integer:self.attachmentSection), with: .automatic)
         if UIAccessibility.isVoiceOverRunning {
            focusOnNewAttachment()
         }
     }
    

    ## Theming

    Supported TEXT class paths:

     fdlFUIAttachmentsFormView_attachmentTitleLabel {}
     fdlFUIAttachmentsViewController_alertActionTitle {}
     fdlFUIFileThumbnailCollectionItemView_titleLabel {}
     fdlFUIThumbnailCollectionItemView_subtitle {}
     fdlFUIThumbnailCollectionItemView_footnote {}
    

    Supported TEXT properties:

     font-color: Color;
     font-style: UIFontTextStyle;
    

    Supported IMAGE class paths:

     fdlFUIFileThumbnailCollectionItemView_detailImageView {}
    

    Supported IMAGE properties:

     tint-color: Color;
    

    Supported BUTTON class paths:

    fdlFUIAddButtonCell_addButton {}
    

    Supported BUTTON properties:

     image: Image;
     tint-color: Color;
    

    Supported CELL class paths:

     fdlFUIAttachmentsFormCell_thumbnailCell {}
     fdlFUIAttachmentsFormCell_addButtonCell {}
    

    Supported CELL properties:

     border-color: Color;
     border-width: Integer;
     corner-radius: Integer;
    

    Supported style classes

    See more

    Declaration

    Swift

    @IBDesignable
    open class FUIAttachmentsFormCell : FUIInlineValidationTableViewCell
  • Simple UITableViewCell subclass, containing a UIButton instance which can be aligned to 3 FUIHorizontalAlignment positions: .left, .center, .right.

    FUIButtonFormCell

    Color settings:

    Setting tintColor for button for a state using setTintColor(_:for:) api. Currently disabled, normal and selected are supported.

    cell.setTintColor(UIColor.red, for: .normal)
    

    Usage:

    Implement the action handler for the UIButton instance, to respond to UIControl events.

    Theming

    Supported style classes

    fdlFUIButtonFormCell
    fdlFUIButtonFormCell_button
    
    See more

    Declaration

    Swift

    @IBDesignable
    open class FUIButtonFormCell : FUIInlineValidationTableViewCell
  • FUIInlineValidationView is a UIView contains a UILabel. It is used by FUIInlineValidationTableViewCell as a validation view appearing at the bottom to show the validation message.

    Theming

    Supported style classes

    fdlFUIInlineValidationView
    fdlFUIInlineValidationView_titleLabel
    fdlFUIInlineValidationView_separatorView
    fdlFUIInlineValidationView_backgroundView
    
    See more

    Declaration

    Swift

    open class FUIInlineValidationView : NibDesignable
  • FUIInlineValidationTableViewCell is a base class for FUIFormCells that need to support validation handling. The validation view will appear at the bottom of cell if validation message is set.

    This class is typically not used by developer. Most of form cells are subclassing this class. To enable validation message on form cells by setting validationMessage property.

    Code usage:

    Set validationMessage on form cell.

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: FUITitleFormCell.reuseIdentifier, for: indexPath) as! FUITitleFormCell
        //Configure your cell
    
        cell.validationMessage = "Validation msg"
    }
    
    See more

    Declaration

    Swift

    open class FUIInlineValidationTableViewCell : NibDesignableFUIBaseTableViewCell, FUIInlineValidation, FUIAccessoryViewDelegate
  • FUIFilterFeedbackControl provides an easy way for programmers to represent a list of applied filters. This FUIFilterFeedbackControl usually appears at the top of the screen above a UITableView. Although you can set this view to any height, it is recommended to set the height of this cell to CGFloat(44). And set its height constraint to the same value.

    Developers can use in Interface Builder by adding a UIView to their storyboard or XIB, then setting its class to FUIFilterFeedbackControl. Then set the filterGroups, and filterResultsUpdater properties.

    @IBOutlet var filterFeedbackControl: FUIFilterFeedbackControl!
    
    // ...
    
    var sortGroup = FUIFilterGroup()
    var mileGroup = FUIFilterGroup()
    var nearGroup = FUIFilterGroup()
    
    override func viewDidLoad() {
    super.viewDidLoad()
    
    let sortDistanceItem = FUIFilterItem("Sort: Distance", isFavorite: false, isActive: true)
    let sortPriceItem = FUIFilterItem("Sort: Price", isFavorite: false, isActive: false)
    let sortRatingsItem = FUIFilterItem("Sort: Ratings", isFavorite: false, isActive: false)
    let sortAvailabilityItem = FUIFilterItem("Sort: Availability", isFavorite: false, isActive: false)
    
    let mile1Item = FUIFilterItem("0.1 mi", isFavorite: true, isActive: false)
    let mile2Item = FUIFilterItem("0.2 mi", isFavorite: true, isActive: false)
    let mile3Item = FUIFilterItem("0.3 mi", isFavorite: true, isActive: false)
    let mile4Item = FUIFilterItem("0.4 mi", isFavorite: true, isActive: true)
    
    sortGroup.items = [sortDistanceItem, sortPriceItem, sortRatingsItem, sortAvailabilityItem]
    sortGroup.allowsEmptySelection = false
    sortGroup.isMutuallyExclusive = true
    
    mileGroup.items = [mile1Item, mile2Item, mile3Item, mile4Item]
    mileGroup.allowsEmptySelection = true
    mileGroup.isMutuallyExclusive = true
    
    let nearGasItem = FUIFilterItem("Nearby Gas", isFavorite: true, isActive: false)
    let nearCoffeeItem = FUIFilterItem("Nearby Coffee", isFavorite: true, isActive: false)
    let nearRestaurantsItem = FUIFilterItem("Nearby Restaurants", isFavorite: true, isActive: false)
    
    nearGroup.items = [nearGasItem, nearCoffeeItem, nearRestaurantsItem]
    nearGroup.allowsEmptySelection = true
    nearGroup.isMutuallyExclusive = false
    
    filterFeedbackControl.filterGroups = [sortGroup, mileGroup, nearGroup]
    filterFeedbackControl.filterResultsUpdater = self
    
    // ...
    }
    
    func updateFilterResults(for filterFeedbackControl: FUIFilterFeedbackControl) {
    let effectiveItems = filterFeedbackControl.filterItems
    
    // ...
    }
    

    To keep selected item in the original order, use following code:

    filterFeedbackControl.keepsItemOrderOnSelection = true
    

    Implement the FUIFilterFeedbackControlDelegate to set cell properties such as accessibility:

    let myDelegate = MyDelegate()
    
    filterFeedbackControl.delegate = myDelegate
    
    class MyDelegate: FUIFilterFeedbackControlDelegate {
        func filterFeedbackControl(_ filterFeedbackControl: FUIFilterFeedbackControl, willDisplay cell: UICollectionViewCell, with item: FUIFilterItem) {
            cell.accessibilityIdentifier = "identifier"
        }
    }
    
    

    Theming

    FUIFilterFeedbackControl is using a list of SegmentedControl componentes. Therefore, theming of FUIFilterFeedbackControl should be using the SegmentedControl theming elements.

    
    fdlSegmentedControl_item_contentView {
    border-color: @primary4;
    }
    
    fdlSegmentedControl_item_titleLabel {
    font-color: @primary2;
    }
    
    fdlSegmentedControl_item_contentView_selected {
    border-color: @tintColorDark;
    }
    
    fdlSegmentedControl_item_titleLabel_selected {
    font-color: @tintColorDark;
    }
    
    

    Theming

    Supported style classes

    // Customize border color
    fdlFUIFilterFeedbackControl_lineView
    
    See more

    Declaration

    Swift

    open class FUIFilterFeedbackControl : UIView, FUIViewBorderDrawing
  • This protocol is to be used in FUIFilterFeedbackControl for updateing the results based on the changes in filters.

    See more

    Declaration

    Swift

    public protocol FUIFilterResultsUpdating : AnyObject
  • A FUIFilterGroup represents a group of related FUIFilterItem objects.

    See more

    Declaration

    Swift

    open class FUIFilterGroup
  • A FUIFilterItem represent one “Filter” item to be displayed on the FUIFilterFeedbackControl view.

    See more

    Declaration

    Swift

    public class FUIFilterItem : Equatable
  • FUISortFilterViewController allows users to narrow down results from a long list by setting criteria. Users are able to reset filters and return to the initial list.

    Various ControlTypes, such as switch, filter, rating, etc. are supported for sort and filter criteria.

    Initialization and Configuration Example:

    let vc = FUISortFilterViewController()
    
    // This is required. This is a 2D array of sort and filter criteria. The first dimension of the array is `UITableView` sections and the second dimension is `ControlTypes(cells`) for that section.
     vc.values = [
         [
             .filter([0], ["Distance", "Availability", "Ratings", "Price"], "Sort by", false, true)
         ],
         [
             .switch(true, "Show Favorites"),
             .listPicker([0], ["None", "John Smith", "Mary Jones", "Ronald Archer"], "Assigned To", false, false, true, true),
             .switch(false, "Show My Work Orders"),
             .filter([0, 2], ["Received", "Started", "Hold", "Transfer", "Completed", "Pending Review", "Rejected"], "Mobile Status"),
         ],
         [
             .datePicker(Date(), "Date and Time")
         ]
     ]
    
     // This is required for `FUISortFilterViewController` to invoke it to update the UI to show the number of results based on the current sort and filter criteria.
     vc.onChangeHandler = { [weak self] values, change in
         // Returns the total number of items when no filter criteria have been provided.
         if values.isEmpty {
             return 20
         }
    
         /// your code goes here
         return filteredNum
     }
    
     // Required.
     vc.completionHandler = { [weak self] values, filteredNum in
        /// your code goes here
     }
    
     let nav = UINavigationController(rootViewController: vc)
     vc.modalPresentationStyle = .popover
     vc.popoverPresentationController?.barButtonItem = sender
    
     self.present(nav, animated: true)
    

    Note:

    The title and subtitle for UINavigationBar and title for the Action button in the bottom UIToolbar can be customized as well.

    /// Customize the title and subtitle for `UINavigationBar`. This is optional.
    vc.titleAndSubtitleHandler = { filteredResult, totalNum in
        ("Filter", "Orders \(filteredResult) of \(totalNum)")
    }
    
    /// Customize the title for the action button. This is optional.
    vc.actionButtonTitleHandler = { filteredResult in
        "Show \(filteredResult) orders"
    }
    

    FUISortFilterFormDelegate Example:

    vc.sortFilterFormDelegate = self
    
    extension YourDelegateClass: FUISortFilterFormDelegate {
        func cell(_ vc: FUISortFilterViewController, controlType: FUISortFilterViewController.ControlType, at indexPath: IndexPath) -> UITableViewCell? {
            if indexPath == IndexPath(row: 0, section: 8) {
                let tableView = vc.tableView
                return tableView?.dequeueReusableCell(withIdentifier: "cellId", for: indexPath)
            }
    
            return nil
        }
    
        func configCell(_ vc: FUISortFilterViewController, controlType: FUISortFilterViewController.ControlType, at indexPath: IndexPath, cell: UITableViewCell) -> UITableViewCell {
            if indexPath == IndexPath(row: 0, section: 1) {
                if let theCell = cell as? FUIListPickerFormCell {
                    theCell.isPickerDismissedOnSelection = true
                    theCell.alwaysShowValueTextOnBottom = true
    
                    return theCell
                }
            }
    
            return cell
        }
    }
    
    
    See more

    Declaration

    Swift

    public class FUISortFilterViewController : FUIFormTableViewController
  • The reusable UI component implemented as an UITableViewCell to display or be edited as a stepper.

    FUIStepperFormCell

    A stepper is a visual representation of a user’s progress through a series of steps in a task, indicating how much the user has completed or how far they are from completing the task.

    The developer should set the following properties on the cell, in their implementation of UITableViewDataSource cellForRow(at:) function:

    • keyName: The key name of the property.
    • value: The numeric value of the stepper.

    And an onChangeHandler:

    • onChangeHandler: a handler closure, which is invoked on changes to the value

    Optionally, the developer may provide

    • hintText: hint text.

    • isEditable: Indicates whether the cell’s value can be modified. The default is true.

    • maximumValue: The highest possible numeric value for the stepper. The default is 100.

    • minimumValue: The lowest possible numeric value for the stepper. The default is 0.

    • stepValue: The step or increment value for the stepper. The default is 1, must be greater than 0.

    The following is an example of usage in an application UITableViewController:

    Important

    The app’s UITableViewController must subclass FUIFormTableViewController
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(FUIStepperFormCell.self, forCellReuseIdentifier: FUIStepperFormCell.reuseIdentifier)
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: FUIStepperFormCell.reuseIdentifier, for: indexPath) as! FUIStepperFormCell
    
        cell.keyName = "Normal Stepper"
        cell.value = 5
        cell.hintText = "hint text"
    
        // MARK:  implement onChangeHandler
        cell.onChangeHandler = { newValue in
            // ...
        }
    
        cell.maximumValue = 10
        cell.minimumValue = 0
    
        // custom colors and fonts
        cell.setAttributes([.fuiBorderColor: UIColor.systemPurple], for: .title, state: .highlighted)
        cell.setAttributes([.fuiBorderColor: UIColor.systemYellow], for: .title, state: .normal)
    
        return cell
     }
    

    ## Customize Style Using tintAttributes

    Supported keyView:

     setAttributes([.foregroundColor:, .font], for: .title, state: { .normal | .highlighted | .disabled })
    

    or directly set textColor and font for the title.

    Supported valueText:

     setAttributes([.foregroundColor:, .font], for: .valueText, state: { .normal | .disabled })
     addAttributes([.fuiBorderColor:], for: .valueText, state: { .normal | .highlighted | .disabled })
    

    or directly set textColor and font for the valueTextField.

    Supported increaseButton and decreaseButton:

     setAttributes([.foregroundColor:], for: .icons, state: { .normal | .disabled })
    

    Supported hintView:

     setAttributes([.foregroundColor:, .font:], for: .subtitle, state: { .normal | .disabled })
    

    ### .nss Theme

    Supported keyView:

     fdlFUIStepperFormCell_keyText {
     font-color { -highlighted | -disabled } (Color)
     font-style { -highlighted | -disabled } (UIFont.TextStyle)
     }
    

    Supported valueText:

     fdlFUIStepperFormCell_valueText {
     font-color { -disabled } (Color)
     font-style { -disabled } (UIFont.TextStyle)
     border-color { -highlighted | -disabled } (Color)
     }
    

    Supported BUTTON class paths:

     fdlFUIStepperFormCell_increaseButton {
     font-color { -disabled } (Color)
     }
    
     fdlFUIStepperFormCell_decreaseButton {
     font-color { -disabled } (Color)
     }
    

    Supported hintView:

     fdlFUIStepperFormCell_hintText {
     font-color { -disabled } (Color)
     font-style { -disabled } (UIFont.TextStyle)
     }
    
    See more

    Declaration

    Swift

    open class FUIStepperFormCell : FUIInlineValidationDrawingTableViewCell<FUIStepperView>, FUIFormCell
    extension FUIStepperFormCell: FUITintAttributesProvider