-
Notifications
You must be signed in to change notification settings - Fork 7
Custom Components
A UI component consists of at least one React component and potentially some optional CSS.
Components can be written in either normal vanilla ES5 javascript or Typescript.
var myContainer = React.createClass({
render: function () {
// Get any child containers & components that need to be displayed in this container
var children = manywho.model.getChildren(this.props.id, this.props.flowKey);
// The UI framework will handle displaying the label, outcomes & the collapse / expand toggle button, custom containers only need to be concerned about
// rendering their children. this.props.children will be populated when being rendered at design time in the page layout editor
return React.DOM.div({ className: "clearfix" }, (this.props.children || manywho.component.getChildComponents(children, this.props.id, this.props.flowKey)) });
}
});
// (Required) Register this container with the framework so it can be found later in the rendering cycle
manywho.component.registerContainer('container_name', myContainer);
// (Optional) Register this container in the styling framework so that child items can have classes applied based on the parent container
manywho.styling.registerContainer('container_name', function (item, container) {
return [];
});
/// <reference path="../../typings/index.d.ts" />
/// <reference path="../interfaces/IComponentProps.ts" />
declare var manywho: any;
interface IMyComponentProps extends IComponentProps {
}
interface IComponentState {
}
class MyComponent extends React.Component<IMyComponentProps, IComponentState> {
constructor(props: IMyComponentProps){
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleEvent = this.handleEvent.bind(this);
}
handleChange(e) {
// Sync the state of this component into the state store, this will then be sent back to ManyWho
manywho.state.setComponent(this.props.id, { contentValue: e.target.value }, this.props.flowKey, true);
// Re-sync with ManyWho if this component hasEvents = true, also re-render the component
manywho.component.handleEvent(this, manywho.model.getComponent(this.props.id, this.props.flowKey), this.props.flowKey);
}
handleEvent(e) {
manywho.component.handleEvent(this, manywho.model.getComponent(this.props.id, this.props.flowKey), this.props.flowKey);
}
render() {
// Get the basic info about this component e.g. id, name, etc
const model = manywho.model.getComponent(this.props.id, this.props.flowKey);
manywho.log.info(`Rendering My Component: ${this.props.id}, ${model.developerName}`);
// Get the local state for this component. Local state will be synced with ManyWho, this.state will not be synced.
const state = manywho.state.getComponent(this.props.id, this.props.flowKey) || {};
// Get any outcomes that are associated with the component, then transform them into Outcome components
const outcomes: any = manywho.model.getOutcomes(this.props.id, this.props.flowKey);
const outcomeElements: Array<JSX.Element> = outcomes && outcomes
.map((outcome) => React.createElement(manywho.component.getByName('outcome'), { id: outcome.id, flowKey: this.props.flowKey }));
// Get the classes that should be applied to this component e.g. mw-component-name
let className = (manywho.styling.getClasses(this.props.parentId, this.props.id, 'toggle', this.props.flowKey)).join(' ');
// If the component is invalid then add a has-error class
if (model.isValid === false || state.isValid === false)
className += ' has-error';
// Hide the component if isVisible is false
if (model.isVisible === false)
className += ' hidden';
// Setup the props for the <input> we will be rendering
const props: any = {
type: 'text',
value: state.contentValue || model.contentValue;
readOnly: !model.isEditable,
required: model.isRequired,
disabled: !model.isEnabled,
}
// Add event handlers at runtime only
if (!this.props.isDesignTime) {
props.onChange = this.handleChange;
props.onBlur = this.handleEvent;
}
return <div className={className} id={this.props.id}>
<label>{model.label}</label>
<input {...props} />
<span className="help-block">{model.validationMessage || state.validationMessage}</span>
<span className="help-block">{model.helpInfo}</span>
{outcomeElements}
</div>
}
}
// (Required) Register this component with the framework so it can be found later in the rendering cycle. This component has been
// registered with an alias of 'input', this component will be used when a component with the name of 'input' is requested
manywho.component.register('component_name', MyComponent, ['input']);
If you need to create a component to display multiple items of the same type e.g. table, list, radio, etc Then you should create an items component. The UI framework includes a higher order component that handles selection, pagination & searching that you can register a custom component into.
Take a look at the Table component as an example, or the Select component for a more advanced example.
The default containers / components can be overridden by registering your custom component with the same name as the default component.
This is only currently supported in custom players, the call to manywho.component.register
will need to go at the top of the initialize
function in the player HTML.
- Upload your resources to a publicly available url (this url will need to support CORS).
- Create a custom player using the Player tool in the Admin area.
- Alter the
manywho
object by adding a "customResources" property as shown below.
var manywho = {
cdnUrl: 'https://assets.manywho.com',
customResources: [
"https://mydomain.com/js/test.js"
],
initialize: function () {
// Your usual initialize code here...
}
}
Any custom resource file loaded using the customResources property will be included into the player after the manywho resources have finished loading. If you need your resources to load first then add them as script or link tags to the player directly.
...