LoginSignup
5
4

More than 5 years have passed since last update.

[Angular] ラジオボタン(radio)のカスタムコンポーネント[サンプルコード]

Last updated at Posted at 2018-06-05

ラジオボタン(radios)の CSSをカスタムして、それをカスタムコンポーネントにしました。
意外と ([ngModel]) をカスタムコンポーネントでやっているリファレンスって少ないので、 ngModel の例としても役に立つかもしれない。

利用する側のコンポーネントのコード

parent.ts
@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html'
})
export class ParentComponent {
  @Input() gender: string;
}
parent.component.html
<app-radio selectValue="male" label="男" name="gender" [(ngModel)]="gender">
<app-radio selectValue="female" label="女" name="gender" [(ngModel)]="gender">
<app-radio selectValue="unknown" label="どちらでもない" name="gender" [(ngModel)]="gender">

コンポーネントのコード

radio.component.ts
import { Component, forwardRef, Input } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'app-radio',
  templateUrl: './radio.component.html',
  styleUrls: ['./radio.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      multi: true,
      useExisting: forwardRef(() => RadioComponent),
    },
  ],
})
export class RadioComponent {
  _value: string;
  @Input() selectValue: any;
  @Input() label: string;

  private onTouchedCallback: () => void = () => {};
  private onChangeCallback: (_: any) => void = () => {};

  get value(): string {
    return this._value;
  }
  @Input('value')
  set value(text: string) {
    if (this._value !== text) {
      this._value = text;
      this.onChangeCallback(text);
    }
  }

  writeValue(text: string): void {
    if (text !== this.value) {
      this.value = text;
    }
  }

  registerOnChange(fn: any): void {
    this.onChangeCallback = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouchedCallback = fn;
  }

  setDisabledState(isDisabled: boolean): void {
  }

}
radio.component.html
<label class="radio-wrapper">
  <input type="radio" [value]="selectValue" [(ngModel)]="value" >
  <span class="checkmark"></span><span class="label">{{ label }}</span>
</label>
radio.component.scss
.radio-wrapper {
  display: inline-flex;
  align-items: center;
  position: relative;
  margin-top: 8px;
  cursor: pointer;
  font-size: 16px;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;

  &.margin-left {
    margin-left: 34px;
  }
  .label {
    margin-left: 4px;
  }
}

/* Hide the browser's default radio button */
.radio-wrapper input {
  position: absolute;
  opacity: 0;
}

/* Create a custom radio button */
.checkmark {
  display: inline-block;
  //position: absolute;
  //top: 0;
  //left: 0;
  height: 21px;
  width: 21px;
  background-color: #eee;
  border-radius: 50%;
}

/* On mouse-over, add a grey background color */
.radio-wrapper:hover input ~ .checkmark {
  background-color: #ccc;
}

/* When the radio button is checked, add a blue background */
.radio-wrapper input:checked ~ .checkmark {
  background-color: white;
  border: 1px solid #2196F3;
}

/* Create the indicator (the dot/circle - hidden when not checked) */
.checkmark:after {
  content: "";
  position: absolute;
  display: none;
}

/* Show the indicator (dot/circle) when checked */
.radio-wrapper input:checked ~ .checkmark:after {
  display: block;
}

/* Style the indicator (dot/circle) */
.radio-wrapper .checkmark:after {
  top: 7px;
  left: 7px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #2196F3;
}
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4