When you have a page to create you have to do something like that:
React.createClass({
render() {
<ScrollSpy>
<Child1 />
<Child2 />
<Child3 />
<Child4 />
<Child5 />
</ScrollSpy>
}
});This component has no state and knows no store.
The state is located in each child and is corellated to the store connection of each Block.
Eacch block is often done with a FormMixin.
The formMixin which should be name formPreset is composed of the following mixins
ownIdentifierBehaviourCreates a unique identifier for the form in itsthisdefinitionMixinConnects to the form to the definitions from the model, it allows the component to have a propertydefinitionPathsuch asdefinitionPath: 'contact'referenceBehaviourwhich connects the component to the master data lists, it allows the component to have a propertyreferenceNamesin order to detail which master data list you need in your page such asreferenceNames: ['papas', 'monkeys'].storeBehaviourconnects the component to the stores using the propertystoreswhich have the signature[{store: aReferenceToTheStore, properties: ['node1', 'node4']}]such asstores: [{store: contactStore, properties:['contact', 'commandes']}]it links the components state to the stores changes. Each time a store node is changed, the component state is updated. this behaviour also getstoreChangeBehaviourwhich has the_onChangeand_onErrorFunctionvalidationBehaviourAdd a_validatemethod to the form which loops all the components also add a_customValidateMethodactionBehaviouradd automatic actions to load and save databuiltInComponents, add all custom components such asfieldFor,listFor, ...formMixinwhich is the problematic part. It deals with theeditmode, it has custom methods to render the buttons. It handles the submit of the form, it renders the form and exposesrenderContent.
const FormExample = React.createClass({
displayName: 'FormExample',
mixins: [formMixin],
stores: [{ // store behaviour + storeChangeBehaviour
store: contactStore,
properties: ['contact', 'commandes']
}],
definitionPath: 'contact', // definitionBehaviour
action: action, // actionBehaviour
referenceNames: ['papas', 'monkeys'], // referenceBehaviour
renderContent() { // formMixin
return (
<Panel actions={this._renderActions} title="Fiche de l'utilisateur">
{this.fieldFor('firstName')}
{this.fieldFor('papaCode', {listName: 'papas'})}
{this.fieldFor('monkeyCode', {listName: 'monkeys', valueKey: 'myCustomCode', labelKey: 'myCustomLabel' })}
{this.fieldFor('lopezCode', {values: [{code: 'JOE', label: 'Joe Lopez'}, {code: 'DAVE', label: 'David Lopez'}]})}
{this.fieldFor('bio')}
{this.fieldFor('isNice')}
{this.textFor('birthDate', {formatter: date => 'formatted date' + date})}
{this.fieldFor('birthDate')}
</Panel>
);
}
});- The
formMixinshould only be a composition of mixins and it shouldn't add specific code. - When you have an entity which is splitted in two Blocks, even if a block can be connected to multiple store, it is hard to build: the webservices are asymetric between load and save. Its unclear wwhich block load the data.
- The form blocks has all the actions and they are too corelated to it. Actions should no be a part of the form.
- The formMixin has been used for almost every page on each projects. It shouldn't be the case. We thought it will be used as a preset and projects could have customize which part of the formMixin they want in their own presets.
- The formComponent has the state from the store and its sometimes problematic
- The form shouldn't call loading actions
- All the mixins composing the store will be pure, there will be no specific code in the
formMixin. TheformMixinis composed of the mixins described in the beginning of this document.
The main goal is to be able to build components without the
formMixin. Aform-presetswill be published in order to have no regression.
- Actions are decorelated from the components
Solves the problem of an entity
- Fields are stateless and get read it from the parent. The state is located in the parent and only in the parent.
Solves the problem of corelated fields and imporve the testabiliy of the components.
- The connection to the stores will be a wrapper around the component which contains the data.