Search code examples
javascriptreactjsmaterial-uidownshift

Creating a label alongside an input using material-ui's TextField and getInputProps


I am using a material-ui TextField to create an input and a label for a typeahead picker type component with downshift.

I've seen the demos, and have got this:

<FormControl fullWidth className={classname}>
    <TextField fullWidth InputProps={ inputProps } InputLabelProps={ inputLabelProps } />
</FormControl>

My inputProps are equal to:

const inputProps = getInputProps({ //passed in by {...downshiftProps} on the parent
    onChange, onKeyDown, disabled, error, label, value: inputValue,
    startAdornment: selectedItems.map(item => ...)
});

const inputLabelProps = getLabelProps({ //passed in by {...downshiftProps} on the parent
    disabled, required, error, disabled, shrink: true, id: inputProps.id
});

My predecessor had those inputLabelProps attributes defined on a material-ui InputLabel component, but in an attempt to get the aria-labelledby attributes working, I've got with a single TextField.

Printing out the content of the input and label props gives:

//labelProps
{
    disabled: false,
    error: false,
    htmlFor: "downshift-0-input",
    id: "downshift-0-label",
    required: undefined,
    shrink: false
}

//inputProps
{
    aria-activedecendant: null,
    aria-autocomplete: "list"
    aria-controls: null,
    aria-labelledby: "downshift-0-label",
    autoComplete: "off"
    disabled: false,
    error: false,
    id: "downshift-0-input",
    onBlur: f(event),
    onChange: f(event),
    onKeyDown: f(event),
    startAdornment: [],
    value: ""
}

My issue is that no label is rendered to the DOM. The closest I get is a div with a label attribute, that wraps the input, but displays nothing.

p.s. I've seen Material-ui textfield with label but I don't think FloatingLAbelText exists anymore? The link in the answers is out of date, and not compatible with the propGetters pattern.


Solution

  • Here is a slightly simplified version of the demo mentioned in the comments:

    Edit Material demo

    The DownshiftMultiple portion of the demo used a label. I've only included the first downshift demo in my sandbox, but modified it to use a label in the same manner as the "multiple" demo. The label doesn't belong in the InputLabelProps, it is just a property of TextField. In the demo, this is a little confusing to follow because label is specified as a property on the object passed to renderInput so it just ends up as part of the ...other object that is the spread onto TextField.

    If you look at the relevant code for TextField you'll see:

        {label && (
          <InputLabel htmlFor={id} ref={this.labelRef} {...InputLabelProps}>
            {label}
          </InputLabel>
        )}
    

    Here you see that the InputLabelProps don't impact the content of the label, just the other properties that affect its rendering, so you need label as a property directly on TextField.