108

I've noticed that the directive matTooltip doesn't work on a disabled button. How can I achieve it?

Example:

<button mat-raised-button [disabled]="true" matTooltip="You cannot delete that">
  <mat-icon>delete</mat-icon>
</button>

For an enabled button it works perfectly:

<button mat-raised-button [disabled]="false" matTooltip="You cannot delete that">
  <mat-icon>delete</mat-icon>
</button>
Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
Marcin Kunert
  • 5,596
  • 5
  • 26
  • 52
  • Note that your text goes against Material Design guide. The tooltip should only describe button. The information that someone cannot delete something should be displayed elsewhere. Source:https://material.io/guidelines/components/tooltips.html# – kvetis Jan 16 '18 at 09:40
  • Thanks for the tip. I wonder how to make it better. If I would call it like: "This button is disabled because you are not allowed to delete that" would it be acceptable? – Marcin Kunert Jan 16 '18 at 09:47
  • 2
    In my opinion it should be clear from the context of the button already. When a button is disabled and has a trash icon, that already explains that _user cannot delete that_ without using words. If you want to explain _why_ I think you should use a different approach than tooltip. I'm not expert and maybe you'd do better asking on ux.stackexchange.com. I did a quick search there: https://ux.stackexchange.com/search?q=tooltip+on+disabled+button that might be of interest of both of us. – kvetis Jan 16 '18 at 10:03
  • 4
    I've found it useful to preempt validation. Better a button that is disabled with a tooltip showing "You must select an event first." than one that must be clicked to display the error, or is disabled and gives no information. – Stephen Turner Jun 22 '18 at 08:48

11 Answers11

183

This doesn't work because it is triggered by mouseenter event which doesn't get fired by most browsers for disabled elements. A workaround is to add matTooltip to a parent element:

<div matTooltip="You cannot delete that" [matTooltipDisabled]="!isButtonDisabled()">
    <button mat-raised-button [disabled]="isButtonDisabled()">
        <mat-icon>delete</mat-icon>
    </button>
</div>

The example above assumes that there is a method for determining if the button should be enabled or not. By using matTooltipDisabled the tooltip will be shown only if the button is disabled.

References:

Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
Marcin Kunert
  • 5,596
  • 5
  • 26
  • 52
  • 1
    I may be missing something, but doesn't this show whether the button is disabled or not? It seems to display well, but I just want it to show when the button is disabled. – goneos Dec 04 '18 at 21:03
  • For anyone who is looking for a solution that will ONLY show when the button is disabled, refer to https://stackoverflow.com/questions/29201953/set-tooltip-for-a-disabled-button – goneos Dec 04 '18 at 21:27
  • 1
    @goneos I've updated the answer to answer your question – Marcin Kunert Dec 05 '18 at 11:20
  • 1
    Thanks @MarcvinKunert. I did it a little differently `matTooltip="isButtonDisabled() ? 'You cannot delete that' : ''"` – goneos Dec 05 '18 at 19:40
  • 2
    I'm actually getting a message saying that div doesn't take a matTooltipDisabled attribute. Can I confirm that you don't get that? – Sean Duggan Feb 05 '20 at 18:29
  • @SeanDuggan I confirm, that it works for me. What tool is giving you this message? – Marcin Kunert Feb 06 '20 at 07:19
  • @MarcinKunert: *facepalm* It was a combination of me having forgotten to import the right module, and then misspelling "matTooltip". Thank you. – Sean Duggan Feb 06 '20 at 15:02
  • You could add `style="display:inline"` to the div if you don't want to box the button. – Peter Feb 18 '20 at 14:52
  • Adding this changes the CSS of the tooltip. Hovering on button shows the tooltip on the left side. Checkout here https://ibb.co/6DPXgGK – Karan Patokar Aug 13 '21 at 11:46
32

I had a similar issue while displaying tooltip on a disabled icon button. The given solution was not practical for me, because adding an additional div on top of the button, messed up the layout of the button relative to the other buttons in the tool bar.

A simpler solution for me was to add the tooltip inside the icon inside the button. Something like this:

<button mat-raised-button [disabled]="true">
    <mat-icon matTooltip="You cannot delete that">delete</mat-icon>
</button>

Since the icon is not disabled, it works.

Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
Sumit
  • 2,189
  • 7
  • 32
  • 50
21

Yes, the simplest solution is like above. But for my case I needed more flexibility.

   <button  [disabled]="form.invalid">
      <span [matTooltip]="form.invalid ? 'some text' : ''">button text</span>
    </button>
Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
Fes9L
  • 448
  • 4
  • 5
10

Adding tooltip inside mat-icon in a button as suggested by others will only work when you hover the icon not the button. Instead of that you can just wrap your button around another div without any css classes, just tooltip.

Additionally you can also add matTooltipDisabled property to make sure your tooltip is never disabled.

<div matTooltip="You cannot delete that" [matTooltipDisabled]="false">
  <button mat-raised-button [disabled]="true">
     <mat-icon>delete</mat-icon>
  </button>
</div>
Sksaif Uddin
  • 642
  • 1
  • 15
  • 22
2

Try this:

<div [matTooltip]="isDisabled ? 'You cannot delete that' : ''">
    <button mat-raised-button [disabled]="isDisabled">
      <mat-icon>delete</mat-icon>
    </button>
    <div>
Tom Slabbaert
  • 21,288
  • 10
  • 30
  • 43
AnnyNeMy
  • 21
  • 1
  • 3
    Welcome to Stack Overflow! While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. –  Jul 07 '20 at 15:39
1

You can use title attribute it will display in necessary cases

<button mat-raised-button [disabled]="true" title = "Some text">
  <mat-icon>delete</mat-icon>
</button>

you can do property binding with ternary operators

Frederik Struck-Schøning
  • 12,981
  • 8
  • 59
  • 68
1

I find a solution!

Put the tooltip into the button content like this:

<button type="submit" [disabled]="disableEdit()" class="btn btn-primary btn-sm"
        [routerLink]="['/entity', entity.id, 'edit']">
    <div matTooltip="{{ 'entity.placeholders.cantEdit' | translate }}"
         [matTooltipDisabled]="disableEdit()">
        <fa-icon [icon]="'pencil-alt'"></fa-icon>
        <span class="d-none d-md-inline">{{ 'entity.action.edit' | translate }}</span>
    </div>
</button>
Juan Lamberti
  • 11
  • 1
  • 6
1

I know this is ugly but you also do this way, Use multiple buttons with ngIf

<!-- No click action -->
<button *ngIf="disable" mat-raised-button matTooltip="You cannot delete that">
  <mat-icon>delete</mat-icon>
</button>
<button *ngIf="!disable" mat-raised-button (click)="delete()">
  <mat-icon>delete</mat-icon>
</button>
Sameer
  • 4,758
  • 3
  • 20
  • 41
1

Just add style 'pointer-events: all' to your button like this

<button mat-raised-button style="pointer-events: all" [disabled]="true" matTooltip="You cannot delete that">
  <mat-icon>delete</mat-icon>
</button>
syed zahed
  • 29
  • 3
  • 2
    This worked great for me. Much easier than adding additional div wrappers or switch statements. Thanks for this! – Michael Norgren Jan 11 '22 at 15:38
  • Sadly "pointer-events: all" seems to be a feature only targeting SVG elements. It would be so great if it actually worked on normal DOM elements. – Greg Grundy Jul 17 '22 at 23:29
0

Angular and Angular Material 15

You can add the matTooltip to the child element, most logically in case of a material button the span holding the button text or the mat-icon with the material icon.

When using Material buttons the disabled button has by default the style pointer-events: none applied; see global material style for the buttons:

Icon buttons:

.mdc-icon-button:disabled,
.mat-mdc-icon-button[disabled] {
  pointer-events: none;
}

Normal buttons:

.mdc-button[disabled],
.mat-mdc-button[disabled] {
  pointer-events: none;
}

You will need to cancel this out for the child elements if you want the tooltip to show on hovering the button. This can be easily solved like this:

<button #myIconButton mat-icon-button [disabled]="!isAllowedDelete">
  <mat-icon [style.pointer-events]="'all'"
            matTooltip="You are not allowed to delete this item"
            [matTooltipDisabled]="!myIconButton.disabled">delete</mat-icon>
</button>

<button #myButton mat-button [disabled]="!isAllowedDelete">
  <span [style.pointer-events]="'all'"
        matTooltip="You are not allowed to delete this item"
        [matTooltipDisabled]="!myButton.disabled">delete</span>
</button>

Or alternatively if you want it in your stylesheet:

button[disabled] span.mat-mdc-tooltip-trigger
button[disabled] mat-icon.mat-mdc-tooltip-trigger {
  /* Allows for tooltips to be triggered on disabled buttons */
  pointer-events: all;
}

In my opinion this is better then wrapping the button in an element, you can now disable/enable the tooltip directly using the button "disabled" state (myButton.disabled) and you don't need to add any additional wrappers or elements to the DOM.

Checkout a working example in this Stackblitz.

Wilt
  • 41,477
  • 12
  • 152
  • 203
-1

Not only matTooltip, even title attribute doesn't work on disabled button.

Just add the tooltip on its containing div, not on the button itself.

<div title="Some tooltip message">
  <button type="button" [disabled]="!enable()">My Button</button> 
</div>
Adir Dayan
  • 1,308
  • 13
  • 21