Angular directive for bootstrap popover

2019-07-07 20:49发布

问题:

I write my custom directive for bootstrap popover, but face some trouble. This is the code:

angular.module('CommandCenterApp')
.directive('bzPopover', function($compile,$http, $commandHelper) {
    return{
        restrict: "A",
        replace: false,
        scope: {
            currencies:"=data",
            selected:"=selected"
        },
        link: function (scope, element, attrs) {
            var html = '<div class="currency-popup">' +
                '<span class="select-label">Select currency:</span>'+
                '<select class="custom-select" ng-model="selected" ng-options="currency.CurrencyName for currency in currencies track by currency.CurrencyId">' +

                '</select>' +
                '<button class="btn btn-green" ng-click="saveCurrency()">Save</button>'+
                '</div>';
            var compiled = $compile(html)(scope);
            $(element).popover({
                content:compiled,
                html: true,
                placement:'bottom'
            });
            scope.saveCurrency = function () {
                var obj = {
                    Currency:scope.selected,
                    venueId: $commandHelper.getVenueId()
                }
                $http.post("/api/currencyapi/changecurrency", obj).success(function() {
                    scope.$emit('currencySaved', scope.selected);
                });
                //$(element).popover('hide');
            }
            scope.$watch('selected', function() {
                console.log(scope.selected);
            });
        }
    }

});

When I first time invoke popover all works fine, I click on button and it trigger scope.saveChanges function. Then I close popover and invoke it again, and directive doesnt work anymore. In markup popover present as:

<a bz-popover data="controller.currencies" selected="controller.selectedCurrency" class="change-currency hidden-xs hidden-sm" href>Change currency</a>

Can anyone help me with this?

UPDATE: it looks like all bindings(scope.saveCurrency,watched on selected property) stop working after popover hidding.

回答1:

Not really sure if this is the problem you're describing because in my fiddle I had to click twice on the button to show the popover after closing the popover.

I don't know what's the problem but with trigger: 'manual' and binding to click event it is working as expected.

Please have a look at the demo below or in this jsfiddle.

I've commented some of your code because it's not needed to show the popover behaviour and also the ajax call is not working in the demo.

angular.module('CommandCenterApp', [])
.controller('MainController', function() {
    this.currencies = [{
        CurrencyId: 1,
        CurrencyName: 'Dollar'},{
          CurrencyId: 2,
        CurrencyName: 'Euro'}];
})
.directive('bzPopover', function($compile,$http) { //, $commandHelper) {
    return{
        restrict: "A",
        replace: false,
        scope: {
            currencies:"=data",
            selected:"=selected"
        },
        link: function (scope, element, attrs) {
            var html = '<div class="currency-popup">' +
                '<span class="select-label">Select currency:</span>'+
                '<select class="custom-select" ng-model="selected" ng-options="currency.CurrencyName for currency in currencies track by currency.CurrencyId">' +

                '</select>' +
                '<button class="btn btn-green" ng-click="saveCurrency()">Save</button>'+
                '</div>';
            var compiled = $compile(html)(scope);
            $(element).popover({
                content:compiled,
                html: true,
                placement:'bottom',
                trigger: 'manual'
            });
            $(element).bind('click', function() {
            	$(element).popover('toggle');
            });
            
            scope.saveCurrency = function () {
                var obj = {
                    Currency:scope.selected,
                    venueId: 1//$commandHelper.getVenueId()
                }
                $http.post("/api/currencyapi/changecurrency", obj).success(function() {
                    scope.$emit('currencySaved', scope.selected);
                });
                $(element).popover('hide');
            }
            scope.$watch('selected', function() {
                console.log(scope.selected);
            });
        }
    }

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/js/bootstrap.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.css" rel="stylesheet"/>
<div ng-app="CommandCenterApp" ng-controller="MainController as controller">
<button bz-popover data="controller.currencies" selected="controller.selectedCurrency" class="change-currency hidden-xs hidden-sm">Change currency</button>
</div>



回答2:

Shameless self-promotion here, but you may want to take a look at the Angualr UI Bootstrap library as we've already done this for you. And even if you don't want to use it, you can just grab the code you need...