角形三态拨动开关

时间:2018-12-26 10:24:11

标签: javascript html css angular typescript

在我的angular 6应用程序中,我需要使用具有顺序的三态切换开关

---ON---NA---OFF---

我为此使用了以下 HTML

<div class="switch-toggle switch-3 switch-candy">
   <input id="on" name="state-d" type="radio" checked="">
   <label for="on" onclick="">ON</label>

   <input id="na" name="state-d" type="radio" checked="checked">
   <label for="na" onclick="">N/A</label>

   <input id="off" name="state-d" type="radio">
   <label for="off" onclick="">OFF</label>

   <a></a>
</div>

由于文件很多,因此无法共享 css 文件。

工作示例: https://stackblitz.com/edit/angular-6-template-driven-form-validation-z2rsig

在其中您可以看到两次制成的开关盒,其中第一个完全是硬编码的单选按钮。

但是我在一秒钟内试图使其动态化,但是我无法获得与所选开关相同的UI和值。

我需要的是,需要进行三个状态切换开关,其值将为On --- NA --- Off。如果用户切换到Off,则state-d的值需要为Off,如果用户的On,则state-d的值必须为{{1} },On也是如此。默认情况下,NA需要选中(选中)。

我需要像链接https://stackblitz.com/edit/angular-6-template-driven-form-validation-z2rsig中的第一个一样的结果

但是,单选按钮必须是动态的,就像我在同一链接的第二个按钮中尝试过的那样。(不起作用)。

HTML:

NA

Ts:

<div *ngFor="let option of options" class="switch-toggle switch-3 switch-candy">
        <div class="radio">
            <input type="radio"
               name="state-d"
               id="{{option.id}}"
               [(ngModel)]="value"
               [value]="option.value"
               />
        <label for="{{option.id}}">{{option.id}}
        </label>
    </div>
  </div>

我还需要获取当前开关的值。

请帮助我通过动态生成单选按钮来达到预期效果,并在切换按钮时将 public options = [ {value: "on", id:"On"}, {value: "na", id:"NA"}, {value: "off", id:"Off"}, ] 设置为默认值,从而相应地更改值。

使用任何第三方库(甚至不允许使用角形材料)或jquery ,都可以获得预期结果。如果UI有所更改但可以预期,则效果很好结果是纯角度的,基于typescript / javascript。

4 个答案:

答案 0 :(得分:2)

我真的很喜欢ng-bootstrap https://ng-bootstrap.github.io/#/components/buttons/examples#radio的单选按钮 (嗯,您可以添加为样式

.btn-primary.focus, .btn-primary:focus {  
   box-shadow: 0 0 0 0; 
}

为了避免焦点上的“丑陋”阴影

在不使用第三方库的情况下进行一些类似的设计可使用CSS。如果我们有类似的选项

<div *ngFor="let option of options" style="display:inline"  
    [className]="value==option.value?'active':'noactive'" >
    <input class="radio" type="radio" name="state-d" id="{{option.id}}"
            [(ngModel)]="value" [value]="option.value" />
        <label for="{{option.id}}">
           {{option.id}}
        </label>
</div>

只需添加

[type="radio"].radio {
  border: 0; 
  clip: rect(0 0 0 0); 
  height: 1px; margin: -1px; 
  overflow: hidden; 
  padding: 0; 
  position: absolute; 
  width: 1px;
}
.active{
   color:red;
}
.noactive{
   color:blue;
}

删除“插入符号”,并为单选按钮赋予一些样式。好吧,制作一个更加复杂的动画。我将尝试使用定义三个状态的Angular Animations,但我不确定如何制作

已更新(使用Angular动画) 在这种情况下,Angulars动画很容易。只需定义三个状态(我举一个非常简单的例子(我的选项将是一个简单的数组)

动画仅定义状态,以及如何将一种状态传递给另一种状态

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  animations: [
    trigger('posX',[
      state('uno',style({transform:'translateX(0)'})),
      state('dos',style({transform:'translateX(100px)'})),
      state('tres',style({transform:'translateX(200px)'})),
      transition('* => uno',animate(200)),
      transition('* => dos',animate(200)),
      transition('* => tres',animate(200)),
    ])
  ]
})
export class AppComponent {
  pos:string='uno';
  pos2:string='uno';
  options=['uno','dos','tres'];
}

动画只说,当[@posX]为'uno'时,不进行翻译;当[@posX]为'dos'时,向左翻译100px;当[@posX]为'tres'时,向200px

一个html将是两个位于相同位置的div(我使用margin-top:-2rem)

<div style="background-color:transparent;">
  <div *ngFor="let option of options" style="display:inline;" >
    <input class="radio" type="radio" name="state-d" id="{{'l'+option}}"
            [(ngModel)]="pos" [value]="option" />
        <label class="radio" for="{{'l'+option}}">
           {{option}}
        </label>
  </div>
</div>
<div style="overflow:hidden;margin-top:-2rem">
   <div  [@posX]="pos" (@posX.done)="pos2=pos" style="background:blue;width:100px" >
      {{pos2}}
  </div>
</div>

还有一个CSS来隐藏“插入符号”并为标签赋予宽度。

[type="radio"].radio {
  border: 0; 
  clip: rect(0 0 0 0); 
  height: 1px; margin: -1px; 
  overflow: hidden; 
  padding: 0; 
  position: absolute; 
  width: 1px;
}
label.radio
{
  width:100px;
}

您可以在stackblitz

中看到

注意:显然,这是一个丑陋的示例,其内嵌样式而不是.css

答案 1 :(得分:1)

此处更新了Stackbilz链接https://stackblitz.com/edit/angular-qkmkvu HTML代码`

<h3>Angular 6 Template-Driven Form Validation</h3>
<form name="form" (ngSubmit)="f.form.valid && onSubmit()" #f="ngForm" novalidate>
  <div class="switch-toggle switch-3 switch-candy">
    <div class="radio" *ngFor="let option of options">
      <input type="radio" name="state-d" id="{{option.id}}" [(ngModel)]="value" [value]="option.value" />
      <label for="{{option.id}}">{{option.id}}
      </label>
    </div>
  </div>
</form>

`

TS代码 `

export class AppComponent {
  model: any = {};
  value = "na";
  public options = [
    { value: "on", id: "On" },
    { value: "na", id: "NA" },
    { value: "off", id: "Off" }
  ];

  onSubmit() {
    alert("SUCCESS!! :-)\n\n" + JSON.stringify(this.model));
  }
}

`

我只是初始化第一个单选按钮值并更改某些样式

答案 2 :(得分:0)

您需要像这样将绑定的值绑定到所选标签。

只要更改输入值,就会检查[checked]="value === 'on'"输入,更改值后,您可以像这样value绑定回(change)="onSelectionChange('on')"模型。您的表单模型看起来不错,没有任何变化,但是可以像这样使单选按钮保持同步。

<form name="form" (ngSubmit)="f.form.valid && onSubmit()" #f="ngForm" novalidate>
                    <div class="form-group">
                        <div class="switch-toggle switch-3 switch-candy">
                            <input id="on" name="state-d" [value]="on"  [checked]="value === 'on'"  type="radio" (change)="onSelectionChange('on')" >
                            <label for="on">ON</label>

                            <input id="na" name="state-d"  [value]="na" [checked]="value === 'na'"  type="radio" checked="checked" (change)="onSelectionChange('na')">
                            <label for="na" >N/A</label>

                            <input id="off" name="state-d"  [value]="off"  [checked]="value === 'off'"  type="radio" (change)="onSelectionChange('off')">
                            <label for="off" >OFF</label>

                            <a></a>
                        </div>
                    </div>
                </form>

您的组件

export class AppComponent {
  model: any = {};

  public options = [
    { value: "on", id: "On" },
    { value: "na", id: "NA" },
    { value: "off", id: "Off" },
  ]

  onSubmit() {
    alert('SUCCESS!! :-)\n\n' + JSON.stringify(this.model))
  }

  onSelectionChange(entry) {
    this.value = entry;
  }
}

Demo

编辑:

添加了具有动态输入的演示,

您需要像这样使用ng-container

<form name="form" (ngSubmit)="f.form.valid && onSubmit()" #f="ngForm" novalidate>
                    <div class="form-group">

<div class="switch-toggle switch-3 switch-candy">
<ng-container *ngFor="let option of options" ><input type="radio"
               name="state-d"
               id="state-d"
               [checked]="value === option.value"
               [value]="option.value" 
               />
        <label (click)="onSelectionChange(option.value)"  for="{{option.id}}">{{option.id}}
        </label></ng-container> <a></a>
          </div> </div> </form>

Demo

答案 3 :(得分:0)

尝试一下

 <form name="form" (ngSubmit)="fM.form.valid && onSubmit()" #fM="ngForm" novalidate>
        <div class="switch-toggle switch-3 switch-candy">
      <ng-container *ngFor="let option of options">
              <input type="radio" name="state-d" id="{{option.id}}" [(ngModel)]="value" [value]="option.value"/>
        <label for="{{option.id}}"> {{option.id}}</label>
      </ng-container>
      <a></a>
    </div>
 </form>
<pre> {{ fM.form?.value | json }}</pre>

ng-container帮助您在不使用换行元素的情况下重复内容(aka * ngFor)

在TS中设置默认值,例如value = "na";