Hi,
I try to have a Form with Selects where options and initial value of one Select can be changed by the value of another one.
I managed to change options but not the initial value. Below, I post a sample code where I do not change options but only try to change the value by clicking on a button.
I think that the problem is that we must use an uncontrolled component into the form (as explained in the documentation).
I think that could be solved by using reset or setValue but they are not available in the Form API.
Does anyone have an idea?
Code of above gif:
import React from 'react';
import { PanelProps } from '@grafana/data';
import { SimpleOptions } from 'types';
import { css, cx } from 'emotion';
// Trick to make Input happy with css. See issue #26512 on Grafana's github
import {} from '@emotion/core';
import { stylesFactory, Form, Field, Button, Select, InputControl } from '@grafana/ui';
interface FormDTO {
cat: string;
cat2: string;
}
function onSubmit(formData: FormDTO) {
console.log('formData', formData);
}
const catOptions = [
{
label: 'Red',
value: 'red',
},
{
label: 'Blue',
value: 'blue',
},
];
const FormContext = React.createContext({});
interface Props extends PanelProps<SimpleOptions> {}
export const SimplePanel: React.FC<Props> = ({ options, data, width, height }) => {
const styles = getStyles();
const [catIndex, setCatIndex] = React.useState(0);
const toggleCatIndex = React.useCallback(function() {
setCatIndex(i => (i === 0 ? 1 : 0));
}, []);
return (
<div
className={cx(
styles.wrapper,
css`
width: ${width}px;
height: ${height}px;
`
)}
>
<Form onSubmit={(formData: FormDTO) => onSubmit(formData)}>
{({ register, control, errors, watch }) => (
<>
<FormContext.Provider value={{ register, control, errors }}>
<Field
label="InputControl with value"
/* By default Form component assumes form elements are uncontrolled .
There are some components like RadioButton or Select that are controlled-only and require some extra work.
To make them work with the form, you need to render those using InputControl component */
>
<InputControl
/* Render InputControl as controlled input (Select) */
as={Select}
/* Pass control exposed from Form render prop */
control={control}
name="cat"
options={catOptions}
disabled={true}
value={catOptions[catIndex]}
/>
</Field>
<Field
label="InputControl with defaultValue"
/* By default Form component assumes form elements are uncontrolled .
There are some components like RadioButton or Select that are controlled-only and require some extra work.
To make them work with the form, you need to render those using InputControl component */
>
<InputControl
/* Render InputControl as controlled input (Select) */
as={Select}
/* Pass control exposed from Form render prop */
control={control}
name="cat1"
options={catOptions}
disabled={true}
defaultValue={catOptions[catIndex]}
/>
</Field>
<Field label="Select with value">
<Select
options={catOptions}
value={catOptions[catIndex]}
disabled={true}
onChange={v => console.log(v)}
/>
</Field>
<Button variant="primary">Save</Button>
</FormContext.Provider>
<Button variant="secondary" onClick={toggleCatIndex}>
Toggle
</Button>
</>
)}
</Form>
</div>
);
};
const getStyles = stylesFactory(() => {
return {
wrapper: css`
position: relative;
`,
};
});