addOption(value, label, attrs = {}, id = getRandomComponentId()) {
    if (_.isNil(label)) return;
    const idPath = this.component.idPath
      ? this.component.idPath.split('.').reduceRight((obj, key) => ({ [key]: obj }), id)
      : {};
    const option = {
      value: this.getOptionValue(value),
      label,
      ...idPath
    };

    const skipOption = this.component.uniqueOptions
      ? !!this.selectOptions.find((selectOption) => _.isEqual(selectOption.value, option.value))
      : false;

    if (skipOption) {
      return;
    }

    if (value) {
      this.selectOptions.push(option);
    }

    if (this.refs.selectContainer && (this.component.widget === 'html5')) {
      // Replace an empty Object value to an empty String.
      if (option.value && _.isObject(option.value) && _.isEmpty(option.value)) {
        option.value = '';
      }
      // Add element to option so we can reference it later.
      const div = document.createElement('div');
      div.innerHTML = this.sanitize(this.renderTemplate('selectOption', {
        selected: _.isEqual(this.getOptionValue(this.dataValue), option.value),
        option,
        attrs,
        id,
        useId: (this.valueProperty === '' || this.isEntireObjectDisplay()) && _.isObject(value) && id,
      }), this.shouldSanitizeValue).trim();

      option.element = div.firstChild;
      this.refs.selectContainer.appendChild(option.element);
    }
  }
Adds an option to the select dropdown.
@param {*} value - The value of the new option.
@param {string} label - The label of the new option.
@param {object} [attrs] - Additional value attributes. Defaults to {}.
@param {string} [id] - An id. Defaults to a random string.