Unable to see results with AsyncTypeahead with multiple option and renderInput - react-bootstrap-typeahead

I'm trying to use a custom Input component on a Typeahead with the multiple option set. I see in the docs it says to "handle the refs" correctly, but I see no examples of how this is done. I'm not sure what to pass into referenceElementRef. Everything I've tried so far just doesn't render the options as I type. I see them in the DOM, but the opacity of the .rbt-menu is set to 0, so they're basically hidden.
Here's my code so far:
const divRef = React.useRef(null);
return (
<Col>
<div ref={divRef}>
<span className="uppercase">
<FormattedMessage id="d.customer" defaultMessage="Customer" tagName="h4" />
</span>
<AsyncTypeahead
multiple
id="customer-filter-input"
inputProps={{
'aria-label': 'Customer search',
style: { fontSize: '14px' },
}}
key={'customer-input'}
minLength={4}
isLoading={props.isLoadingcustomersSuggestions}
delay={300}
onSearch={(term: string) => handleFilterInputs(term, 'customers')}
size={'lg'}
options={dataSource}
labelKey={'defaultMessage'}
placeholder={intl.formatMessage({
id: 'companyName',
defaultMessage: 'Company name',
})}
onChange={(filterItem: any) => handleAutocompleteUpdate(filterItem, 'customer')}
renderInput={({ inputRef, referenceElementRef, ...inputProps }: any) => (
<Input
{...inputProps}
style={{ position: 'relative' }}
ref={(input: any) => {
inputRef(input);
referenceElementRef(divRef); // What do I put here?
}}
/>
)}
/>
</div>
</Col>
);
And this is what renders in the DOM after I type in the Typeahead and get results:
Any ideas or working examples of Typeahead using multiple and renderInput together?
EDIT:
Here's a codesandbox of what I'm seeing. I also see that the problem is also happening when multiple is NOT set. It seems to be an issue with using renderInput. Is it required that I also use renderMenu?
https://codesandbox.io/s/react-bootstrap-typeahead-async-pagination-example-forked-3kz3z

If you upgrade the typeahead version in your sandbox to the latest version (v5.1.1) and pass the input element to referenceElementRef, it works (note that you need to type some characters into the input for the menu to appear):
// v5.0 or later
renderInput={({ inputRef, referenceElementRef, ...inputProps }) => (
<Input
{...inputProps}
ref={(input) => {
inputRef(input);
referenceElementRef(input);
}}
/>
)}
The menu is rendered in relation to the referenceElementRef node by react-popper. In most common cases, the reference node will be the input itself. The reason there's both an inputRef and a referenceElementRef is for more complex cases (like multi-selection) where the menu needs to be rendered in relation to a container element around the input.
If using v4 of the component, the approach is similar, but the ref to use is simply called ref:
// v4
renderInput={({ inputRef, ref, ...inputProps }) => (
<Input
{...inputProps}
ref={(input) => {
inputRef(input);
ref(input);
}}
/>
)}

Related

Vite React VScode. Errors not underlined, no warnings etc

I've just started assembling my projects with Vite. And noticed that VSCode doesn't inform you about your mistakes anymore. Component just doesn't work properly and I don't see any underlines. So I did something like this:
const BasketItem = ({ removeFrromOrder, id, name, price, quantity }) => {
return (
<ListItem>
<Typography variant='body1'>
{name} {price}руб x{quantity}
</Typography>
<IconButton onClick={() => removeFrromOrder(id)}>
<Close />
</IconButton>
</ListItem>
);
};
<BasketItem key={item.name} removeFromOrder={removeFromOrder} {...item} />
Nothing is underlined. Usually the last string of code would be underlined since component expects removeFrromOrder with two 'r' (which is typo :)
Any ideas why it would be happening? Is it connected with Vite in any way?

#mui/lab/DateRangePicker - How to add custom toolbar with action buttons above and under calendar

I'm using DateRangePicker from #mui/lab and now, there is need to add custom toolbar with action buttons above or under calendar (for example, buttons apply or cancel). I struggled to find solution but couldn't find something useful. It should be on both desktop and mobile versions of datepicker.
For all those who suffer from the lack of simple and necessary solutions.
Hope this will help 🫡
Here the docs, but there is huge lack of information and examples
<LocalizationProvider dateAdapter={AdapterDateFns} localeText={{ start: 'from', end: 'to' }}>
<DateRangePicker
components={{ //edit component
PaperContent: data => { //exactly PaperContent
const childCopy = [...data.children]; //duplicate to avoid errors
const Component = () => <Box>BUILD YOUR COMPONENT</Box>;
childCopy.push(<Component />);
return childCopy; //return array of childrens
}
}}
value={value}
onChange={newValue => {
setValue(newValue);
}}
renderInput={(startProps, endProps) => (
<>
<MNVTTextField {...startProps} />
<Box>-</Box>
<MNVTTextField {...endProps} />
</>
)}
/>
</LocalizationProvider>;

Trying to create a draggable table/list and it gives me error saying 'provided.innerRef has not been provided with a HTMLElement.'

I am trying to create a draggable list using Material UI and react-beautiful-dnd. I followed the tutorial on their page and created this-
function DraggableList(props) {
const { classes, tableHeaders, tasksList } = props;
return (
<div>
<Droppable droppableId="id">
{(provided) => (
<div ref={provided.innnerRef} {...provided.droppableProps}>
{tasksList && tasksList.slice(0,5).map((row, index) => (
<Draggable draggableId={row.id} index={index}>
{(provided)=> (
<div index={index} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
<Paper className={classes.root} key={row.id}>
<Grid container xs={12} className={classes.topContainer}>
<Grid item xs={2}>
<IconButton><DragIndicatorIcon className={classes.dragIcon}/></IconButton> </Grid>
<Grid item xs={10}>
<Typography className={classes.activity} variant="body2">{row.name}</Typography>
</Grid>
</Grid>
</Paper>
</div>
)}
</Draggable>
))}
</div>
)}
</Droppable>
</div>
);
}
It keeps giving me
Error: Invariant failed:
provided.innerRef has not been provided with a HTMLElement.
You can find a guide on using the innerRef callback functions at:
https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/guides/using-inner-ref.md
error though I am setting innerRef on a 'div' . What is the mistake here
Typo:
ref={provided.innnerRef}
I had the same problem, but my solution was quite different. I made the silly mistake of using curly bracket instead of parentheses. So I did:
{(provided) => {
And not:
{(provided) => (
No error indications whatsoever other than "provided.innerRef has not been provided with a HTMLElement."
You put
provided={provided}
in the same div it will start working. I also had the same issue but it got resolved with this.
I had the same problem and I used styled-components. I just set the ref prop on the styled-component element and it worked for me.
I mean this:
const StyledElement = styled.div`
//the css goes in here
`;
<StyledElement ref={provided.innerRef} {...provided.droppableProps}>
//The rest of the code goes here
<StyledElement/>

React: how to use child FormItem components without getting Warning: validateDOMNesting: <form> cannot appear as a descendant of <form>

Given the parent component, I am using a child component DynamicFieldSet that is a grouping of FormItems. But I am receiving the error:
Warning: validateDOMNesting(...): <form> cannot appear as a descendant of <form>. See CreateTopic > Form > form > ... > DynamicFieldSet > Form > form.
I have tried to remove the <Form> </Form> tags in my child component, but then it is a compile error.
Is there a way I can disable rendering of the child Form view?
Parent component
class CreateTopic extends React.Component {
render() {
return (
<div className="create-topic-container">
<h3>Create an event</h3>
<Form onSubmit={this.handleSubmit}>
<FormItem>...</FormItem>
<FormItem>...</FormItem>
<FormItem>...</FormItem>
<FormItem
{...formItemLayout}
label="Results"
style={{ marginBottom: SPACING_FORM_ITEM }}
>
{getFieldDecorator('results', {
rules: [
{
required: true,
message: 'Results cannot be empty.',
},
],
})(<DynamicFieldSet
form={this.props.form}
/>)}
</FormItem>
</Form>
</div>
);
}
}
DynamicFieldSet - Child component
export class DynamicFieldSet extends React.Component {
render() {
getFieldDecorator('keys', { initialValue: ['0', '1'] });
const keys = getFieldValue('keys');
const formItems = keys.map((k, index) => {
return (
<FormItem
{...formItemLayoutWithOutLabel}
required={false}
key={k}
>
{getFieldDecorator(`results[${k}]`, {
validateTrigger: ['onChange', 'onBlur'],
rules: [
{
required: true,
whitespace: true,
message: 'Result name cannot be empty.',
},
{
validator: this.validateLength,
},
],
})(<Input placeholder={`Result #${index + 1}`} style={{ width: '80%', marginRight: 8 }} />)}
{keys.length > 2 ? (
<Icon
className="dynamic-delete-button"
type="minus-circle-o"
disabled={keys.length === 1}
onClick={() => this.remove(k)}
/>
) : null}
</FormItem>
);
});
return (
<Form>
{formItems}
<FormItem {...formItemLayoutWithOutLabel}>
{keys.length < 10 ? (
<Button type="dashed" onClick={this.add} style={{ width: '80%' }}>
<Icon type="plus" />Add Result
</Button>
) : null}
</FormItem>
</Form>
);
}
}
I faced this issue when using ant design table and turns out its not ant design which throws the warning. It's the web standards description
"Every form must be enclosed within a FORM element. There can be several forms in a single document, but the FORM element can't be nested."
So, there should not be a form tag inside a form tag.
To solve the issue (in our case), remove the Form tag inside the DynamicFieldSet "return" and replace with a div tag
Hope it helps :)
You can portal a form like this:
import Portal from '#material-ui/core/Portal';
const FooComponent = (props) => {
const portalRef = useRef(null);
return <>
<form>
First form
<div ref={portalRef} />
</form>
<Portal container={portalRef.current}>
<form>Another form here</form>
</Portal>
</>;
}
In the example above I use the react material-ui Portal component. But you can try to implement it with React Portals as well
If you're using MUI, the Box component contains an attribute that identifies them as any native HTML container; form is one of them. E.g:
<Box
xs={6}
sx={{
"& > :not(style)": { m: 1, width: "25ch" },
}}
component="form"
noValidate
autoComplete="off"
>
In such case, we just need to delete that attribute, it will default to a DIV. The form will continue to work as expected, and the error will disappear off the console.
In my case this is occur bcoz of i declared <form> inside another <form/> tag.

Jquery tokeninput and unobtrusive validation in a MVC 4 application

I am stuck here and would very much appreciate help. I have a form in a razor view with a input field for current city which looks like this:
#Html.LabelFor(x => x.UserModel.CurrentCity)
#Html.TextBoxFor(x => x.UserModel.CurrentCity, new { #data_bind = "value: UserModel.CurrentCity ", #class = "city", #data_val = "true", #data_val_required="City is required" })
#Html.ValidationMessageFor(x => x.UserModel.CurrentCity)
I want autocomplete for this field and am using jquery token input plugin for this like:
$(".city").tokenInput('#Url.Action("AutocompleteCity", "Settings")',{ minChars: 2, tokenLimit: 1, hintText: "Type in a city" });
$(".city").tokenInput("add", {name: viewModel.UserModel.CurrentCity()});
Everything works fine except the clientside unobtrusive validation. The form gets posted even if CurrentCity is empty.
I also tried to change the MVC helpers to plain html:
<input data-val="true" data-val-required="City is required" type="text" class="city" data-bind = "value: UserModel.CurrentCity, attr: { name: 'UserModel.CurrentCity', id: 'UserModel.CurrentCity'}" />
<span class="field-validation-valid" data-valmsg-for="UserModel.CurrentCity" data-valmsg-replace="true"></span>
This approach prevents the form from being submitted but the validation-error class is not injected into the span and the error message does not show up.
Any suggestions?
The original input element you created is hidden. You will likely need to enable validation of hidden elements: jquery.validate v. 1.9 ignores some hidden inputs or https://stackoverflow.com/a/13295938/173225.