Skip to content

Commit

Permalink
Merge pull request #845 from commercelayer/fix-hooked-input-select
Browse files Browse the repository at this point in the history
multi-async-select works well with `defaultValues`
  • Loading branch information
marcomontalbano authored Nov 27, 2024
2 parents 045f398 + 40b9966 commit 35610c3
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const HookedInputSelect: React.FC<HookedInputSelectProps> = ({
onSelect,
...props
}: HookedInputSelectProps) => {
const { control, watch, getValues } = useFormContext()
const { control, watch, getValues, formState } = useFormContext()
const feedback = useValidationFeedback(name)
const [prevWatched, setPrevWatched] = useState(getValues(name))

Expand All @@ -72,8 +72,6 @@ export const HookedInputSelect: React.FC<HookedInputSelectProps> = ({
[watched, ref]
)

const isAsync = props.loadAsyncValues != null

return (
<Controller
name={name}
Expand All @@ -84,17 +82,13 @@ export const HookedInputSelect: React.FC<HookedInputSelectProps> = ({
name={name}
ref={ref}
onBlur={onBlur}
defaultValue={
isAsync
? getDefaultValueFromFlatten({
initialValues: props.initialValues,
currentValue: value,
pathToValue
})
: undefined
}
defaultValue={getDefaultValueFromFlatten({
initialValues: props.initialValues,
currentValue: value,
pathToValue
})}
value={
!isAsync
formState.dirtyFields[name] !== true
? getDefaultValueFromFlatten({
initialValues: props.initialValues,
currentValue: value,
Expand Down
11 changes: 9 additions & 2 deletions packages/docs/src/mocks/data/tags.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// @ts-check

import { HttpResponse, http } from 'msw'

const mockedTags = Array(15)
Expand Down Expand Up @@ -25,9 +27,14 @@ const customerTags = http.get(

const organizationTags = http.get(
`https://mock.localhost/api/tags`,
async () => {
async ({ request }) => {
const url = new URL(request.url)
const name =
url.searchParams.get('filter[q][name_cont]')?.toLowerCase() ?? ''
return HttpResponse.json({
data: mockedTags,
data: mockedTags.filter((tag) =>
tag.attributes.name.toLowerCase().includes(name)
),
meta: { record_count: 100, page_count: 10 }
})
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import { CoreSdkProvider, useCoreSdkProvider } from '#providers/CoreSdkProvider'
import { MockTokenProvider as TokenProvider } from '#providers/TokenProvider/MockTokenProvider'
import { Button } from '#ui/atoms/Button'
import { Spacer } from '#ui/atoms/Spacer'
import { HookedForm } from '#ui/forms/Form'
import { HookedInputSelect } from '#ui/forms/InputSelect'
import { HookedInputSelect, type InputSelectValue } from '#ui/forms/InputSelect'
import { type Meta, type StoryFn } from '@storybook/react'
import { useEffect, useState } from 'react'
import { useForm } from 'react-hook-form'

const setup: Meta<typeof HookedInputSelect> = {
title: 'Forms/react-hook-form/HookedInputSelect',
component: HookedInputSelect,
parameters: {
layout: 'padded'
}
},
decorators: [
(Story) => (
<TokenProvider kind='integration' appSlug='orders' devMode>
<CoreSdkProvider>
<Story />
</CoreSdkProvider>
</TokenProvider>
)
]
}
export default setup

Expand Down Expand Up @@ -177,3 +189,78 @@ export const Clear: StoryFn<typeof HookedInputSelect> = () => {
</HookedForm>
)
}

export const AsyncAllIn: StoryFn<typeof HookedInputSelect> = () => {
const { sdkClient } = useCoreSdkProvider()
const [initialTags, setInitialTags] = useState<InputSelectValue[] | null>(
null
)
const [defaultTags, setDefaultTags] = useState<string[]>([])

const methods = useForm()

useEffect(() => {
void sdkClient.tags.list().then((tags) => {
setInitialTags(
tags.slice(0, 5).map((tag: any) => ({
value: tag.id,
label: tag.name
}))
)

setDefaultTags([tags[1]?.id, tags[3]?.id].filter((v) => v != null))
})
}, [])

useEffect(() => {
methods.reset({
tags: defaultTags
})
}, [defaultTags])

return (
<div
style={{
paddingBottom: '300px'
}}
>
<HookedForm
{...methods}
onSubmit={(values) => {
alert(JSON.stringify(values))
}}
>
<HookedInputSelect
name='tags'
isMulti
label='Search resource'
initialValues={initialTags ?? []}
loadAsyncValues={async (input) => {
const tags = await sdkClient.tags.list({
filters: { name_cont: input }
})

return tags.map((tag: any) => ({
value: tag.id,
label: tag.name
}))
}}
placeholder='Type to filter list...'
/>
<Spacer top='4'>
<Button
type='reset'
variant='secondary'
onClick={() => {
methods.reset()
}}
>
Reset
</Button>
&nbsp;&nbsp;&nbsp;
<Button type='submit'>Submit</Button>
</Spacer>
</HookedForm>
</div>
)
}

0 comments on commit 35610c3

Please sign in to comment.