...
The store should contain, at least, the initial values for openModal and activeTrap states. Also, handlers to modified them to open and close the modal. A simple example:
Code Block language js theme DJango import {BaseStore} from 'fluxible/addons'; class ExampleModalStore extends BaseStore{ constructor(dispatcher) { super(dispatcher); this.openModal = false; this.activeTrap = false; } getState(){ return { openModal : this.openModal, activeTrap : this.activeTrap }; } dehydrate() { return this.getState(); } rehydrate(state) { this.openModal = state.openModal; } openExampleModal(payload){ this.openModal = true; this.activeTrap = true; this.emitChange(); } closeExampleModal(payload){ this.openModal = false; this.activeTrap = false; this.emitChange(); } } ExampleModalStore.storeName = 'AttachSubdeckModalStore'; ExampleModalStore.handlers = { 'EXAMPLE_MODAL_OPEN' : 'openExampleModal', 'EXAMPLE_MODAL_CLOSE': 'closeExampleModal' }; export default ExampleModalStore;
The actions to open and close the modal, only should dispatch the proper instructions to the store. Examples:
Code Block language js theme DJango export default function openExampleModal(context, payload, done) { console.log('action'); context.dispatch('EXAMPLE_MODAL_OPEN', payload); done(); }
Code Block language js theme DJango export default function closeExampleModal(context, payload, done) { context.dispatch('EXAMPLE_MODAL_CLOSE', payload); done(); }
- At the modal component, we should connect it to the store and modify a little the way in which we manage the state:
Connecting to the store:
Code Block language js theme DJango import { connectToStores } from 'fluxible-addons-react'; .... AccesibleModal = connectToStores(AccesibleModal ,[ExampleModalStore],(context,props) => { return { ExampleModalStore: context.getStore(ExampleModalStore).getState() }; });
Changes at the constructor:
Code Block language js theme DJango constructor(props) { super(props); this.state = { openModal: this.props.ExampleModalStore.openModal, activeTrap: this.props.ExampleModalStore.activeTrap, }; this.handleClose = this.handleClose.bind(this); this.unmountTrap = this.unmountTrap.bind(this); }
Update the state
Code Block language js theme DJango componentWillReceiveProps(nextProps){ if (nextProps.ExampleModalStore.activeTrap !== this.props.ExampleModalStore.activeTrap){ this.setState({ activeTrap: nextProps.ExampleModalStore.activeTrap }); } if (nextProps.ExampleModalStore.openModal!== this.props.ExampleModalStore.openModal){ this.setState({ openModal: nextProps.ExampleModalStore.openModal }); } }
The close method shoul call the proper action:
Code Block language js theme DJango import closeAttachModal from '../../../../actions/exampleModal/closeExampleModal'; handleClose(){ this.context.executeAction(closeExampleModal); $('#app').attr('aria-hidden','false'); } .... AccesibleModal.contextTypes = { executeAction: React.PropTypes.func.isRequired };
The open method called from another component should call the corresponding action:
Code Block language js theme DJango import React from 'react'; ... import AccesibleModal from '../AccesibleModal/AccesibleModal.js'; import openExampleModal from '../../../../actions/exampleModal/openExampleModal '; class ContentActionsHeader extends React.Component { .... .... handleOpenExampleModal(){ this.context.executeAction(openExampleModal ); $('#app').attr('aria-hidden','true'); } ... render(){ ... return( .... <Button basic onClick={this.handleOpenExampleModal.bind(this)} type="button" aria-label="Example Modal" data-tooltip="Example Modal" tabIndex="0" > Example Modal </Button> <AccesibleModal /> .... ); } }
Some interesting
...
links about accessible modals
Technique: Accessible modal dialogs, from Harvard University
...