reactjsmaterial-ui

Why is the renderValue function not being called? I want to give the Select dropdown a placeholder


The "renderValue" function is not working. I want to give the Select dropdown a custom placeholder but it doesn't work.

Here's the Select component:

<Select
            className={classNames({ error: !!error })}
            labelId={name}
            id={name}
            value={multiple ? value || [] : value}
            disabled={disabled}
            multiple={multiple}
            onChange={(event) => {
              onChange(event);
              if (handleChange) handleChange(event.target);
            }}
            renderValue={(selected) => {
              if (!selected) {
                return <em>Placeholder</em>;
              }
            }}
            MenuProps={menuProps}
            endAdornment={
              showCrossIcon && (
                <IconButton
                  sx={{ visibility: value ? 'visible' : 'hidden', position: 'absolute', right: '20px', zIndex: '1' }}
                  disableRipple
                  onClick={() => {
                    onChange('');
                  }}
                >
                  <CrossIcon />
                </IconButton>
              )
            }
            sx={{ paddingRight: '0px' }}
          >
            {options.map((item) => {
              const isLabelValueOption =
                typeof item === 'object' && item.hasOwnProperty('label') && item.hasOwnProperty('value');
              const optionLabel = isLabelValueOption ? item.label : item;
              const optionValue = isLabelValueOption ? item.value : item;
              return (
                <MenuItem key={optionLabel} value={optionValue} className="menu-item">
                  <div data-testid="menu-items" className="multi-select">
                    <OverflowText sx={{ margin: '0px' }}>{optionLabel}</OverflowText>
                  </div>
                </MenuItem>
              );
            })}
          </Select>

It's a reusable component. To give more context, here's where it coming from:

<SelectFormField
            data-testid="timeGrain"
            fieldType="Select"
            fieldSize="medium"
            tableSelect={true}
            name="timeGrain"
            label="Time Grain"
            control={control}
            options={timeGrainOptionsList}
            defaultValue={R.pathOr('P1D', ['time', 'timeGrain', 'defaultValue'], configurationTemplate)}
            required={R.pathOr(false, ['time', 'timeGrain', 'required'], configurationTemplate)}
          />

and then:

export const SelectFormField: React.FC<SelectProps & AdditionalFormFieldProps> = (props) => {
  const { name, defaultValue, control } = props;
  return (
    <Controller
      name={name}
      control={control}
      defaultValue={defaultValue}
      render={({ field: { onChange, value }, fieldState: { error } }) => (
        <SelectField {...props} value={value} onChange={onChange} error={error} />
      )}
    />
  );
};

I have followed the MUI Select component documentation it seems to be the right way to give it a placeholder. Why is it not working?


Solution

  • I think that the issue is in the renderValue function. As per your code, the render value would only return Placeholder text when there is no selected option. But in the case when there is a selected option, it will return nothing. So what you want to do is update the renderValue function as below:

    renderValue={(selected) => {
       if (!selected || selected.length === 0) {
         return <em>Placeholder</em>;
       } else if(Array.isArray(selected){
         return selected.join(', ');
       } else {
         return selected
       }
     }}