Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular material switch between mat-icon-button and mat-button

Is there any prettier way to switch between mat-icon-button and mat-button, depending on media queries? I've made a demo of my current solution, but it needs two independent button.

<button type=button mat-icon-button fxHide fxShow.lt-sm (click)="onEdit($event)">
  <mat-icon>edit</mat-icon>
</button>
<button type="button" mat-button fxHide.lt-sm (click)="onEdit($event)">
  <mat-icon>edit</mat-icon> Edit
</button>

DEMO

like image 703
Totati Avatar asked Feb 21 '18 06:02

Totati


People also ask

How do you use a toggle mat button?

By default, mat-button-toggle-group acts like a radio-button group- only one item can be selected. In this mode, the value of the mat-button-toggle-group will reflect the value of the selected button and ngModel is supported. Adding the multiple attribute allows multiple items to be selected (checkbox behavior).

What is the use of toggle in angular?

The <mat-button-toggle>, an Angular Directive, is used to create a toggle or on/off button with material styling and animations. mat-button-toggle buttons can be configured to behave as radio buttons or checkboxes.


1 Answers

Got the same problem, currently using this solution.

Component.html:

<button
        mat-button
        [ngClass]="isBigDevice() ? 'mat-stroked-button' : 'mat-icon-button'"
        color="accent"
        type="button"
        (click)="coolMethodToDoStuff()"
        [disabled]="isSelected() && contextTypeIsSomething()">
    <span *ngIf="isBigDevice()">Edit</span>
    <mat-icon *ngIf="!isBigDevice()">edit</mat-icon>
</button>

There is a problem/annotation: You need to add the base button style/property mat-button. If you dont, you will get an error that color is no property for this kind of html-element. The advantages are, if you have multiple properties on one button or conditions for disabled, hidden or *ngIf you dont need them twice. I know with *ngIfthe readability is lacking, but currently its the best way to avoid a huge junk of duplicate code.

Next step for me: I will build an directive for things like this.

Edit:

More over this is my MediaQueryService:

import {Injectable, OnDestroy} from '@angular/core';
import {BreakpointObserver, Breakpoints, BreakpointState} from '@angular/cdk/layout';
import {Subject} from 'rxjs';
import {takeUntil} from 'rxjs/operators';

@Injectable({
    providedIn: 'root'
})

export class MediaQueryService implements OnDestroy {

private _breakpointArray = {
    isXSmall: false,
    isSmall: false,
    isMedium: false,
    isLarge: false,
    isXLarge: false,
};
private _destroy$ = new Subject();

constructor(
    private _breakpointObserver: BreakpointObserver,
) {
    this._breakpointObserver
        .observe([
            Breakpoints.WebLandscape,
            Breakpoints.WebPortrait,
        ])
        .pipe(
            takeUntil(this._destroy$)
        )
        .subscribe((state: BreakpointState) => {
            _breakpointObserver.isMatched(Breakpoints.WebLandscape)
                ? this.webOrientationChangeLogger('landscape')
                : this.webOrientationChangeLogger('portrait');
        });

    this._breakpointObserver.observe([
            Breakpoints.XSmall,
            Breakpoints.Small,
            Breakpoints.Medium,
            Breakpoints.Large,
            Breakpoints.XLarge,
        ]
    )
        .pipe(
            takeUntil(this._destroy$)
        )
        .subscribe((state: BreakpointState) => {
            this._breakpointArray.isXSmall = _breakpointObserver.isMatched(Breakpoints.XSmall);
            this._breakpointArray.isSmall = _breakpointObserver.isMatched(Breakpoints.Small);
            this._breakpointArray.isMedium = _breakpointObserver.isMatched(Breakpoints.Medium);
            this._breakpointArray.isLarge = _breakpointObserver.isMatched(Breakpoints.Large);
            this._breakpointArray.isXLarge = _breakpointObserver.isMatched(Breakpoints.XLarge);
        });
}

public ngOnDestroy(): void {
    this._destroy$.next();
    this._destroy$.complete();
}

public get isSmallDevice(): boolean {
    return this.getBreakpointBoolean('isXSmall') || this.getBreakpointBoolean('isSmall');
}

public get isBigDevice(): boolean {
    return this.getBreakpointBoolean('isXLarge') || this.getBreakpointBoolean('isLarge');
}

public getBreakpointBoolean(breakpointName: string): boolean {
    return this._breakpointArray[breakpointName];
}

private webOrientationChangeLogger(orientation: string) {
    console.log(orientation);
}

}

And inside the component where I am using the button I just call the isBigDevice() method and return the boolean.

Component.ts:

public isBigDevice(): boolean {
    return this._mediaQueryService.isBigDevice();
}

You could also try use this the fxShow, fxHide properties of angular material.

like image 128
liqSTAR Avatar answered Oct 25 '22 01:10

liqSTAR