How to disable or overwrite cdk-focused in Angular
Asked Answered
H

15

30

I am working on mat-button-toggle-group for which I modified existing css by overwriting mat-button-toggle-checked class like below. Now, when I toggle between buttons the css is not working till I get focus out and that is because 2 cdk classes 'cdk-focused' and 'cdk-program-focused' are being added when the clicked button is on focus . Is there any way that I can make these classes disable or make them not apply or overwrite them with same css of mat-button-toggle-checked?

<mat-button-toggle-group #group="matButtonToggleGroup" value="line">
    <mat-button-toggle (click)="showLine()" value="line">Line</mat-button-toggle>
    <mat-button-toggle (click)="showChart()" value="chart">Chart</mat-button-toggle>
</mat-button-toggle-group>

and css

mat-button-toggle-group {
    border: solid 1px #d1d8de;
    width:260px;
    height:41px;
    text-align: center;
    .mat-button-toggle-checked{
      background-color: #ffffff;
      font-weight: bold;
    }
    .mat-button-toggle{
      width:50%;
      font-size: 15px;
    }
  }
Hexose answered 23/2, 2018 at 18:15 Comment(2)
have you got rid of that cdk-focused and cdk-program-focused classes? – Natty
My situation was a mat-button that opened a mat-dialog still had focus when the dialog was closed. I solved it by automatically calling blur on the button after the dialog was closed - github.com/angular/components/issues/… – Irisirisa
S
33

You can make use of Angular CDK's FocusMonitor service to disable .cdk-focused and .cdk-program-focused classes by calling the service's stopMonitoring() method.

The documentation for this & the API can be found in the following links respectively:
1) FocusMonitor documentation &
2) FocusMonitor API

The problem I had:

My sidenav had 4 buttons created using *ngFor. Each of these buttons was also a routerLink. Only the button whose router link was active should have primary background color.

Now, this was getting confusing if, say, the routerLink associated with my 4th button was active as the 4th button would have the primary background color and the 1st button had focused styling because of .cdk-focused and .cdk-program-focused classes applied by the FocusMonitor on the button.

The solution:

import { Component, AfterViewInit } from '@angular/core';
import { FocusMonitor } from '@angular/cdk/a11y';

@Component({
    selector   : 'test-component',
    templateUrl: 'test-component.template.html',
})

export class TestComponent implements AfterViewInit {
    constructor(private _focusMonitor: FocusMonitor) {}

    ngAfterViewInit() {
        this._focusMonitor.stopMonitoring(document.getElementById('navButton_1'));
    }
}

You can take a look at the documentations for tailoring this to your need.

Strip answered 19/7, 2018 at 9:56 Comment(2)
excelent answer, I had remove focus programmatly as you say 😁 – Unstrung
I would strongly advise to not change the DOM directly. Use ViewChild and references, it is cleaner and better practice. In the html element put a reference like this : #navButtonRef And then in the component ts add @ViewChild('navButtonRef') navButton: MatAnchor; ngAfterViewInit() { this.focusMonitor.stopMonitoring(this.navButton._elementRef.nativeElement); } – Used
W
11

In my case, the real problem stay in button structure, 'material' build various sub-components and the last one is a 'div' with CSS class 'mat-button-focus-overlay':

My solution is simple, in 'style.css' file, add or subscribe to the 'mat-button-focus-overlay'

.mat-button-focus-overlay { 
background-color: transparent !important; 
}
Wavy answered 25/6, 2019 at 19:11 Comment(1)
I've learned it was best practice to avoid !important to override styling. It usually means the imports could be done better. – Weakfish
G
4

CSS method for the lazy folks:

.your-elements-class-name:focus {
  outline: 0px solid transparent;
}
Goldfarb answered 29/4, 2019 at 21:33 Comment(0)
V
2

I was facing the same issue using a side-nav component.

After reading the solution provided by Aravind here How to use EventEmitter(onClose) of the sidenav I decided to call the following method:

onSideNavOpened() {
    let buttonsList = document.getElementsByClassName('mat-button');

    for(let currentButton of buttonsList) {
      currentButton.classList.remove("cdk-focused");
      currentButton.classList.remove("cdk-program-focused");
    }
  }

Perhaps you can do more or less the same in your ngOnInit() method for instance?

(For the record, my opening side-nav tag looks like this: <mat-sidenav #snav class="menu-sidenav" mode="over" position="end" opened="false" (open)="onSideNavOpened()"> )

Volcanic answered 9/5, 2018 at 15:34 Comment(0)
B
2

Simplest "disable" is just to add the following css override to your component.

:host {
  /deep/ .mat-button-toggle-focus-overlay {
    display: none;    
  }
}
Besides answered 8/5, 2019 at 17:17 Comment(0)
M
2

If buttons are contained by a parent mat element, there is an option to disable autofocus with autoFocus @input property of some elements. For example, mat dialog or mat sidenav have it.

Miguelinamiguelita answered 13/12, 2019 at 20:8 Comment(0)
T
2

The easiest way to get rid of the outline which is created by cdk-focused, cdk-program-focused, cdk-mouse-focused and cdk-touch-focused is by adding

button:focus { outline: none; }

in your styles.css file

Before enter image description here

After enter image description here

Turkey answered 24/1, 2020 at 13:36 Comment(0)
A
1

Scroll Down to the bold text for answers.

Good practice is to not reference by element but by class when changing the style of an element. For example instead of using:

mat-button-toggle-group {
    border: solid 1px #d1d8de;
}

you would write

.mat-button-toggle-group {
    border: solid 1px #d1d8de;
}

Again, this is just good practice.

Another thing that is important (no pun intended) is to point out is that you should refrain from using !important. Generally speaking this should be reserved for special edge cases (like printing). This is because it can lead to harder to maintain stylesheets. A good example of where this would be problematic would be wanting to change the border of this:

.mat-button-toggle-group {
    border: solid 1px #d1d8de !important;
}

because the only way to override an !important is with another !important.

Possible Solutions to your Answer

Have a material-theme-overrides.scss file that basically overrides the way classes are styled. This method is ideal when you want all classes to behave this way by default. Like if you want all of your .mat-buttons to have a radius. Material provides a good guide in doing that: https://material.angular.io/guide/theming

Another option Use ::ng-deep this allows you to force a style down to child components. Read more about that here:

How and Where to use ::ng-deep?

Arithmetician answered 3/3, 2018 at 11:25 Comment(2)
Thanks Don. I already have a custom theme class as you mentioned. But, these are cdk classes – Hexose
Perfect! You can overwrite those the same way. You can check out how material does it by going to there theme file. Thats in your node_modules/@angular/material/_theming.scss – Arithmetician
D
1

I solve this issue with the class css selector of cdk-focused and !important:

.cdk-focused {
  background-color: transparent!important;
}
Deboer answered 11/10, 2019 at 19:26 Comment(0)
P
1

For cdk focused class as base of the problem use:

.cdk-focused, .cdk-mouse-focused {
  outline: 0 !important;
}
Prisca answered 25/6, 2020 at 17:41 Comment(0)
G
0

You can do it if you use sass:

::host {
  &::ng-deep {
    .cdk-program-focused {
      background-color: transparent !important;
    }
  }
}
Georgiannegeorgic answered 25/4, 2021 at 1:30 Comment(0)
R
0

For mat-radio-button works:

.mat-radio-button .mat-radio-ripple {
  height: 0px !important;
  width: 0px !important;
}
Rahmann answered 19/8, 2021 at 11:41 Comment(0)
L
0

the cleanest solution is to remove box-shadow:

.mat-raised-button, .mat-flat-button {
  background-color: #4bcd3e;
  color: #ffffff;
  border-color: #4bcd3e;
  box-shadow: none;
}

.mat-raised-button:not([disabled]).cdk-keyboard-focused,
.mat-raised-button:not([disabled]).cdk-program-focused {
  background-color: #41b336;
  border-color: #41b336;
  color: #ffffff;
  box-shadow: none;
}
Lorenzen answered 2/11, 2021 at 12:13 Comment(0)
B
0

I had to increase the weight of my selector to be able to attack the element

<button mat-stroked-button (click)="close()" class="close">Cancel</button>
.close {
  border-color: var(--primary-color);
  color: var(--primary-color);

  background-color: #fff;

  &.mat-focus-indicator.mat-stroked-button ::ng-deep span.mat-button-focus-overlay {
    background-color: #fff;
    opacity: 0;
  }
}

Please don't use important.

Billyebilobate answered 1/7, 2022 at 8:32 Comment(0)
S
-1

Had you tried adding !important to your selector's attributes:

mat-button-toggle-group {
    border: solid 1px #d1d8de !important;
    width:260px !important;
    height:41px !important;
    text-align: center !important;
    .mat-button-toggle-checked{
      background-color: #ffffff !important;
      font-weight: bold !important;
    }
    .mat-button-toggle{
      width:50% !important;
      font-size: 15px !important;
    }
  }

This way your will override the cdk-focused and cdk-program-focused classes.

Shook answered 28/2, 2018 at 14:17 Comment(1)
yes I did, and my question is the my css is working but 2 new CDK classes are being added when a toggle button is clicked until it has focus on it 'cdk-focused' and 'cdk-program-focused' are the classes..once the focus is gone my css is applied. Please let me know if there is a way to overwrite cdk classes – Hexose

© 2022 - 2024 β€” McMap. All rights reserved.