Skip to content

Commit

Permalink
feat: removeInput returns the removed record (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
aviemet authored Apr 14, 2024
1 parent 2d2e1bd commit b4ac146
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 46 deletions.
12 changes: 7 additions & 5 deletions src/useDynamicInputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import { get, set } from 'lodash'
import { useNestedAttribute } from './NestedFields'
import { NestedObject } from './useInertiaForm'

export interface DynamicInputsProps {
export interface DynamicInputsProps<T = NestedObject> {
model?: string
emptyData: Record<string, unknown>
emptyData: T
}

type DynamicInputsReturn = {
type DynamicInputsReturn<T = unknown> = {
addInput: () => void
removeInput: (i: number) => void
removeInput: (i: number) => T
paths: string[]
}

const useDynamicInputs = ({ model, emptyData }: DynamicInputsProps): DynamicInputsReturn => {
const useDynamicInputs = <T extends NestedObject>({ model, emptyData }: DynamicInputsProps<T>): DynamicInputsReturn<T> => {
const { setData, unsetData, getData } = useForm()
const { model: formModel } = useFormMeta()
let inputModel = formModel ?? ''
Expand Down Expand Up @@ -45,7 +45,9 @@ const useDynamicInputs = ({ model, emptyData }: DynamicInputsProps): DynamicInpu
}, [])

const handleRemoveInputs = useCallback((i: number) => {
const record = getData(`${inputModel}[${i}]`) as T
unsetData(`${inputModel}[${i}]`)
return record
}, [])

const data = getData(inputModel)
Expand Down
30 changes: 5 additions & 25 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,32 +53,15 @@ export const fillEmptyValues = <TForm>(data: TForm) => {
}

/**
* Appends a string to the end of parts of a dot notated string,
* excepting those with array notation, and the first and last elements
*/
export const renameWithAttributes = (str: string, append = '_attributes') => {
const parts = str.split('.')

if(parts.length < 2) return str

for(let i = parts.length - 2; i > 0; i--) {
if(parts[i].charAt(parts[i].length - 1) !== ']') {
parts[i] = `${parts[i]}${append}`
} else {
parts[i].replace('[', '_attributes[')
}
}

return parts.join('.')
}

/**
* Removes appended string '_attributes' from dot notation
* Removes appended string (default of '_attributes') from dot notation
*/
export const stripAttributes = (str: string, attribute = '_attributes') => {
return str.replace(new RegExp(`${attribute}\\.`), '.')
}

/**
* Append string (default of '_attributes') to keys of nested records
*/
export const renameObjectWithAttributes = <T>(data: T, str = '_attributes') => {
const clone = structuredClone(data)

Expand Down Expand Up @@ -110,10 +93,7 @@ const renameKey = (obj, oldKey, newKey) => {
}
}

export const coerceArray = (arg: string | string[]) => {
if(Array.isArray(arg)) return arg
return [arg]
}
export const coerceArray = <T = unknown>(arg: T | T[]) => Array.isArray(arg) ? arg : [arg]

/**
* Returns whether a value should be considered empty in the context of a form input
Expand Down
19 changes: 3 additions & 16 deletions tests/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NestedObject } from '../src/useInertiaForm'
import { coerceArray, fillEmptyValues, renameObjectWithAttributes, renameWithAttributes, stripAttributes, unsetCompact } from '../src/utils'
import { coerceArray, fillEmptyValues, renameObjectWithAttributes, stripAttributes, unsetCompact } from '../src/utils'

const nestedData: NestedObject = {
one: 'one',
Expand Down Expand Up @@ -78,23 +78,10 @@ describe('fillEmptyValues', () => {
})
})

describe('renameWithAttributes', () => {
it('should add _attributes where appropriate to dot notation strings', () => {
expect(renameWithAttributes('user.person.name')).toEqual('user.person_attributes.name')
expect(renameWithAttributes('user.contact.phones[2].number')).toEqual('user.contact_attributes.phones[2].number')
expect(renameWithAttributes('user.person.manager.name')).toEqual('user.person_attributes.manager_attributes.name')
})

it('accepts another string to use in place of _attributes', () => {
expect(renameWithAttributes('user.person.name', '_input')).toEqual('user.person_input.name')
})
})

describe('stripAttributes', () => {
it('should remove _attributes from dot notation strings', () => {
const key = 'user.person.name'
const attributed = renameWithAttributes('user.person.name')
expect(stripAttributes(attributed)).toEqual(key)
const key = 'user.person_attributes.name'
expect(stripAttributes(key)).toEqual('user.person.name')
})

it('should not remove the word attributes without the _ or not at the end of a segment', () => {
Expand Down

0 comments on commit b4ac146

Please sign in to comment.