【问题标题】:How to bind to model with Angular Material <mat-button-toggle>?如何使用 Angular Material <mat-button-toggle> 绑定到模型?
【发布时间】:2018-04-15 10:35:44
【问题描述】:

看看这个 Plunker: https://plnkr.co/edit/yu95hUrKlUh4Ttc5SwYD?p=preview

当我使用&lt;mat-slide-toggle&gt; 时,我可以修改组件中的值:

<mat-slide-toggle [(ngModel)]="myFlagForSlideToggle">Toggle me!</mat-slide-toggle>

myFlagForSlideToggle 已按预期更新。

但是当我使用&lt;mat-button-toggle&gt; 时,值不会更新。我必须添加ngDefaultControl 才能使这个示例正常运行,但我不确定它的重要性。

<mat-button-toggle [(ngModel)]="myFlagForButtonToggle" ngDefaultControl>Toggle me!</mat-button-toggle>

将按钮状态绑定到组件的正确方法是什么?

【问题讨论】:

    标签: angular angular-material


    【解决方案1】:

    我在使用 Angular Material 时遇到了同样的问题。我提供了 name 和 id 属性以及 ngModel 属性(用于模板驱动的表单)以绑定到模型值。它对我有用。

    请看下面的代码:

    <mat-button-toggle-group name="fontStyle" name="fontStyle" id="fontStyle">
        <mat-button-toggle value="bold">Bold</mat-button-toggle>
        <mat-button-toggle value="italic">Italic</mat-button-toggle>
        <mat-button-toggle value="underline">Underline</mat-button-toggle>
    

    【讨论】:

      【解决方案2】:
      <mat-button-toggle-group formControlName="flags" style="width: 100%" (change)="onChangeFlag($event)">
          <mat-button-toggle *ngFor="let flag of allFlags" value="{{flag.flag}}" style="width: 100%;" 
          matTooltip="{{flag.name}}" [checked]="flagSelected == flag.flag"
          > <img [alt]="flag" src="assets/images/flags/{{flag.flag}}.png" width="20px"/> 
          </mat-button-toggle>
      
        </mat-button-toggle-group>
      

      【讨论】:

        【解决方案3】:

        我为 Angular Material Button Toggle Group 创建了一个自定义表单控件。以下是我的实现方式:

        custom-button-toggle-group.component.html

        <mat-button-toggle-group
          (change)="onToggleGroupChange($event)"
          [disabled]=disabled
          [value]=value
        >
          <mat-button-toggle
            *ngFor="let toggle of toggles"
            [value]="toggle.value"
          >{{ toggle.label }}</mat-button-toggle>
        </mat-button-toggle-group>
        

        custom-button-toggle-group.component.ts

        import { Component, forwardRef, HostListener, Input } from '@angular/core';
        import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
        import { MatButtonToggleChange } from '@angular/material/button-toggle';
        
        export interface ButtonToggle {
          value: string;
          label: string;
        }
        
        @Component({
          selector: 'custom-button-toggle-group',
          templateUrl: './button-toggle-group.component.html',
          styleUrls: ['./button-toggle-group.component.scss'],
          providers: [
            {
              provide: NG_VALUE_ACCESSOR, multi: true,
              useExisting: forwardRef(() => CustomButtonToggleGroupComponent),
            }
          ]
        })
        export class CustomButtonToggleGroupComponent implements ControlValueAccessor {
        
          @Input() public toggles: ButtonToggle[];
        
          public value: string;
          public disabled: boolean;
        
          private onChange: (value: string) => void;
          private onTouched: () => void;
        
        
          public onToggleGroupChange({ value }: MatButtonToggleChange): void {
            this.doChange(value);
          }
        
          writeValue(obj: any): void {
            this.value = obj;
          }
        
          registerOnChange(fn: any): void {
            this.onChange = fn;
          }
        
          registerOnTouched(fn: any): void {
            this.onTouched = fn;
          }
        
          setDisabledState?(isDisabled: boolean): void {
            this.disabled = isDisabled;
          }
        
          private doChange(selectedValue: string): void {
            this.onChange(selectedValue);
          }
        
          @HostListener('blur')
          private doBlur(): void {
            this.onTouched();
          }
        
        }
        

        这样您就可以在custom-button-toggle-group 上使用FormControlFormControlName 等。

        【讨论】:

        • 正确的解决方案,我想实施,清晰,简单和可重用。已经用过了,谢谢
        • @JosilloDebian 同样的想法
        【解决方案4】:

        使用 Angular 6.1.3Angular Material 6.4.6 使用 Slide Toggle(即 &lt;mat-slide-toggle&gt;

        模板

        <mat-slide-toggle [checked]="isAwesome"
           (change)="toggleIsAwesome()">
           Is TypeScript Awesome?
        </mat-slide-toggle>
        

        组件

        export class AwesomeExampleComponent {
           // props
           isAwesome = false;
        
           // methods
           toggleIsAwesome() {
              this.isAwesome = !this.isAwesome;
              // could put additional logic here
           }
        }
        

        我正在使用这个解决方案,它很方便地符合Style Guide 规则:

        不要将表示逻辑放在组件类中,而不是在模板中。

        【讨论】:

          【解决方案5】:

          如果您尝试使用mat-button-toggle 在启用/禁用某些功能之间进行切换,则必须对mat-button-toggle-group 使用绑定,并确保mat-button-toggle 本身具有@987654324 的布尔值@ 和 false,而不是字符串值。也就是说:

          <mat-button-toggle-group [(ngModel)]="isEnabled">
              <mat-button-toggle [value]="true"> Enable </mat-button-toggle>
              <mat-button-toggle [value]="false"> Disable </mat-button-toggle>
          </mat-button-toggle-group>
          

          【讨论】:

          • 这应该被标记为正确答案,因为这是有效的,并且是最干净的方式,无需单击或更改处理程序。
          【解决方案6】:

          mat-button-toggle 没有布尔值,[(ngModel)] 不起作用。见doc

          这些开关可以配置为单选按钮或复选框。

          一个用例可能是这样的

          <mat-button-toggle-group  [(ngModel)]="myFlagForButtonToggle">
            <mat-button-toggle value="button1"  ngDefaultControl>Toggle me!</mat-button-toggle>
            <mat-button-toggle value="button2"  ngDefaultControl>Toggle me!</mat-button-toggle>
            <mat-button-toggle value="button3"  ngDefaultControl>Toggle me!</mat-button-toggle>
          </mat-button-toggle-group>
          

          并将您的布尔值更改为myFlagForButtonToggle :string;

          【讨论】:

          • 无法绑定到“ngModel”,因为它不是“mat-button-toggle-group”的已知属性
          • 一切正常...只需导入 CommonModule 让 NgModel 工作...
          • 太棒了。其他解决方案也可以,但这是迄今为止最简单和最“正常”的数据绑定。
          • 这应该是最好的答案了,这正是官方文档中提到的设计和特性。但是ngModel生活在FormModule中,也就是说需要将import { FormsModule } from '@angular/forms';导入到AppModule中
          • 这包含好的和坏的。代码本身有效。这是很好的部分。但是你说“切换按钮不适用于布尔值”的那部分是错误的。检查上面的 Andrew Favaloro 答案。用 [] 环绕值可以设置布尔值。否则它是字符串。也许 2017 年的情况有所不同。
          【解决方案7】:
          public selectedVal: string;
          constructor() { }
          
          ngOnInit(){
            this.selectedVal ='option1';
          } 
          
          public onValChange(val: string) {
            this.selectedVal = val;
          }
          
           <mat-button-toggle-group #group="matButtonToggleGroup" [value]="selectedVal" (change)="onValChange(group.value)" >
            <mat-button-toggle value="option1">
              Option 1
            </mat-button-toggle>
            <mat-button-toggle value="option2">
              Option 2
            </mat-button-toggle>
          </mat-button-toggle-group>
          

          【讨论】:

            【解决方案8】:

            MatButtonToggle 组件没有实现ControlValueAccessor,因此你不能在它上面使用ngModelngDefaultControl 是为 other purposes 引入的。

            MatButtonToggle 应该是mat-button-toggle-group 的一部分。但是,如果您想将它用作独立组件并将模型绑定到它,这里有一些示例说明如何做到这一点:

            <mat-button-toggle 
              [checked]="myFlagForButtonToggle" 
              (change)="myFlagForButtonToggle = $event.source.checked">
                Toggle me!
            </mat-button-toggle>
            

            Plunker Example

            【讨论】:

            • 谢谢!试图对来自父组件的对象进行可观察的操作,但没有得到它的工作。这就是诀窍(但是,不适用于可观察数组,只能用于常规数组..
            猜你喜欢
            • 2019-09-16
            • 2018-10-01
            • 2019-07-24
            • 2018-10-10
            • 2020-01-25
            • 2020-03-25
            • 1970-01-01
            • 1970-01-01
            • 2018-12-05
            相关资源
            最近更新 更多