Style a HTML select according to the selected option in Angular.

huangapple go评论62阅读模式
英文:

Style a HTML select according to the selected option in Angular

问题

I will provide a translation of the code-related content you provided:

我想要为 Angular 组件中的 *select* 元素样式不同的情况当选择了具有非活动属性的特定选项时

我的组件如下所示
```javascript
class ComponentWithSelect {
  @Input() ngModel: unknown = null;
  @Input() options: { value: unknown, label: string, disabled: boolean }[]

  inactiveSelected: boolean = false;
  ...
}

对应的模板如下:

<select
  [ngModel]="ngModel"
  [class.inactive-select]="inactiveSelected">
  <option *ngFor="let option of options"
    [ngValue]="option.value"
    [disabled]="option.disabled">
    {{option.label}}
  </option>
</select>

我想在选择具有非活动属性的选项时应用 inactive-select 类,或者在从外部传递了与具有非活动属性的选项相对应的 ngModel 到组件时。

我尝试使用 (ngModelChange) 来设置 inactiveSelected 属性,但传递给对应方法(onModelChange)的 $event 参数包含选定选项的 value,而不是非活动属性。

我可以使用 (change) 并访问 event.target.options.selectedIndex 属性,但当 ngModel 从外部设置或其初始值是这样的,使其对应于具有非活动属性的选项时,这两种方法都不起作用。

编辑:

我尝试了使用整个 option 对象作为 ngValue 的建议方法。

class ComponentWithSelect {

  @Input()
  set ngModel(model: unknown) {
    this.selectedValue = this.options.find(option => option.value === model) || null;
  }
  @Input() options: { value: unknown, label: string, disabled: boolean }[] = [];
  @Output() ngModelChange = new EventEmitter<unknown>();

  selectedValue: { value: unknown, label: string, disabled: boolean } = null;

  onModelChange(option: { value: unknown, label: string, disabled: boolean }) {
    this.ngModel = option.value;
    this.ngModelChange.emit(this.ngModel);
  }

和模板:

<select
  [(ngModel)]="selectedValue"
  [class.inactive-select]="selectedValue.disabled">
  <option *ngFor="let option of options"
    [ngValue]="option">
    {{option.label}}
  </option>
</select>

当将相应的 ngModel 传递给我的组件时,现在会正确选择正确的选项,但当我尝试手动更改选择时,第一次什么都没有选中,所有随后的更改都正常工作。


<details>
<summary>英文:</summary>

I would like to to style a *select* element in an Angular component differently, when a specific option (with an inactive attribute) is selected.


My component look like this:
```javascript
class ComponentWithSelect {
  @Input() ngModel: unknown = null;
  @Input() options: { value: unknown, label: string, diasbled: boolean }[]

  inactiveSelected: boolean = false;
  ...

}

and the corresponding template look like this:

&lt;select
  [ngModel]=&quot;ngModel&quot;
  [class.inactive-select]=&quot;inactiveSelected&quot;&gt;
  &lt;option *ngFor=&quot;let option of options&quot;
    [ngValue]=&quot;option.value&quot;
    [disabled]=&quot;option.disabled&quot;&gt;
    {{option.label}}
  &lt;/option&gt;
&lt;/select&gt;

I would like to apply the inactive-select class when an option with the inactive attribute is selected OR when a ngModel is passed to the component which corresponds to an option with an inactive attribute.

I tried to use the (ngModelChange) to set the inactiveSelected property but $event parameter passed to a corresponding method (onModelChange) does contain the value of the selected option, not the inactive attribute.

I could go with (change) and access the event.target.options.selectedIndex property but neither of those two approaches works, when the ngModel is set from outside or its initial value is so, that it corresponds to a option with an inactive property

EDIT:

I tried the suggested approach with using the whole option object for ngValue

class ComponentWithSelect {

  @Input()
  set ngModel(model: unknown) {
    this.selectedValue = this.options.find(option =&gt; option.value === model) || null;
  }
  @Input() options: { value: unknown, label: string, disabled: boolean }[] = [];
  @Output() ngModelChange = new EventEmitter&lt;unknown&gt;();

  selectedValue: { value: unknown, label: string, disabled: boolean } = null;

  onModelChange(option: { value: unknown, label: string, disabled: boolean }) {
    this.ngModel = option.value;
    this.ngModelChange.emit(this.ngModel);
  }

and the template

&lt;select
  [(ngModel)]=&quot;selectedValue&quot;
  [class.inactive-select]=&quot;selectedValue.disabled&quot;&gt;
  &lt;option *ngFor=&quot;let option of options&quot;
    [ngValue]=&quot;option&quot;&gt;
    {{option.label}}
  &lt;/option&gt;
&lt;/select&gt;

The right option is now selected properly when a corresponding ngModel is passed to my component, but when I try to manually change the select, for the for the first time nothing is selected, all consequent changes are working fine.

答案1

得分: 1

以下是翻译的部分:

  • 如Maggini指出,您的ngValue绑定是错误的。
  • 使用[(ngModel)]而不是[ngModel]。

此外,您不需要一个用于跟踪的额外布尔属性。
最后注意,初始绑定的对象必须来自选项数组。

*** .html 文件 ***

<select
  [(ngModel)]="selectedValue"
  [ngClass]="{'inactive-select': selectedValue.inactive}"
>
  <option *ngFor="let option of options"
    [ngValue]="option"
  >
    {{option.label}}
  </option>
</select>

*** .ts 文件 ***

import { Component, Input, OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit  {

  selectedValue: any;

  options: { value: unknown, label: string, inactive: boolean } [] = [
    {
      value: 1,
      label: "1",
      inactive: false,
    },
    {
      value: 2,
      label: "2",
      inactive: true,
    },    
  ]

  ngOnInit(): void {
    this.selectedValue = this.options[0];
  }

}
英文:

There are 2 things you should notice:

  • as Maggini pointed out your ngValue binding is wrong
  • use [(ngModel)] instead of [ngModel]

Besides you do not need a secondary boolean property for tracking.<br/>
Last note, inital bound object must be one from the options array.

*** .html file ***

&lt;select
  [(ngModel)]=&quot;selectedValue&quot;
  [ngClass]=&quot;{&#39;inactive-select&#39;: selectedValue.inactive}&quot;
  &gt;
  &lt;option *ngFor=&quot;let option of options&quot;
    [ngValue]=&quot;option&quot;&gt;
    {{option.label}}
  &lt;/option&gt;
&lt;/select&gt;

*** .ts file ***

import { Component, Input, OnInit } from &#39;@angular/core&#39;;

@Component({
  selector: &#39;app-root&#39;,
  templateUrl: &#39;./app.component.html&#39;,
  styleUrls: [&#39;./app.component.css&#39;]
})
export class AppComponent implements OnInit  {

  selectedValue: any;

  options: { value: unknown, label: string, inactive: boolean } [] = [
    {
      value: 1,
      label: &quot;1&quot;,
      inactive: false,
    },
    {
      value: 2,
      label: &quot;2&quot;,
      inactive: true,
    },    
  ]

  ngOnInit(): void {
    this.selectedValue = this.options[0];
  }

}

答案2

得分: 0

I got it working, I had to add getter as well

class ComponentWithSelect {

  @Input()
  set ngModel(model: unknown) {
    this._ngModel = model;
    this.selectedValue = this.options.find(option => option.value === model) || null;
  }
  get (): unknown {
    return this._ngModel;
  }
  @Input() options: { value: unknown, label: string, disabled: boolean }[] = [];
  @Output() ngModelChange = new EventEmitter<unknown>();

  private _ngModel: unknown;
  selectedValue: { value: unknown, label: string, disabled: boolean } = null;

  onModelChange(option: { value: unknown, label: string, disabled: boolean }) {
    this._ngModel = option.value;
    this.ngModelChange.emit(this._ngModel);
  }

and the template:

<select
  [(ngModel)]="selectedValue"
  [class.inactive-select]="selectedValue.disabled">
  <option *ngFor="let option of options"
    [ngValue]="option">
    {{option.label}}
  </option>
</select>
英文:

I got it working, I had to add getter as well

class ComponentWithSelect {

  @Input()
  set ngModel(model: unknown) {
    this._ngModel = model;
    this.selectedValue = this.options.find(option =&gt; option.value === model) || null;
  }
  get (): unknown {
    return this._ngModel;
  }
  @Input() options: { value: unknown, label: string, disabled: boolean }[] = [];
  @Output() ngModelChange = new EventEmitter&lt;unknown&gt;();

  private _ngModel: unknown;
  selectedValue: { value: unknown, label: string, disabled: boolean } = null;

  onModelChange(option: { value: unknown, label: string, disabled: boolean }) {
    this._ngModel = option.value;
    this.ngModelChange.emit(this._ngModel);
  }

and the template:

&lt;select
  [(ngModel)]=&quot;selectedValue&quot;
  [class.inactive-select]=&quot;selectedValue.disabled&quot;&gt;
  &lt;option *ngFor=&quot;let option of options&quot;
    [ngValue]=&quot;option&quot;&gt;
    {{option.label}}
  &lt;/option&gt;
&lt;/select&gt;

huangapple
  • 本文由 发表于 2023年4月11日 06:35:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75981229.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定