11import React , { useState } from 'react' ;
22import {
33 Form ,
4- FormSelect ,
5- FormSelectOption ,
4+ Select ,
5+ SelectOption ,
6+ SelectList ,
7+ MenuToggle ,
8+ MenuToggleElement ,
69} from '@patternfly/react-core' ;
710import { FieldBuilder } from '@patternfly/react-component-groups/dist/dynamic/FieldBuilder' ;
811
@@ -16,12 +19,19 @@ export const FieldBuilderSelectExample: React.FunctionComponent = () => {
1619 { department : '' , role : '' }
1720 ] ) ;
1821
22+ // State for managing which select dropdowns are open
23+ const [ departmentOpenStates , setDepartmentOpenStates ] = useState < boolean [ ] > ( [ false ] ) ;
24+ const [ roleOpenStates , setRoleOpenStates ] = useState < boolean [ ] > ( [ false ] ) ;
25+
1926 // Handle adding a new team member row
2027 const handleAddTeamMember = ( event : React . MouseEvent ) => {
2128 // eslint-disable-next-line no-console
2229 console . log ( 'Add button clicked:' , event . currentTarget ) ;
2330 const newTeamMembers = [ ...teamMembers , { department : '' , role : '' } ] ;
2431 setTeamMembers ( newTeamMembers ) ;
32+ // Add new open states for the selects
33+ setDepartmentOpenStates ( [ ...departmentOpenStates , false ] ) ;
34+ setRoleOpenStates ( [ ...roleOpenStates , false ] ) ;
2535 } ;
2636
2737 // Handle removing a team member row
@@ -30,6 +40,9 @@ export const FieldBuilderSelectExample: React.FunctionComponent = () => {
3040 console . log ( 'Remove button clicked:' , event . currentTarget , 'for index:' , index ) ;
3141 const newTeamMembers = teamMembers . filter ( ( _ , i ) => i !== index ) ;
3242 setTeamMembers ( newTeamMembers ) ;
43+ // Remove corresponding open states
44+ setDepartmentOpenStates ( departmentOpenStates . filter ( ( _ , i ) => i !== index ) ) ;
45+ setRoleOpenStates ( roleOpenStates . filter ( ( _ , i ) => i !== index ) ) ;
3346 } ;
3447
3548 // Handle updating team member data
@@ -39,6 +52,36 @@ export const FieldBuilderSelectExample: React.FunctionComponent = () => {
3952 setTeamMembers ( updatedTeamMembers ) ;
4053 } ;
4154
55+ // Handle department select open/close
56+ const handleDepartmentToggle = ( index : number ) => {
57+ const newOpenStates = [ ...departmentOpenStates ] ;
58+ newOpenStates [ index ] = ! newOpenStates [ index ] ;
59+ setDepartmentOpenStates ( newOpenStates ) ;
60+ } ;
61+
62+ // Handle role select open/close
63+ const handleRoleToggle = ( index : number ) => {
64+ const newOpenStates = [ ...roleOpenStates ] ;
65+ newOpenStates [ index ] = ! newOpenStates [ index ] ;
66+ setRoleOpenStates ( newOpenStates ) ;
67+ } ;
68+
69+ // Handle department selection
70+ const handleDepartmentSelect = ( index : number , _event : React . MouseEvent < Element , MouseEvent > | undefined , value : string | number | undefined ) => {
71+ handleTeamMemberChange ( index , 'department' , value as string ) ;
72+ const newOpenStates = [ ...departmentOpenStates ] ;
73+ newOpenStates [ index ] = false ;
74+ setDepartmentOpenStates ( newOpenStates ) ;
75+ } ;
76+
77+ // Handle role selection
78+ const handleRoleSelect = ( index : number , _event : React . MouseEvent < Element , MouseEvent > | undefined , value : string | number | undefined ) => {
79+ handleTeamMemberChange ( index , 'role' , value as string ) ;
80+ const newOpenStates = [ ...roleOpenStates ] ;
81+ newOpenStates [ index ] = false ;
82+ setRoleOpenStates ( newOpenStates ) ;
83+ } ;
84+
4285 // Custom announcement for adding rows
4386 const customAddAnnouncement = ( rowNumber : number , rowGroupLabelPrefix : string ) => `New ${ rowGroupLabelPrefix . toLowerCase ( ) } ${ rowNumber } added.` ;
4487
@@ -62,18 +105,6 @@ export const FieldBuilderSelectExample: React.FunctionComponent = () => {
62105 return `Remove ${ rowGroupLabelPrefix . toLowerCase ( ) } in row ${ rowNumber } ` ;
63106 } ;
64107
65- // Create a ref callback that works with FormSelect
66- const createFormSelectRef = ( focusRef : ( element : HTMLElement | null ) => void ) =>
67- ( instance : React . ComponentRef < typeof FormSelect > | HTMLElement | null ) => {
68- if ( instance ) {
69- // Get the underlying DOM element from the FormSelect instance
70- const domElement = ( instance as any ) ?. ref ?. current || instance ;
71- if ( domElement instanceof HTMLElement ) {
72- focusRef ( domElement ) ;
73- }
74- }
75- } ;
76-
77108 const departmentOptions = [
78109 { label : 'Choose a department' , value : '' , disabled : true } ,
79110 { label : 'Engineering' , value : 'engineering' } ,
@@ -110,39 +141,90 @@ export const FieldBuilderSelectExample: React.FunctionComponent = () => {
110141 addButtonContent = "Add team member"
111142 >
112143 { ( { focusRef, firstColumnAriaLabel, secondColumnAriaLabel } , index ) => [
113- < FormSelect
144+ < Select
114145 key = "department"
115- ref = { createFormSelectRef ( focusRef ) }
116- value = { teamMembers [ index ] ?. department || '' }
117- onChange = { ( event , value ) => handleTeamMemberChange ( index , 'department' , value ) }
118- aria-label = { firstColumnAriaLabel }
119- isRequired
146+ id = { `department-select-${ index } ` }
147+ isOpen = { departmentOpenStates [ index ] || false }
148+ selected = { teamMembers [ index ] ?. department || '' }
149+ onSelect = { ( event , value ) => handleDepartmentSelect ( index , event , value ) }
150+ onOpenChange = { ( isOpen ) => {
151+ const newOpenStates = [ ...departmentOpenStates ] ;
152+ newOpenStates [ index ] = isOpen ;
153+ setDepartmentOpenStates ( newOpenStates ) ;
154+ } }
155+ toggle = { ( toggleRef : React . Ref < MenuToggleElement > ) => (
156+ < MenuToggle
157+ ref = { ( element ) => {
158+ // Handle both the toggle ref and focus ref
159+ if ( typeof toggleRef === 'function' ) {
160+ toggleRef ( element ) ;
161+ } else if ( toggleRef && 'current' in toggleRef && toggleRef . current !== element ) {
162+ ( toggleRef as React . MutableRefObject < MenuToggleElement | null > ) . current = element ;
163+ }
164+ focusRef ( element ) ;
165+ } }
166+ onClick = { ( ) => handleDepartmentToggle ( index ) }
167+ isExpanded = { departmentOpenStates [ index ] || false }
168+ aria-label = { firstColumnAriaLabel }
169+ style = { { width : '100%' } }
170+ >
171+ { teamMembers [ index ] ?. department ?
172+ departmentOptions . find ( opt => opt . value === teamMembers [ index ] ?. department ) ?. label || 'Choose a department'
173+ : 'Choose a department' }
174+ </ MenuToggle >
175+ ) }
176+ shouldFocusToggleOnSelect
120177 >
121- { departmentOptions . map ( ( option , optionIndex ) => (
122- < FormSelectOption
123- key = { optionIndex }
124- value = { option . value }
125- label = { option . label }
126- isDisabled = { option . disabled }
127- />
128- ) ) }
129- </ FormSelect > ,
130- < FormSelect
178+ < SelectList >
179+ { departmentOptions . map ( ( option , optionIndex ) => (
180+ < SelectOption
181+ key = { optionIndex }
182+ value = { option . value }
183+ isDisabled = { option . disabled }
184+ >
185+ { option . label }
186+ </ SelectOption >
187+ ) ) }
188+ </ SelectList >
189+ </ Select > ,
190+ < Select
131191 key = "role"
132- value = { teamMembers [ index ] ?. role || '' }
133- onChange = { ( event , value ) => handleTeamMemberChange ( index , 'role' , value ) }
134- aria-label = { secondColumnAriaLabel }
135- isRequired
192+ id = { `role-select-${ index } ` }
193+ isOpen = { roleOpenStates [ index ] || false }
194+ selected = { teamMembers [ index ] ?. role || '' }
195+ onSelect = { ( event , value ) => handleRoleSelect ( index , event , value ) }
196+ onOpenChange = { ( isOpen ) => {
197+ const newOpenStates = [ ...roleOpenStates ] ;
198+ newOpenStates [ index ] = isOpen ;
199+ setRoleOpenStates ( newOpenStates ) ;
200+ } }
201+ toggle = { ( toggleRef : React . Ref < MenuToggleElement > ) => (
202+ < MenuToggle
203+ ref = { toggleRef }
204+ onClick = { ( ) => handleRoleToggle ( index ) }
205+ isExpanded = { roleOpenStates [ index ] || false }
206+ aria-label = { secondColumnAriaLabel }
207+ style = { { width : '100%' } }
208+ >
209+ { teamMembers [ index ] ?. role ?
210+ roleOptions . find ( opt => opt . value === teamMembers [ index ] ?. role ) ?. label || 'Choose a role'
211+ : 'Choose a role' }
212+ </ MenuToggle >
213+ ) }
214+ shouldFocusToggleOnSelect
136215 >
137- { roleOptions . map ( ( option , optionIndex ) => (
138- < FormSelectOption
139- key = { optionIndex }
140- value = { option . value }
141- label = { option . label }
142- isDisabled = { option . disabled }
143- />
144- ) ) }
145- </ FormSelect >
216+ < SelectList >
217+ { roleOptions . map ( ( option , optionIndex ) => (
218+ < SelectOption
219+ key = { optionIndex }
220+ value = { option . value }
221+ isDisabled = { option . disabled }
222+ >
223+ { option . label }
224+ </ SelectOption >
225+ ) ) }
226+ </ SelectList >
227+ </ Select >
146228 ] }
147229 </ FieldBuilder >
148230 </ Form >
0 commit comments