【问题标题】:How to add select all option to ion-select in ionic 5如何在离子 5 中添加选择所有选项到离子选择
【发布时间】:2020-09-23 14:13:04
【问题描述】:

我尝试添加 ion-select-option,然后尝试在更改事件中处理选择所有逻辑,但更改事件根本不会触发。好像不支持事件

    <ion-item>
        <ion-label>Test</ion-label>
        <ion-select [(ngModel)]="selectedValues" multiple="true">
            <ion-select-option (ionChange)="selectAll()">Select All</ion-select-option>
            <ion-select-option [value]="option" *ngFor="let option of  items">{{option}}
            </ion-select-option>
        </ion-select>
    </ion-item>

样本https://stackblitz.com/edit/ionic-5-angular-10-start-template-hure6j?file=src/app/tabs/tabs.page.html

【问题讨论】:

    标签: angular ionic-framework ionic5


    【解决方案1】:

    使用 Ionic 多项选择,没有内置的“全选”或“全选”的方法,但我想出了一个自定义解决方案来做到这一点。您将需要使用自定义 alert component 而不是 &lt;ion-select&gt;,并且需要以编程方式触发警报。

    constructor(
        private alertController: AlertController,
        public platform: Platform
      ) {}
    
      async showAlert() {
    
        let buttons = [
          {
            text: 'All',
            cssClass: 'all-none-button',
            handler: () => {
    
              // check all checkboxes
              alert.inputs = alert.inputs.map((checkbox) => {
                checkbox.checked = true;
                return checkbox;
              });
    
              return false;
            }
          }, {
            text: 'None',
            cssClass: 'all-none-button',
            handler: () => {
    
              // uncheck all checkboxes
              alert.inputs = alert.inputs.map((checkbox) => {
                checkbox.checked = false;
                return checkbox;
              });
    
              return false;
            }
          }, {
            text: 'OK',
            handler: (data) => {
              // handle the data returned from the alert here
              console.log(data);
            }
          }, {
            text: 'Cancel',
            role: 'cancel',
          }
        ];
    
        // adjust button order in four button layout for ios
        if (this.platform.is('ios')) {
          const okButton = { ...buttons[2] };
          const cancelButton = { ...buttons[3] };
          buttons = [buttons[0], buttons[1], cancelButton, okButton];
        }
    
        const alert = await this.alertController.create({
          header: 'Select Option',
          inputs: [
            {
              label: 'Option 1',
              type: 'checkbox',
              value: 'one',
              checked: false
            },
            {
              label: 'Option 2',
              type: 'checkbox',
              value: 'two',
              checked: false
            },
            {
              label: 'Option 3',
              type: 'checkbox',
              value: 'three',
              checked: false
            },
          ],
          cssClass: 'four-button-alert',
          buttons: [...buttons]
        });
    
        await alert.present();
      }
    

    您还需要一些自定义 CSS 来获取此自定义警报的四个按钮布局。

    .four-button-alert.md {
        .alert-button-group-vertical {
            display: block;
    
            button:nth-of-type(1),
            button:nth-of-type(2) {
                float: left;
                color: var(--ion-color-medium);
            }
    
            button:nth-of-type(3),
            button:nth-of-type(4) {
                float: right;
            }
        }
    }
    
    .four-button-alert.ios {
        .alert-button-group-vertical {
            flex-direction: row !important;
    
            button:nth-of-type(1) {
                color: var(--ion-color-medium);
            }
    
            button:nth-of-type(2) {
                color: var(--ion-color-medium);
                border-right: none;
            }
        }
    }
    

    成品看起来像这样(iOS & Android)。

    【讨论】:

      【解决方案2】:

      我同意 Wesley 的观点,因为 ion-select 在后台利用警报控制器或弹出框,所以最好的方法是使用自定义警报。 但是,如果您必须保持 ion-select 的“外观和感觉”,您可以执行以下操作:

      HTML:

      <ion-item (click)="openSelector(selector)">
            <ion-label>Pizza Toppings</ion-label>
            <ion-select #selector style="pointer-events: none" [interfaceOptions]="customAlertOptions" multiple="true" [value]="basket">
            <ion-select-option *ngFor="let option of options" [value]="option">{{option}}</ion-select-option>
          </ion-select>
      </ion-item>
      

      TS:

      import { Inject, Component, Renderer2 } from '@angular/core';
      import { DOCUMENT } from '@angular/common';
      
      @Component({
        selector: 'my-app',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
      })
      export class AppComponent {
      
        options = ["cheese", "pepperoni", "basil"];
        basket = [];
      
        listener;
        selectAllCheckBox: any;
        checkBoxes: HTMLCollection;
      
        customAlertOptions: any = {
          header: 'Pizza Toppings',
          subHeader: 'Select All:',
          message: '<ion-checkbox id="selectAllCheckBox"></ion-checkbox>'
        };
      
        constructor(@Inject(DOCUMENT) private document: Document, private renderer: Renderer2) {}
      
        openSelector(selector) {
          selector.open().then((alert)=>{
            this.selectAllCheckBox = this.document.getElementById("selectAllCheckBox");
            this.checkBoxes = this.document.getElementsByClassName("alert-checkbox");
            this.listener = this.renderer.listen(this.selectAllCheckBox, 'click', () => {
                if (this.selectAllCheckBox.checked) {
                  for (let checkbox of this.checkBoxes) {
                    if (checkbox.getAttribute("aria-checked")==="false") {
                      (checkbox as HTMLButtonElement).click();
                    };
                  };
                } else {
                  for (let checkbox of this.checkBoxes) {
                    if (checkbox.getAttribute("aria-checked")==="true") {
                      (checkbox as HTMLButtonElement).click();
                    };
                  };
                }
            });
            alert.onWillDismiss().then(()=>{
              this.listener();
            });
          })
        }
        
      }
      

      基本上,您禁用 ion-select 上的默认单击处理程序并通过 ion-item 绑定单击事件传递“选择器”引用。然后,您使用离子选择的“打开”方法来访问“警报”实例。 由于警报选项的 'message' 属性支持“净化” HTML,您仍然可以将 HTML 元素及其 ID 传递给它(复选框)。然后使用文档参考你得到复选框并添加监听器(稍后将在 willDismiss 钩子上删除)。 在 click 方法中可以实现全选/全选的功能。

      演示:https://stackblitz.com/edit/ionic-angular-v5-2jqnsv?file=src/app/app.component.ts

      【讨论】:

      • 谢谢,它解决了我的问题,但是当任何项目未选中时,我想取消选中 selectALL。任何提示
      【解决方案3】:

      2021 年 7 月更新:添加了搜索并将全选和搜索移至自定义元素以便于管理

      代码示例: https://stackblitz.com/edit/ionic-5-angular-10-start-template-6m73vb

      以前的方法:

      我最终使用了@Sergey Rudenko 解决方案,并创建了一些改进指令并在更多场景中处理全选。有兴趣的朋友请看下面的相关代码

      解决方案 1:全选复选框指令。基于@Sergey Rudenko 的回答

      import { ContentChild, Directive, HostListener, Renderer2 } from '@angular/core';
      import { IonSelect } from '@ionic/angular';
      @Directive({
          selector: '[selectAllDirective]'
      })
      export class SelectAllDirective {
          @ContentChild(IonSelect) ionSelect;
          constructor(private renderer: Renderer2) { }
      
          ngAfterViewInit() {
              this.ionSelect.el.style.pointerEvents = "none";
          }
          @HostListener('click', ['$event'])
          onClick() {
              this.ionSelect.open().then(alert => {
                  let id = "selectAllCheckBox";
                  alert.message = `<ion-checkbox id="${id}"></ion-checkbox><ion-label class="m-l-15">Select All</ion-label>`;
      
                  setTimeout(() => {
                      let selectAll: any = alert.querySelector("#" + id);
                      let checkboxes = Array.from(alert.querySelectorAll(".alert-checkbox"));
                      let setState = () => {
                          let isAllChecked = checkboxes.every((c: any) => c.ariaChecked === "true");
                          let isAllUnChecked = checkboxes.every((c: any) => c.ariaChecked === "false");
                          if (isAllChecked || isAllUnChecked) {
                              selectAll.indeterminate = false;
                              selectAll.checked = isAllChecked;
                          } else {
                              selectAll.indeterminate = true;
                          }
                      }
                      setState();
      
                      let checkboxListeners = checkboxes.map(ci => this.renderer.listen(ci, 'click', () => {
                          setTimeout(setState);
                      }));
      
                      let selectAllListener = this.renderer.listen(selectAll, 'click', (event) => {
                          setTimeout(() => alert.inputs = alert.inputs.map(i => { i.checked = event.target.checked; return i; }));
                      });
                      alert.onWillDismiss().then(() => {
                          selectAllListener();
                          checkboxListeners.forEach(i => i());
                      });
                  });
              });
          }
      }
      

      解决方案 2:使用指令全选按钮。基于@Wesley 的回答

      import { ContentChild, Directive, HostListener, Renderer2 } from '@angular/core';
      import { IonSelect } from '@ionic/angular';
      @Directive({
          selector: '[selectAllWithButtonDirective]'
      })
      export class SelectAllWithButtonDirective {
          @ContentChild(IonSelect) ionSelect;
          constructor(private renderer: Renderer2) { }
      
          ngAfterViewInit() {
              this.ionSelect.el.style.pointerEvents = "none";
          }
          @HostListener('click', ['$event'])
          onClick() {
              this.ionSelect.open().then(alert => {
                  alert.cssClass = 'unset-vertical-buttons';
                  alert.buttons = [{
                      text: 'All',
                      handler: () => {
                          alert.inputs = alert.inputs.map((checkbox) => {
                              checkbox.checked = true;
                              return checkbox;
                          });
                          return false;
                      }
                  }, {
                      text: 'None',
                      handler: () => {
                          alert.inputs = alert.inputs.map((checkbox) => {
                              checkbox.checked = false;
                              return checkbox;
                          });
                          return false;
                      }
                  }, ...alert.buttons,];
              });
          }
      }
      

      styles.css

      .unset-vertical-buttons .alert-button-group-vertical {
          flex-direction: row !important;
      }
      .m-l-15 {
        margin-left: 15px;
      }
      

      两个指令代码示例:https://stackblitz.com/edit/ionic-5-angular-10-start-template-hu3y3u?file=src/app/tabs/select-all-with-button-directive.ts

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-15
        • 2017-10-22
        • 2020-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-26
        相关资源
        最近更新 更多