57

I am trying to use angular-ui's tooltip functionality to show my user that a particular field is invalid but it seems that the tooltip can be shown only on some pre-defined triggers. Is there any way by which I can trigger the tooltip except those triggers?

For example:

<input
    type="text"
    tooltip="Invalid name!"
    tooltip-position="right"
    tooltip-trigger="myForm.username.$invalid">
Léo Lam
  • 3,870
  • 4
  • 34
  • 44
vivek
  • 2,807
  • 5
  • 31
  • 44

5 Answers5

108

Here's a trick.

Twitter Bootstrap tooltips (that Angular-UI relies upon) have an option to specify the trigger event with an additional attribute as in data-trigger="mouseenter". This gives you a way of changing the trigger programmatically (with Angular):

<input 
  ng-model="user.username"
  name="username"
  tooltip="Some text" 
  tooltip-trigger="{{{true: 'mouseenter', false: 'never'}[myForm.username.$invalid]}}" 
/>

So when username is $invalid, the tooltip-triggerexpression will evaluate to 'mouseenter' and tooltip will show up. Otherwise, the trigger will evaluate to 'never' which in return won't fire up the tooltip.

EDIT:

@cotten (in comments) mentions a scenario where tooltip gets stuck and won't go away even when model is valid. This happens when mouse stays over the input field while the text is being entered (and model becomes valid). As soon as model validation evaluates to true, the tooltip-triggerwill switch to "never".

UI Bootstrap uses a so called triggerMap to determine on which mouse events to show/hide the tooltip.

// Default hide triggers for each show trigger
var triggerMap = {
  'mouseenter': 'mouseleave',
  'click': 'click',
  'focus': 'blur'
};

As you may see, this map knows nothing about the "never" event, so it's unable to determine when to close the tooltip. So, to make out trick play nicely we only need to update this map with our own event pair and UI Bootstrap will then know what event to observe for closing the tooltip when tooltip-trigger is set to "never".

app.config(['$tooltipProvider', function($tooltipProvider){
  $tooltipProvider.setTriggers({
    'mouseenter': 'mouseleave',
    'click': 'click',
    'focus': 'blur',
    'never': 'mouseleave' // <- This ensures the tooltip will go away on mouseleave
  });
}]);

PLUNKER

Note: $tooltip provider is exposed by the "ui.bootstrap.tooltip" module and it allows us to globally configure our tooltips in app configuration.

Stewie
  • 60,366
  • 20
  • 146
  • 113
  • 7
    This answer should be accepted and example really added to tooltip details page. – vittore Jun 07 '13 at 01:46
  • I cannot get this to work. Please see: http://jsbin.com/ekeset/1/edit. When the form is valid, the tooltip is not disapearing... – Cotten Aug 09 '13 at 08:10
  • The "working" jsbin has stopped working, here's a plnkr that demonstrates it. http://plnkr.co/edit/s8tkXVji4UK0AZaUC1vK?p=preview – boatcoder Jan 18 '14 at 23:36
  • 5
    This is pretty clever but it just doesn't seem to work as a user would expect. They have to blur the field, then focus to see their error message and with the mouseover they have to mouseover the field to see what's wrong. If we had the ability to define custom triggers we could just show the error message whenever we wanted (like dirty && invalid). – creamcheese Feb 15 '14 at 20:50
  • @Stewie How to do this same thing if i used angular-validator plugin ?? I can't able to perform validation when i use this method – arjun Sep 04 '14 at 09:36
  • 1
    Agree with @DominicWatson. Ideally as soon as the user tabs off the field (or otherwise removes focus), the tooltip appears. It would then be automatically hidden as soon as the error is corrected (this time within the field, should be no need to tab out). Anything else is unintuitive. Can we make this work? – Patrick Oct 29 '14 at 19:24
32

I tried something different

tooltip="{{(myForm.input1id.$invalid) ? 'You have an error with this field' : ''}}"

This way, my tooltip only has something written when the input is invalid, and if it doesn't have anything written, the tooltip doesn't show.

Victor Ivens
  • 2,221
  • 2
  • 22
  • 32
  • This works very well if you pair it with the right popover-trigger event. For example i'm validating on a text input so the keyup even then forces the popup to re-evaluate on each keyup event. I tried 'focus' first, but then the error message only showed up if i clicked out, then into the element. `````` – nomis Jul 11 '14 at 18:10
9

From version 0.12.0 onwards, tooltip-tigger is no longer observable (so you can't change it programatically).

You can use tooltip-enable to get the same behavior. See more details here: https://github.com/angular-ui/bootstrap/issues/3372

Bruno
  • 304
  • 4
  • 10
4

You can also add the tooltip-enable instead of the tooltip-trigger on your field.

<input
    type="text"
    tooltip="Invalid name!"
    tooltip-position="right"
    tooltip-enable="{{myForm.username.$invalid}}">

In this case if the username is invalid ($invalid returns true) the tooltip will appear.

Salma Hamed
  • 2,000
  • 4
  • 26
  • 45
  • This is so much simpler and more readable than the accepted answer, and also closer to OPs original code – daniero Aug 31 '16 at 11:19
1

As per the new version document I will suggest to use below HTML. stewie's answer is not helpful with latest version.

<input class="form-control" name="name" type="text" required ng-model="name"
                   uib-tooltip="name required" tooltip-is-open="formname.name.$invalid" 
tooltip-trigger="none" tooltip-placement="auto top" />

Replace just your form name in tooltip-is-open="formname.name.$invalid"

you are good to go.

nirmal
  • 2,143
  • 1
  • 19
  • 29