Breadcrumb
- Sabre Red 360 Software Development Kit Help
- Web Red Apps
- Red App Cookbooks
- Web Red Apps examples
- com.sabre.redapp.example3.web.react.modal Sample
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 thecloseReactModal
function and use it in theonClick
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 viacloseReactModal
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 thenlarge
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);