After the drop targets and drag sources were configured last week, this week my primary motive was to develop a better UI for adding Question types. After mulling over the UI a bit, I decided to replace the existing Javascript prompt with a modal which would allow text entry and multiple radio buttons / checkboxes to configure various parts of a Question type.

Adding a Bootstrap Modal

UI

The key idea behind Surveyman is that by giving survey authors a way to write their surveys that steers them away from unnecessary ordering constraints, we can apply static analysis, randomization, and statistical dynamic analysis to locate survey errors and ensure the quality of responses.

The extra configuration parameters allow survey authors to modify the behavior of Surveyman. For example, if you are adding a question where you don’t want your options to be displayed in a random order, checking the ordered checkbox ensures that Surveyman shows the options in the order in which they were added.

The other half of this is displaying these parameters in a clear way to the users. For this, I decided on using the combo of meaningful icons and tooltips to communicate this information.

Icons for showing configuration

Architecture

To build this, I started off with migrating from Skeleton to Bootstrap so that I could use the React-Bootstrap library. The motivation here was to save time by using a set of prebuilt components that can be used right off the shelf. Apart from the modal, I knew that I’d be needing an Alert and Tooltip very soon.

With that done, the next part was laying down the architecture for Modals. The key idea here was to setup an action that would be called when the question is dropped on a Block. This would then cause the store to change a piece of data, which in our case would be the isOpen property on the modal. The triggering of this change would then finally re-render the views.

All this sounds simple, especially once you have a look at the sample code for custom triggering a modal. But things start to get interesting once you start building the form inside the modal. How do you tag DOM elements so that you can retrieve their value when an event is called? Use refs silly!

<div className="form-group">
   <label htmlFor="qtext">Question Text</label>
   <input type="text" placeholder="What is value of 4 + 5?" 
      className="form-control" id="qtext" ref="qtext" />
</div>

So I built a few form elements and tagged with them using refs and when I ran the application I got a cryptic error

Uncaught Error: Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. 

You can go dive deeper into the issue but the main idea here was with the way renderOverlay was rendering the DOM in a different DOM Tree. As a fix, I had to create a BaseModal component that would then rendered inside a renderOverlay.

The final component looked like this -

var BaseModal = React.createClass({
   // custom handler code
   render() {
      return <Modal />
   }
});

var QuestionModal = React.createClass({
   mixins: [OverlayMixin],
   render() {
      return <div className="static-modal"></div>
   },
   renderOverlay() {
      return (
         this.props.open ? <BaseModal parentId={this.props.parentID} /> 
                         : <div></div>
      )
   }
});

The last step was simply rendering the QuestionModal in the Application component.

// in Application component
render() {
   <QuestionModal
   isOpen={modalState.question}
   parentID={this.state.dropTargetID}/>
}

The other parts of the application were quite straightforward and got done rather quickly. I did get stuck with building a self-dismissing alert box but the React IRC channel helped out quite a bit.

If you’ve read this far, go ahead and take the app for a spin. For the complete code, feel free to browse the Github repository.

This week my plan is to finish off in-place editing Block, Options and Questions. Stay tuned for the next post!