render()

in addons/addon-base-ui/packages/base-ui/src/parts/helpers/fields/DropDown.js [103:188]


  render() {
    const {
      field,
      selection,
      fluid,
      disabled,
      clearable,
      multiple,
      search,
      allowAdditions,
      additionLabel,
      className,
      options = [],
      onChange,
      dataTestId,
    } = this.props;

    const { id, value, sync, placeholder, error = '' } = field;
    const hasError = !_.isEmpty(error); // IMPORTANT do NOT use field.hasError

    const extra = field.extra || {};
    extra.options = extra.options || [];

    const mergeOptions = _.uniq([...this.optionsInState, ...extra.options, ...options]);

    const isDisabled = field.disabled || disabled;
    const disabledClass = isDisabled ? 'disabled' : '';
    const errorClass = hasError ? 'error' : '';

    /**
     * A utility function to see if the given component attribute is passed as an argument when rendering this component
     * or specified in the "extra" object.
     * The function returns the attribute value in the following order of precedence
     * 1. attribute value directly specified at the time of rendering the component (i.e., passed to the component), if the attribute was not passed then
     * 2. attribute value specified in the "extra" object of the given field, if it was not passed in the extra object as well then
     * 3. default attribute value
     *
     * @param attribName The name of the attribute
     * @param attribValue The attribute value that was passed when rendering the component
     * @param defaultAttribValue The default attribute value to use
     * @returns {*}
     */
    const getValue = (attribName, attribValue, defaultAttribValue) => {
      const fromExtra = extra && extra[attribName];
      // use specified attribValue if it is passed. If not, then try to use attrib value from the "extra" object
      let toUse = _.isNil(attribValue) ? fromExtra : attribValue;

      // if the attrib is neither passed nor in extra then use default value
      if (_.isNil(toUse)) {
        toUse = defaultAttribValue;
      }
      return toUse;
    };

    const attrs = {
      id,
      value: this.getDefaultValue(value, field),

      // applicable only when allowAdditions = true
      onAddItem: this.onAddItem,
      onChange: (e, data = {}) => {
        sync(data.value);
        field.validate({ showErrors: true });
        if (onChange) onChange(data.value, field);
      },
      placeholder,
      selection: getValue('selection', selection, DEFAULT_SELECTION),
      clearable: getValue('clearable', clearable, DEFAULT_CLEARABLE),
      multiple: getValue('multiple', multiple, DEFAULT_MULTIPLE),
      search: getValue('search', search, DEFAULT_SEARCH),
      fluid: getValue('fluid', fluid, DEFAULT_FLUID),
      allowAdditions: getValue('allowAdditions', allowAdditions, DEFAULT_ALLOW_ADDITIONS),
      disabled: getValue('disabled', isDisabled, DEFAULT_DISABLED),
      additionLabel: getValue('additionLabel', additionLabel, DEFAULT_ADDITION_LABEL),
      error: hasError,
    };

    return (
      <div className={c(getValue('className', className, DEFAULT_CLASS_NAME), errorClass, disabledClass)}>
        <Header field={field} />
        <Description field={field} />
        <Dropdown data-testid={dataTestId} className="field" options={mergeOptions} {...attrs} />
        <ErrorPointer field={field} />
      </div>
    );
  }