react-bootstrap-typeahead

React-Bootstap-Typeahead: Manually set custom display value in onChange() upon menu selection


In the onChange of React-Bootstrap-Typeahead, I need to manually set a custom display value. My first thought was to use a ref and do something similar to the .clear() in this example.

But although .clear() works, inputNode.value = 'abc' does not work, and I'm left with the old selected value from the menu.

onChange={option => {
     typeaheadRef.current.blur(); // This works
     typeaheadRef.current.inputNode.value = 'abc'; // This does not work (old value is retained)
}}

I also tried directly accessing the DOM input element, whose ID I know, and doing

var inputElement = document.querySelector('input[id=myTypeahead]');
inputElement.value = 'abc';

But that didn't work either. For a brief second, right after my changed value = , I do see the new display label, but then it's quickly lost. I think the component saves or retains the menu-selected value.

Note: I cannot use selected, I use defaultSelected. I have some Formik-related behavior that I've introduced, and it didn't work with selected, so I'm stuck with defaultSelected.


Solution

  • The only workaround I found is to re-render the Typeahead component (hide and re-show, from a blank state) with a new defaultSelected="abc" which is a one-time Mount-time value specification for the control.

    I couldn't get selected=.. to work, I have a wrapper around the component which makes it fit into Formik with custom onChange and onInputChange and selected wasn't working with that.

    So the simple workaround that works is, if the visibility of the Typeahead depends on some condition (otherwise it won't be rendered), use that to momentarily hide and re-show the component (a brand new repaint) with a new defaultSelected, e.g.

    /* Conditions controlling the visibility of the Typeahead */
    !isEmptyObject(values) &&
    (values.approverId === null || (values.approverId !== null && detailedApproverUserInfo) 
    )
    &&
        <AsyncTypehead defaultSelected={{...whatever is needed to build the string, or the literal string itself...}}
         ..
         
       // Given the above visibility condition, we'll hide/re-show the component
       // The below will first hide the control in React's renders
       setFieldValue("approver", someId);
       setDetailedUserInfo(null);
       // The below will re-show the control in React's renders, after a small delay (a fetch)
       setDetailedUserInfo(fetchDetailedUserInfo());