首页 > 解决方案 > 没有选择和选项标签的角反应形式下拉菜单

问题描述

我在设置下拉列表时遇到了困难:https ://developer.mozilla.org/en-US/docs/Web/HTML/Element/select#Styling_with_CSS

众所周知,选择元素很难使用 CSS 高效地设置样式。

总之,即使结合使用,您可以在选项和选择标签上使用的任何技巧都不值得。

我很想继续使用响应式表单,但我希望通过仅使用<div>标签来绘制并以响应式表单使用我的下拉列表来净化我的 html 和 css。

这可能吗?

这是我今天存在的代码。

// 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;

标签: htmlcssangulardropdownangular-reactive-forms

解决方案


您将“选项”部分创建为 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 样式

.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: ['']
});

推荐阅读