Reputation: 1134
In my AngularJS controller, I call my data service method, which makes a $http
call to fetch the data needed for page display.
appDataService.getById()
.success(function(document) {
vm.document = document;
}
.error(function(e)){});
Everything is displaying fine and most of my popovers are displaying their contents correctly when toggled / clicked on. However, I am having an issue with one of them.
<button popover-directive
popover-placement="auto"
popover-content="{{ vm.document.content }}"
popover-label="Click to View Text "
class="btn btn-info btn-xs">
</button>
I checked the HTML and can confirm that the popover-content
is given the correct string value. However, when I click on it, the expected triggered-popover behavior did not occur,
i.e. a new <div class="popover fade right in">
did not appear.
If the popover-content
is given a direct value such as popover-content="testing"
, the popover
works properly and shows the content when clicked.
It is my strong suspicion that this is due to the asynchronous behavior of my data fetch; my data is not being returned in time for my popover
to be properly initialized.
Clearly, my popover directive is functioning as it should and I don't think the problem lies with it, but for the sake of a complete picture, I supply my popover directive as follows:
function popoverDirective ($document) {
return {
restrict: 'A',
template: '<span>{{label}}</span>',
link: function (scope, element, attrs) {
scope.label = attrs.popoverLabel;
$(element).popover({
trigger: 'click',
html: true,
content: attrs.popoverContent,
placement: attrs.popoverPlacement
});
}
};
}
Any solutions? Thank you!
Upvotes: 2
Views: 1253
Reputation: 25797
Since the directive attributes are interpolated, consider changing it as:
<button popover-directive
popover-placement="auto"
popover-content="{{vm.document.content}}" <!-- Change at this line -->
popover-label="Click to View Text "
class="btn btn-info btn-xs">
</button>
Also, you need to register an observer since vm.document.content
is resolved via a promise:
function popoverDirective ($document) {
return {
restrict: 'A',
template: '<span>{{label}}</span>',
link: function (scope, element, attrs) {
function initPopover() {
scope.label = attrs.popoverLabel;
// Make sure to remove any popover before hand (please confirm the method)
$(element).popover("destroy");
$(element).popover({
trigger: 'click',
html: true,
content: attrs.popoverContent,
placement: attrs.popoverPlacement
});
}
attrs.$observe("popoverContent", initPopover);
}
};
}
Note Please remove bootstrap.min.js
if you are using Bootstrap and you can also remove jQuery. Angular UI team has ported the Bootstrap Javascript to support Angular. Check this out http://angular-ui.github.io/bootstrap
Upvotes: 1
Reputation: 5217
Have you considered using promises instead of directly returning from the service? The goal here would be that it doesn't matter that your function may immediately return or not, because when the asynchronous value is available, the promise will update to contain that value.
You could update the service itself to utilize a promise and either resolve the promise with the value if successful or reject it if there is an error. On the receiving side of this function, the value on the scope will update when the promise has been resolved one way or another.
Upvotes: 1