Updating Items
If you want to be able to edit your records from within the list view, we've got you covered. violet-paginator
exposes both synchronous and asynchronous actions that allow you to modify the properties of a list item.
Async Update
updateAsync(id, data, update)
We intend for the updateAsync
action to be your one-stop-shop for inline updates. This action executes the following operations:
- Call
updateItem
to merge the properties from thedata
argument. This will normally be the same data you submit to the server, but can really be anything you want. - Call
updatingItem
to indicate that the item is waiting for an update from the server. - Call the
update
promise, provided as the last argument toupdateAsync
. - If the
update
promise succeeds, callupdateItem
again using the resolved data. - If the
update
promise fails, useresetItem
to revert the item to its previous state. Then rethrow the error for the caller to handle.
Example:
import api from 'ROOT/api'
import { composables } from 'violet-paginator'
import * as actionTypes from './actionTypes'
const pageActions = composables({ listId: 'recipes' })
export function toggleActive(recipe) {
const data = {
active: !recipe.active
}
return pageActions.updateAsync(
recipe.id,
data,
api.recipes.update(data)
)
}
Note that violet-paginator
will handle your promise failure if it occurs. If you want to handle that error yourself, just make sure you throw it along to us when you're done:
export function toggleActive(recipe) {
const data = {
active: !recipe.active
}
const update = api.recipes.update(data).catch(err => {
toastr.error('An error occured!')
throw err
})
return pageActions.updateAsync(
recipe.id,
data,
update
)
}
We expect that updateAsync
will cover most of your use cases,you may desire more fine grained control. To provide this, we expose every operation that updateAsync
performs so that you can organize them anyway you want to.
Instant Update
updateItem(itemId, data)
Use the updateItem
action if you want to update the values of a list item's properties. For example, assume you want an action creator that toggles the active
state of a list item:
import { composables } from 'violet-paginator'
const pageActions = composables({ listId: 'recipes' })
export function toggleActive(recipe) {
return pageActions.updateItem(
recipe.id,
{ active: !recipe.active }
)
}
Indicate Updating State
In some cases you may want to indicate that an item within a list is waiting for an update from the server. Dispatching the updatingItem
action will set the appropriate state, which can be checked with the isUpdating
function.
Setting the state
import { composables } from 'violet-paginator'
const pageActions = composables({ listId: 'recipes' })
export function updatingRecipe(recipe) {
return pageActions.updatingItem(recipe.id)
}
Checking the state
import { isUpdating } from 'violet-paginator'
import { connect } from 'react-redux'
export default connect(
(state, ownProps) => ({
updating: isUpdating(state, 'recipes', ownProps.params.id)
})
)(Recipe)
Resetting an Item
While updateItem
will merge in all provided data, resetItem
will actually overwrite the item with this data. This is actually used by violet-paginator
to revert items when promises fail for asynchronous updates. This is necessary because we update the item's data before calling the promise. If the promise fails, then, the item needs to snap back to its previous state. We achieve this by caching the current version of the item before calling the promise and feeding it to resetItem
in the event of a failure. For an example, let's just look at how violet-paginator
implements updateAsync
:
const updateAsync = (itemId, data, update) =>
(dispatch, getState) => {
const item = getPaginator(getState(), id).get('results')
.find(r => r.get(identifier) === itemId)
dispatch(basic.updateItem(itemId, data))
dispatch(basic.updatingItem(itemId))
return update.then(serverUpdate =>
dispatch(basic.updateItem(itemId, serverUpdate))
).catch(err => {
dispatch(basic.resetItem(itemId, item.toJS()))
return dispatch(basic.itemError(itemId, err))
})
}
Checking the state
To know whether or not an item is updating, use the isUpdating
function in your selector:
import { isUpdating } from 'violet-paginator'
...
export default connect(
state => ({ updating: isUpdating(state, 'myList', ownProps.recordId) })
)(MyTableRowComponent)
Note that the DataRow
component and the withRecordProps()
decorator with both give you this infomration for free.
See here for more details.