My HTML form has many questions I create using ng-repeat. I want to create a pop-over for some questions. When I put the button that triggers the pop-over outside the ng-repeat, it works. Inside the ng-repeat it does not.
This works (button before ng-repeat):
<div class="row">
<div class="col-md-12">
<button title="" data-toggle="popover" data-placement="top" data-trigger="hover" data-title="Popover on hover" data-content="And here's some amazing content. It's very engaging. Right?" class="btn btn-primary btn-wide">
hover
</button>
<div ng-repeat="q in config.questionnaire.questions">
Producing this:
This does not work (button after ng-repeat):
<div class="row">
<div class="col-md-12">
<div ng-repeat="q in config.questionnaire.questions">
<button title="" data-toggle="popover" data-placement="top" data-trigger="hover" data-title="Popover on hover" data-content="And here's some amazing content. It's very engaging. Right?" class="btn btn-primary btn-wide">
hover
</button>
Inspecting the button element on google chrome, I found that some event listeners were removed:
These are the event listeners for the button before the ng-repeat:
These are the event listeners for the button after the ng-repeat:
As you can see, mouseover and mouse out listeners disappeared.
Why?
What can I do?
If you are using Bootstrap with your Angular project, think of using Angular UI library.
https://angular-ui.github.io/bootstrap/#/popover
It provides many directives which make it easier to connect Bootstrap with Angular. I tested the uib-popover
directive with ng-repeat
and it works properly this way. The code is pretty simple:
//...
<div ng-repeat="t in main.testArray">
<button uib-popover="My popover content" popover-title="Popover title" popover-trigger="mouseenter">{{t.text}}</button>
</div>
//...
I will try to investigate your problem further, but the library seems to be an easy workaround.
Edit
I think I also managed to figure out a solution without using external library. What I did was creating a directive which initializes Boostrap popover on specified element. This way you make sure that the popover
function will be fired when elements are rendered. I guess this was the reason why it didn't work with your method. You probably invoked the popover
function before elements were really rendered as ng-repeat
does this with a delay.
And here is the code:
angular.module('moduleName')
.directive('bootstrapPopover', function() {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.popover();
}
};
});
And then use directive on element:
<div ng-repeat="t in main.test">
<button data-toggle="popover" data-placement="top" data-trigger="hover" data-title="Test" data-content="Test"
class="btn btn-primary btn-wide" bootstrap-popover>hover {{t.text}</button>
</div>
However, I would still recommend trying the Angular UI out. I used it in the last Angular project and it was really helpful.