Угловая раскрывающаяся форма без тегов выбора и опции - PullRequest
2 голосов
/ 02 октября 2019

Я столкнулся с трудностями при стилизации моего выпадающего списка: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#Styling_with_CSS

Элемент select общеизвестно сложно продуктивно стилизовать с помощью CSS.

в итоге ни один из хаковВы можете использовать опцию и выбирать теги, которые стоят их соли даже в комбинации.

Я бы хотел продолжать использовать реактивные формы, но я хочу очистить мои html и css, используя только теги <div> для рисованияи использовать мой выпадающий в реактивной форме.

возможно ли это?

вот мой код, как он существует сегодня.

// this.statusForm = this.fb.group({
//    status: ['Delivered', Validators.required]
// });
<form [formGroup]="statusForm">
   <select formControlName="status">
      <option value="Delivered">Delivered</option><!--&#xf00c;-->
      <option value="Cancelled">Cancelled</option><!--&#xf05e;-->
      <option value="UndeliveredTechnicalissue">Undelivered/Technical issue</option><!--&#xf00d;-->
   </select>
</form>

js - это просто гидратация FormBuilder.

Я могу собрать / console.log () значение, используя

 this.statusForm.value.status;

1 Ответ

2 голосов
/ 02 октября 2019

Вы создаете часть «options» как ul> li или div и затем соответственно ее стилизуете.

Хитрость заключается в том, чтобы скрыть / показать эту часть при щелчке мышью или взаимодействии с клавиатурой, но для этого вы можете использоватьлогическая переменная (здесь expanded).

Здесь рабочий Stackblitz .

Если вы хотите посмотреть код только в одномстраницы, посмотрите на код ниже:

шаблон

<div class="select-container">
  <input type="text"      
      [id]="customId"
      [placeholder]="placeholder"
      [value]= "selectedValue"
      [disabled]="disabled"
      (click)="showOptions()"/>
  <ul class="select-menu box" role="listbox" *ngIf="expanded">   
      <li role="option"
          *ngFor="let option of options; let i = index;" 
          [id]="customId + '-option-' + i" 
          [title]="option.label"
          class="option-item"
          [ngClass]="{ 'selected': activeItemIndex === i }"
          (click)="selectItem(option)">
          <span> {{option.label}}</span>
      </li>
    </ul>
</div>

компонент

@Component({
  selector: 'form-select',
  templateUrl: './form-select.component.html',
  styleUrls: ['./form-select.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      multi: true,
      useExisting: forwardRef(() => FormSelectComponent)
    }
  ]
})
export class FormSelectComponent implements ControlValueAccessor{

  public selectedValue = '';
  public disabled = false;
  public value: string;

  @Input()
  label: string;

  @Input()
  formCtrl: AbstractControl;

  @Input()
  pipe: { type?: string; params?: any };

  @Input()
  options: {key: string, label: string}[] = [];

  @Input()
  customId: string;

  @Input()
  placeholder: string;

  public expanded = false;

  public activeItemIndex: number;


public onChange(newVal: T) {}

public onTouched(_?: any) {}

public registerOnChange(fn: any): void {
    this.onChange = fn;
  }

public registerOnTouched(fn: any): void {
    this.onTouched = fn;


writeValue(value: string) {
    if (value && this.options) {
      const match = this.options.find(
        (item: { type?: string; params?: any }, index: number) => {
          if (item.key === value) {
            this.activeItemIndex = index;
            return true;
          }
        }
      );
      this.selectedValue = match ? match.label : '';
    }
  }

  showOptions() {
    if (!this.disabled) {
      this.expanded = true;
    }
  }

  selectItem(item: {key: string, label: string}) {
    this.value = item.key;
    this.expanded = false;
    this.selectedValue = item.label;
    this.onChange(item.key);
  }
}

scss styles

.select-container {
  position: relative;

  .input-container {
    i {
      position: absolute;
      top: 1rem;
      right: 1rem;
    }
    input[type='text'] {
      overflow-x: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      padding-right: 2rem;
    }

  }

  .select-menu {
    width: 100%;
    z-index: 100;
    max-height: 17.75rem;
    overflow: auto;
    position: absolute;
    top: -5px;
    right: 0;
    background-color: white;
    border: 1px solid gray;
    padding: 1rem;
    box-sizing: border-box;

    .option-item {
      padding-left: 1rem;
      line-height: 3rem;
      color: gray;
      overflow-x: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      margin: 0 -1rem;

      &:last-child {
        margin-bottom: 0;
      }

      &.selected,
      &:hover {
        background-color: lightgray;
        color: black;
      }

      &:focus {
        outline: none;
      }
    }
  }
}

Как использовать это:

В шаблоне:

<form [formGroup]="mainFormGroup">
    <form-select formControlName="myControl" [options]="options">
     </form-select>
  </form>

в компоненте:

const options = [{
        key: key1,
        label: 'value_1'
      }, {
        key: key2,
        label: 'value_2'
      }];

this.mainFormGroup = this.fb.group({
  myControl: ['']
});
...