Kurt Schwanda
Kurt Schwanda

Reputation: 219

How can Ionic 3 buttons be set to clear or outline dynamically?

I have some buttons in an Ionic 3 app that I would like to be able to dynamically set as outline or clear. I can bind clear by itself and that works (case 1 below). And I can bind outline by itself (case 2 below). But when I try to bind both clear and outline it seems like the value of outline gets ignored. I've shown my desired output in the very last row.

I have this as part of the class for my page:

  buttons = [
          {clear: true, outline: false, name: 'Clear'},
          {clear: false, outline: true, name: 'Outline'},
          {clear: false, outline: false, name: 'Default'},
        ];

And my HTML is:

<ion-content padding>
  <ion-row>
    <ion-col col-6>
      <ion-label>
        1. Binding clear attribute:
      </ion-label>
    </ion-col>
    <ion-col col-2 *ngFor="let button of buttons">
      <button ion-button
        [clear]="button.clear">
        {{button.name}}
      </button>
    </ion-col>
  </ion-row>
  <ion-row>
    <ion-col col-6>
      <ion-label>
        2. Binding outline attribute:
      </ion-label>
    </ion-col>
    <ion-col col-2 *ngFor="let button of buttons">
      <button ion-button
        [outline]="button.outline">
        {{button.name}}
      </button>
    </ion-col>
  </ion-row>
  <ion-row>
    <ion-col col-6>
      <ion-label>
        3. Binding clear and outline attributes:
      </ion-label>
    </ion-col>
    <ion-col col-2 *ngFor="let button of buttons">
      <button ion-button
        [outline]="button.outline"
        [clear]="button.clear">
        {{button.name}}
      </button>
    </ion-col>
  </ion-row>
  <ion-row>
    <ion-col col-6>
      <ion-label>
        4. Desired output:
      </ion-label>
    </ion-col>
    <ion-col col-2>
      <button ion-button clear>Clear</button>
    </ion-col>
    <ion-col col-2>
      <button ion-button outline>Outline</button>
    </ion-col>
    <ion-col col-2>
      <button ion-button>Default</button>
    </ion-col>
  </ion-row>
</ion-content>

Here is a rendering of the page: enter image description here

And a Plunker with the full code: https://embed.plnkr.co/eFBFc9/

Is there a reason I shouldn't be able to bind to both clear and outline?

I realize I could use an ngIf to ultimately achieve the same result:

<button ion-button *ngIf="button.clear" clear>{{button.name}}</button>
<button ion-button *ngIf="button.outline" outline>{{button.name}}</button>
<button ion-button *ngIf="!button.clear && !button.outline">{{button.name}}</button>

But it seems like it would be more concise to have one button with multiple bound attributes. How can I achieve this?

I also tried attr.clear and attr.outline in place of clear and outline but had no luck with that either.

Upvotes: 1

Views: 2341

Answers (1)

sebaferreras
sebaferreras

Reputation: 44659

This looks like a bug in Ionic, but still you can create your own custom component to "hide" the fix that involves using three buttons with the *ngIf and use that custom component in your pages.


StackBlitz demo


Your custom component could look like this for example:

import { Component, ChangeDetectionStrategy, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'custom-button',
    template: `
    <button (click)="onClick()" ion-button *ngIf="clear" clear>{{name}}</button>
    <button (click)="onClick()" ion-button *ngIf="outline" outline>{{name}}</button>
    <button (click)="onClick()" ion-button *ngIf="!clear && !outline">{{name}}</button>
  `,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class CustomButtonComponent {

  @Input() 
  public clear: boolean = false;

  @Input() 
  public outline: boolean = false;

  @Input() 
  public name: string;

  @Output() 
  customClick: EventEmitter<void> = new EventEmitter<void>();

  public onClick(): void {
    this.customClick.next();
  }

}

And then you'd use it like this in your pages:

import { Component } from '@angular/core';

@Component({
  selector: 'page-home',
  template: `
    <ion-header>
      <ion-navbar>
        <ion-title>Home</ion-title>
      </ion-navbar>
    </ion-header>

    <ion-content padding>
      <h2>Welcome to Ionic!</h2>

      <ion-row>
        <ion-col col-6>
          <ion-label>
            Using the custom component:
          </ion-label>
        </ion-col>
        <ion-col col-2 *ngFor="let button of buttons">

          <custom-button
            [clear]="button.clear ? true : null"       
            [outline]="button.outline ? true : null"
            [name]="button.name"
            (customClick)="onClicked()">
          </custom-button>

        </ion-col>
      </ion-row>

    </ion-content>
  `
})
export class HomePage {

  public buttons: Array<any> = [
    { clear: true, outline: false, name: 'Clear' },
    { clear: false, outline: true, name: 'Outline' },
    { clear: false, outline: false, name: 'Default' }
  ];

  public onClicked() {
    console.log('Clicked!');
  }

}

Upvotes: 1

Related Questions