Skip Navigation

com.sabre.redapp.example3.web.react.modal Sample

Red App developers can show modals (pop-up windows) containing a react component instead of the classic handlebar-backbone stack.

The most important thing you need is an actual component:

class ModalComponentPure extends React.Component<ComponentProps, ComponentState> {

    constructor(props) {
        super(props);

        this.state = {
            internalState: ''
        }
    }

    updateInput(newVal) {
        this.props.updateStoreMessage(newVal);
    }



    render(): JSX.Element {

        return (
            <div className="com-sabre-redapp-example3-web-command-message-web-module">
                <Panel bsStyle="primary">
                    <Panel.Heading>
                        <Panel.Title componentClass="h3"> Message from Redux</Panel.Title>
                    </Panel.Heading>
                    <Panel.Body>
                        <div>Props hello message: {this.props.helloMessage}</div>
                        <div>Message from redux store: {this.props.messageFromStore}</div>
                        <div><input
                            onChange={(e) => this.updateInput(e.target.value)}
                            value={this.props.messageFromStore}
                        /></div>
                    </Panel.Body>
                </Panel>
            </div>
        );
    }
}

Keep in mind that you have to define proper typings for both state and props of a component:

interface ComponentProps {
    helloMessage: string
}

interface StoreActions {
    updateStoreMessage: (string) => void
}

export interface ComponentState {
    internalState: string
}

Then, in logic that shows the modal, you have to use the showReactModal method from sabre-ngv-modals/services/PublicModalService SDK module

This method takes as a param the ReactModalOptions object that defines some obligatory and optional properties.

    private showReactModal(): void {

        const modalService : PublicModalsService = getService(PublicModalsService);

        const ngvModalOptions : ReactModalOptions = {
            header: "Modal Header",
            component: React.createElement(ModalComponent, {helloMessage: "Well hello there"}, {}),
            onHide: () => console.log("[REACT MODAL SAMPLE] Closing the react modal logic"),
            onSubmit: () => {
                console.log("[REACT MODAL SAMPLE] Submitting using ctrl+enter / command+return");
                this.onButtonSubmit();
            },
            store: this.localStore.store,

            actions: actions(this.onButtonSubmit)
        }

        modalService.showReactModal(ngvModalOptions);
    }
  • component param is the most important one, here you can inject your component.

  • header is the actual text of the modal’s header.

  • store is an optional param that has to point to the redux store if you want to use one (the sample in the SDK showcases one with the store since this allows to share data between UI and services)

  • actions are the buttons on the bottom of the modal window. Keep in mind that you need to use the closeReactModal function and use it in the onClick implementation for the modal to close. Optional, if there is no action button passed, there will be added only 'Cancel' button.

  • onHide function is called whenever modal closes (either via closeReactModal method or closing the modal window). Optional.

  • onSubmit function is called whenever user calls CTRL+ENTER (or COMMAND+RETURN on MAC) key combo, so usually it’s the same function that 'submit' button executes (if there’s one). Optional, if not provided then CTRL+ENTER will close the modal.

  • layerOptions are configurations for the layer that modal will be open on. Optional.

  • modalSize is size of the opening modal. Can only have one of the following values: 'xs' | 'xsmall' | 'sm' | 'small' | 'medium' | 'lg' | 'large'. Optional, if not provided then large size will be applied.

export const actions = (onButtonSubmit) => [
    <Button
        key={2}
        className="btn-secondary"
        onClick={onButtonSubmit}
    >
        Submit
    </Button> ]
    private onButtonSubmit(): void {

        const modalService : PublicModalsService = getService(PublicModalsService);

        console.log("[REACT MODAl SAMPLE] Submit action clicked");
        console.log("Store state: ", this.localStore.store.getState());
        modalService.closeReactModal();

    }

Example of store creation and setup:

import {createStore} from 'redux'
import {StoreData} from "../interfaces/StoreData";

const defaultState: StoreData = {
  storeMessage: 'Initial message'
}

function reducer(state: StoreData = defaultState, action) {

  console.log("[REACT MODAL SAMPLE] Store received action: ", action)

  switch (action.type) {
    case 'CHANGE_MSG':
      return {
        ...state,
        storeMessage: action.newVal
      };
    default:
      return state
  }
}

export class LocalStore {

  public store = createStore(reducer);

  getData(): StoreData {
    return this.store.getState();
  }

}

The component connected with the store:

import * as React from "react";

import {Panel} from "react-bootstrap";
import {StoreData} from "../interfaces/StoreData";
import {connect} from 'react-redux';

interface StoreState {
    messageFromStore: string
}

interface OwnProps {
    helloMessage: string
}

interface StoreActions {
    updateStoreMessage: (string) => void
}

export interface ComponentState {
    internalState: string
}

class ModalComponentPure extends React.Component<StoreState & StoreActions & OwnProps, ComponentState> {

    constructor(props) {
        super(props);

        this.state = {
            internalState: ''
        }
    }

    updateInput(newVal) {
        this.props.updateStoreMessage(newVal);
    }



    render(): JSX.Element {

        return (
            <div className="com-sabre-redapp-example3-web-command-message-web-module">
                <Panel bsStyle="primary">
                    <Panel.Heading>
                        <Panel.Title componentClass="h3"> Message from Redux</Panel.Title>
                    </Panel.Heading>
                    <Panel.Body>
                        <div>Props hello message: {this.props.helloMessage}</div>
                        <div>Message from redux store: {this.props.messageFromStore}</div>
                        <div><input
                            onChange={(e) => this.updateInput(e.target.value)}
                            value={this.props.messageFromStore}
                        /></div>
                    </Panel.Body>
                </Panel>
            </div>
        );
    }
}

function mapStateToProps(state: StoreData): StoreState {
    return {
        messageFromStore: state.storeMessage
    };
}

const mapDispatchToProps = (dispatch) => {
    return {
        updateStoreMessage: (newVal) => {
            dispatch({ type: 'CHANGE_MSG', newVal: newVal})
        }
    }
};

export const ModalComponent = connect<StoreState, StoreActions, OwnProps>(mapStateToProps, mapDispatchToProps)(ModalComponentPure);