没有选择和选项标签的角反应式下拉菜单

时间:2019-10-02 09:15:09

标签: html css angular dropdown angular-reactive-forms

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

  

众所周知,很难使用CSS有效地设置select元素的样式。

总而言之,即使结合使用,您也无法在选项和选择标签上使用任何技巧。

我希望继续使用反应式表单,但我希望通过仅使用<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;

1 个答案:

答案 0 :(得分:2)

您将“选项”部分创建为ul> li或div,然后相应地设置其样式。

诀窍是在鼠标单击或键盘交互时隐藏/显示此部分,但是为此您可以使用布尔变量(此处为expanded)。

这里有working 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: ['']
});