Checkbox客製化與在Angular中實作全選

文章目錄

建立資料模型

  • 新增類別 Checkbox 擴展物件屬性,在物件中新增屬性 checked,來表示是否選擇。
export class CheckboxComponent implements OnInit {

  itemList: (Item & Checkbox)[] = [];

  constructor() { }

  ngOnInit(): void {
    const box: Checkbox = new Checkbox();
    const items = [ {name: "Item1", ...box}, {name: "Item2", ...box}, {name: "Item3", ...box} ];
    this.itemList = items;
  }
}

export interface Item {
  name: string
}
export class Checkbox {
  checked: boolean = false;
  indeterminate: boolean = false;
}

建立 HTML 語意結構

  • 建立一個 Checkbox 來全選所有項目。
    • 只有部分選項被選取時,設定 indeterminate 屬性為 true
    • 當所有選項被選取時,設定 checked 屬性為 true
    • 當不選取任何選項時,設定 checked 屬性為 falseindeterminate 屬性為 false
  • 以清單列出所有項目。
  • <input type="checkbox"> 包在 label 內,當 label 內的任何元素被點擊,input 的 checked 狀態即改變。
<div>
    <label class="field-checkbox">
        <input type="checkbox" [checked]="AllChecked" [indeterminate]="AllIndeterminate" (change)="allSelect()">
        <span class="checkmark"></span>All
    </label>
    
    <ul>
        <ng-container *ngFor="let item of itemList">
            <li>
                <label class="field-checkbox">
                    <input type="checkbox" [(ngModel)]="item.checked">
                    <span class="checkmark"></span>
                    {{ item.name}}
                </label>
            </li>
        </ng-container>
    </ul>
</div>

控制 Checkbox 狀態

  • get AllChecked() 偵測是否所有項目皆已選擇。
  • get AllIndeterminate() 偵測是否只有部分項目已選擇。
  • allSelect() 全選(或取消全選)所有項目。
export class CheckboxComponent implements OnInit {
  get AllChecked() {
    return this.itemList.every(_ => _.checked);
  }
  get AllIndeterminate() {
    return !this.AllChecked && this.itemList.some(_ => _.checked);
  }
  allSelect() {
    const isAllChecked = this.AllChecked;
    this.itemList.forEach(_ => _.checked = !isAllChecked);
  }
}

自訂 Checkbox 樣式

  • 隱藏 input。
  • .checkmark 客製化 Checkbox。
  • .checkmark:after 客製化選擇圖示。
.field-checkbox {
    display: inline-block;
    position: relative;
    padding-left: 35px;
    margin-bottom: 12px;
    cursor: pointer;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    cursor: pointer;
}

.field-checkbox input[type="checkbox"] {
    appearance: none;
}

.field-checkbox .checkmark {
    position: absolute;
    top: -3px;
    left: 0;
    height: 25px;
    width: 25px;
    font-size: 22px;
    margin-right: 5px;
    background-color: aliceblue;
    transition: all .5s;
}
.field-checkbox:hover input:not(:disabled)~.checkmark {
    background-color: rgb(202, 230, 255);
}

.field-checkbox .checkmark::after {
    position: absolute;
    content: '';
    display: block;
}

.field-checkbox input:not(:disabled):checked~.checkmark::after {
    left: 9px;
    top: 5px;
    width: 5px;
    height: 10px;
    border: solid rgb(125, 125, 249);
    border-width: 0 3px 3px 0;
    -webkit-transform: rotate(45deg);
    -ms-transform: rotate(45deg);
    transform: rotate(45deg);
}

.field-checkbox input:not(:disabled):indeterminate~.checkmark::after {
    left: 5px;
    top: 11px;
    width: 15px;
    height: 3px;
    background-color: rgb(125, 125, 249);
}