Components
*onFirstMount: the first time a component with a specific instance or tree is mounted. If another instance with the same instance or tree is mounted afterwards, it will skip the onFirstMount function
Setup Components
DeclareReducer
Sets the reducer for its child TWRComponents required parent for all TWRComponents
Base Example:
<DeclareReducer reducer='admin'>
<TWRIndex tree='users'/>
</DeclareReducer>
Two Way Components
TWRIndex
Returns an entire table from the frontend database
onFirstMount:
Backend: GET request to tree Frontend: state.set(tree, response)
instance(s):
return state.get(tree)
Base Example:
<TWRIndex tree='user'>
<ListUsers/>
</TWRIndex>
function ListUsers(props){
return <ul>
{props.instances.map(user=>
<li>{user.get('name)}</li>
)}
}
Fake Response
<TWRIndex tree='user' response={[id: 1, name: 'Sam']}>
<ListUsers/>
</TWRIndex>
function ListUsers(props){
return <ul>
{props.instances.map(user=>
<li>{user.get('name)}</li>
)}
}
*Instead of sending an ajax call, this component uses the response property to fill the frontend database*
TWRShow
Returns an instance from a table in the frontend database
onFirstMount:
Backend: GET request to tree/id Frontend: return state.setIn([tree, id], response)
instance:
return state.getIn([tree, id])
Base Example:
<TWRShow tree='user/1'>
<ShowUser/>
</TWRIndex>
function ShowUser(props){
const user = props.instance
return <div>
<h1>{user.get('name')}</h1>
<h2>{user.get('occupation'}</h2>
</div>
}
TWRCreate
when the component is submitted, it creates a new instance in the backend and frontend databases
onSubmit:
Backend: POST request to tree, ...formData Frontend: state.setIn([tree, response.id], ...formData)
instance:
return state.getIn([Substate, tree, randomId])
Base Example:
<TWRCreate tree='user'>
<CreateUser noErrors/>
</TWRShow>
function CreateUser(props){
const {instance} = props
return <div>
<label>Name</label>
<input name='name' type='text' placeholder='user name' />
{instance.get('errors') ?
<span className='label-danger'>{instance.get('errors')}</span>
:''}
<button type='submit'>Save User Name</button>
</div>
}
noErrors is a component property we use to tell the component not use the default display error functions. If we had not provided the noErrors prop, by default the component would have loaded a similar error code into the component
TWRUpdate
when the component is submitted, it updates the backend and frontend databases
onSubmit:
Backend: PUT request to instanceType/id, ...formData Frontend: state.updateIn([instanceType, id], ...formData)
instance:
return state.getIn([Substate, instanceType, randomId])
Base Example:
<TWRShow tree='user/1'>
<UpdateUser/>
</TWRShow>
function UpdateUser(props){
const user = props.instance
return <TWRUpdate instance={user}>
<UpdateUserForm user={user}/>
</TWRUpdate>
}
function UpdateUserForm(props){
const {user, instance} = props
return <div>
<label>Name</label>
<input name='name' type='text' defaultValue={user.get('name')} />
{instance.get('errors') ?
<span className='label-danger'>{instance.get('errors')}</span>
:''}
<button type='submit'>Save User Name</button>
</div>
}
Notice how we pass the user prop into the UpdateUserForm. This is because the TWRUpdate only passes the substate instance, not the actual instance, and the substate instance only holds error information noErrors is a component property we use to tell the component not use the default display error functions. If we had not provided the noErrors prop, by default the component would have loaded a similar error code into the component
TWRCreateChild
when the component is submitted, it creates a new instance with relational information in the backend and frontend databases
onSubmit:
Backend: POST request to childName, ...formData + {parent_id: parent.get('id')} Frontend: state.setIn([childName, response.id], ...formData).setIn([parentName, parentId], children.push(response.id))
instance:
return state.getIn([Substate, childName, randomId])
Base Example:
<TWRShow tree='user/1'>
<CreateChild />
</TWRShow>
function CreateChild(props){
const user = props.instance
return <TWRCreateChild instance={user} childName='children'>
<CreateChildForm />
</TWRCreateChild>
}
function CreateChildForm(props){
return <div>
<label>Name</label>
<input name='name' type='text' placeholder='child name' />
<button type='submit'>Save Child Name</button>
</div>
}
*when this form is submitted, the post data will be {name: 'child name', user_id: user.get('id')}
TWRDestroy
when the component is submitted, it deletes the instance in the backend and frontend databases
onSubmit:
Backend: DELETE request to instance, ...formData Frontend: state.deleteIn([instance, instance.get('id')], ...formData)
instance:
return state.getIn([Substate, instanceName, randomId])
Base Example:
<TWRShow tree='user/1'>
<DestroyUser />
</TWRShow>
function DestroyUser(props){
const user = props.instance
return <TWRDestroy instance={user}>
<button type='submit'>Delete User</button>
</TWRCreateChild>
}
*when this form is submitted successfully, the return data is not merged into the frontend database. Instead, the instance is simply removed from the database}
Frontend Components
TWRLink
returns a link that uses the instance type and id
Base Example:
<TWRShow tree='user/1'>
<LinkToUser>
</TWRShow>
function LinkToUser(props){
const user = props.instance
return <TWRLink instance={user}>User</TWRCreateChild>
}
==> a href='...reducerName/user/1'
or
function LinkToUser(props){
const user = props.instance
return <TWRLink instance={user} rest='edit'>User</TWRCreateChild>
}
==> a href='.../reducerName/user/1/edit'
TWRShowFront, TWRIndexFront, TWRUpdateFront, TWRDestroyFront, TWRCreateChildFront
The exact same as the Two Way components but without the backend ajax calls