Hooks
You can transform and validate data with custom hooks
Pulter's Hooks help you reformat, validate, and correct data automatically via custom functions per column and/or row. For example, using these hooks you can automatically reformat area codes or country codes, remove special characters, validate emails against external data, or anything else you can think of.
Match columns hook runs only once after column matching. They are run before the row hooks and will only run once during the import process.
A column hook receives all values in the column, formated data, and raw data. where each value is an object with
index
and value
keys. index
is the row index of the value, and value
is the raw value of the column at that row, as a string.Given the following imported data:
First Name | Last Name |
---|---|
Michelle | Doe |
Jane | Doe |
Steve | Jones |
Wayne | Gretzy |
Here is an example of what our match columns hook could return:
<Pulter
fields =[
{
label: 'First Name',
key: 'first_name',
alternateMatches: ['first name', 'first'],
fieldType: {
type: 'input',
},
},
{
label: 'Surname',
key: 'surname',
alternateMatches: ['second name', 'last name', 'last'],
fieldType: {
type: 'input',
},
},
{
label: 'Full Name',
key: 'full_name',
fieldType: {
type: 'input',
},
},
matchColumnsStepHook: async (data, rawData, columns) => {
const promise = data.map((value) => {
if (value.first_name !== "" && value.surname !== "") {
value.full_name = value.first_name + " " + value.surname
}
return value
})
Promise.all(promise)
return data
},
]
/>
Row hook runs validation on each record (row) of data and returns the record with new data and/or error messaging for the user.
Row hooks receive as their first argument the
record
object with a row
property.The
row
property is an object with key
s you have defined for your fields
as keys. Each of these keys will have the row's value as a string.Here is an example of what our Row hook could return:
<Pulter
fields =[
{
label: 'First Name',
key: 'first_name',
alternateMatches: ['first name', 'first'],
fieldType: {
type: 'input',
},
},
{
label: 'Surname',
key: 'surname',
alternateMatches: ['second name', 'last name', 'last'],
fieldType: {
type: 'input',
},
},
{
label: 'Full Name',
key: 'full_name',
fieldType: {
type: 'input',
},
},
rowHook={(data, addError) => {
// Validation
if (data.first_name === "John") {
addError("name", { message: "No Johns allowed", level: "info" })
}
// Transformation
return { ...data, first_name: "Not John" }
// Sorry John
}},
]
/>
Table hook runs validation on all rows. and returns the record with new data and/or error messaging for the user.
Very expensive, but can change rows that depend on other rows. It's more advisable to use Row Hook.
The
setError
accepts rowIndex
is the 0-indexed position of the data row, and fieldKey
is the key of the field as defined by fields
. messages
is the message object which will be placed on the specified field.Here is an example of what our Table hook could return:
<Pulter
fields =[
{
label: 'First Name',
key: 'first_name',
alternateMatches: ['first name', 'first'],
fieldType: {
type: 'input',
},
},
{
label: 'Surname',
key: 'surname',
alternateMatches: ['second name', 'last name', 'last'],
fieldType: {
type: 'input',
},
},
{
label: 'Full Name',
key: 'full_name',
fieldType: {
type: 'input',
},
},
tableHook: (data, setError) => {
data.forEach((value, index) => {
if (value.name === "John") {
setError(index, "surname", { message: "Wrong name", level: "error" })
}
return value
})
return data
},
]
/>
This hook runs only once after uploading the file. It receives and returns raw sheet data
<Pulter
fields =[
{
label: 'First Name',
key: 'first_name',
alternateMatches: ['first name', 'first'],
fieldType: {
type: 'input',
},
},
uploadStepHook: async (data) => {
await new Promise((resolve) => {
setTimeout(() => resolve(data), 4000)
})
return data
},
]
/>
This hook runs only once after selecting the header row in spreadsheet.. It receives and returns raw sheet data
<Pulter
fields =[
{
label: 'First Name',
key: 'first_name',
alternateMatches: ['first name', 'first'],
fieldType: {
type: 'input',
},
},
selectHeaderStepHook: async (hData, data) => {
await new Promise((resolve) => {
setTimeout(
() =>
resolve({
headerValues: hData,
data,
}),
4000,
)
})
return {
headerValues: hData,
data,
}
},
]
/>
In rare case when you need to skip the beginning of the flow, you can start the flow from any of the steps.
- initialStepState - initial state of component that will be rendered on load.
initialStepState?: StepState
type StepState =
| {
type: StepType.upload
}
| {
type: StepType.selectSheet
workbook: XLSX.WorkBook
}
| {
type: StepType.selectHeader
data: RawData[]
}
| {
type: StepType.matchColumns
data: RawData[]
headerValues: RawData
}
| {
type: StepType.validateData
data: any[]
}
type RawData = Array<string | undefined>
// XLSX.workbook type is native to SheetJS and can be viewed here: https://github.com/SheetJS/sheetjs/blob/83ddb4c1203f6bac052d8c1608b32fead02ea32f/types/index.d.ts#L269
Example:
<Pulter
initialStepState={{
type: StepType.matchColumns,
data: [
["Josh", "2"],
["Charlie", "3"],
["Lena", "50"],
],
headerValues: ["name", "age"],
}}
/>
Last modified 1yr ago