ng-click inside bs-tooltip not working - angularjs

I'm using angular-strap tooltip and inside I have link that should react to ng-click, but instead it's not responding.
.html
<span class="add-on input-group-addon" data-title="{{tooltips.date}}" bs-tooltip>
<i class="glyphicon glyphicon-calendar fa fa-calendar"></i> Dates
</span>
.js
$scope.tooltips = {
date: '<a class="btn btn-default" ng-click="select()">Select date</a>'
};
$scope.select = function() {
//doing something and works fine outside tooltip
}
In app .config() there is html set to true.
angular.extend($tooltipProvider.defaults, {
template: "static/lib/angular-strap/tooltip.tpl.html",
trigger: 'click',
html: true,
placement: 'bottom-left'
});

By using data-title along with html: true you are just passing some html, but it is not compiled by angular. If you want to use angular directives and data binding in your tooltip, use 'contentTemplate'; here is a working plunker: http://plnkr.co/LSl9gyHRKCMYoEGZZQei

Related

AngularJS directive to add content after element and trigger element click

I'm trying to create a very simple directive to ask confirmation on a button click.
The following html:
<button kr-confirm>Delete</button>
Should compile into:
<button kr-confirm>Delete</button>
<span ng-show="vm.isOpen">
Are you sure?
<span class="btn btn-sm btn-danger">Yes</span>
<span class="btn btn-sm btn-secondary">No</span>
</span>
I wanted to handle this in templateUrl, but could not find an option to add template after element.
I ended up adding DOM in link function and calling element.on('click') but this doesn't seem to work.
Based on HTML and anticipated result, how would I go about implementing this?
Best case would be if it could be solved with templateUrl.
See my current fiddle:
https://jsfiddle.net/kraaness/4rn8ycb3/
You should create a component that will provide you with the desired functionality. See a quick <confirmation-button> component below.
angular.module('app', [])
.component('confirmationButton', {
bindings: {
onConfirm: '&'
},
template: '<button ng-click="$ctrl.confirm = true">Delete</button>' +
'<div ng-show="$ctrl.confirm">Are you sure?' +
'<button ng-click="$ctrl.onConfirm(); $ctrl.confirm = false">Yes</button>' +
'<button ng-click="$ctrl.confirm = false">No</button></div>'
})
.run(function($rootScope) { // using $rootScope just for sake of the demo
$rootScope.delete = function() {
alert("Oh no!");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="app">
<confirmation-button on-confirm="delete()"></confirmation-button>
</div>

AngularJS binding to Bootstrap Popover attribute

I'm trying to dynamically populate the data-title and the data-content of a Bootstrap popover from a JSON create in an AngularJS controller.
Controller Snippet:
$scope.popoverContent = {name: {title: "title", content: "content"}}
HTML Snippet:
<span class="glyphicon glyphicon-question-sign"
aria-hidden="true"
data-toggle="popover"
data-trigger="hover"
data-title="{{popoverContent.name.title}}"
data-placement="right"
data-content="{{popoverContent.name.content}}">
</span>
I'm getting the exact text between the double quotes in the HTML page, {{popoverContent.name.title}}.
I've tried with ng-attr-data-title="{{popoverContent.name.title}}" but in this case, the title does not get displayed at all.
Other variables set in the controller are getting displayed properly in the HTML page.
Is is possible to implement something like this?
Try this code
var demo = angular.module('demo', []);
demo.controller('loadData', function($scope){
$scope.uploadData = function() {
$scope.popoverContent = {name: {title: "title", content: "content"}};
};
});
demo.directive("popUps",function(){
return {
restrict:'E',
replace: true,
transclude: false,
template:'<span class="glyphicon glyphicon-question-sign" aria-hidden="true" data-toggle="popover" data-trigger="hover" data-title="{{popoverContent.name.title}}" data-placement="right" data-content="{{popoverContent.name.content}}">data-title:{{popoverContent.name.title}}</br>data-content:{{popoverContent.name.content}}</span>'
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script>
<div ng-app='demo'>
<div ng-controller='loadData'>
<button ng-click='uploadData($event)' >show</button>
<div>
<pop-ups></pop-ups>
</div>
</div>
</div>

uib-timepicker broken when $compile

I want to use a 'uib-timepicker' inside a popover, so as I read, I need to $compile the html to bind it to angular scope:
app.directive('bsPopover', function($compile) {
return function(scope, element, attrs) {
element.find('#formula-nro').popover({
html : true,
title : '<span>Title</span>',
content : function() {
return $compile($('#formula_form_nro').html())(scope);
// return $('#formula_form_nro').html();
}
});
};
});
If I compile the code, the component brokes, but when I don't, it's shows and behaves correctly, but it is not binded to angular scope.
This is the HTML code of the component:
<div id="formula_form_nro" class="padding-block hide">
.....
<uib-timepicker ng-model="time" minute-step="15" readonly-input="true"> </uib-timepicker>
.....
</div>
The following is the popover button:
<button id="formula-nro" type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="top">f(x)</button>
The button is inside a ng-repeat:
<div ng-repeat="item in items" bs-popover>
It looks like a bug, but I don't know if am I doing well. Maybe there is a workaround for this ..
thanks,

Can't create a popover with custom template

First I tried using angular-ui
<span popover-template="removePopover.html" popover-title="Remove?" class="glyphicon glyphicon-remove cursor-select"></span>
here the template is not included and no errors are provided in console. As I undestood from previous questions this capability is still in development (using v0.13.0).
Then I tried using bootstrap's popover
<span delete-popover row-index={{$index}} data-placement="left" class="glyphicon glyphicon-remove cursor-select"></span>
This is included to popover
<div id="removePopover" style="display: none">
<button id="remove" type="button" ng-click="removeElement()" class="btn btn-danger">Remove</button>
<button type="button" ng-click="cancelElement()" class="btn btn-warning">Cancel</button>
</div>
This is the managing directive
app.directive('deletePopover', function(){
return{
link: function(scope, element, attrs) {
$(element).popover({
html : true,
container : element,
content: function() {
return $('#removePopover').html();
}
});
scope.removeElement = function(){
console.log("remove"); //does not get here
}
scope.cancelElement = function(){
console.log("cancel"); //does not get here
}
}
};
});
In case of bootstrap's popover the scope is messed up. cancelElement() call does not arrive in directive neither the parent controller.
If anyone could help me get atleast on of these working it would be great.

Invoking modal window in AngularJS Bootstrap UI using JavaScript

Using the example mentioned here, how can I invoke the modal window using JavaScript instead of clicking a button?
I am new to AngularJS and tried searching the documentation here and here without luck.
Thanks
OK, so first of all the http://angular-ui.github.io/bootstrap/ has a <modal> directive and the $dialog service and both of those can be used to open modal windows.
The difference is that with the <modal> directive content of a modal is embedded in a hosting template (one that triggers modal window opening). The $dialog service is far more flexible and allow you to load modal's content from a separate file as well as trigger modal windows from any place in AngularJS code (this being a controller, a service or another directive).
Not sure what you mean exactly by "using JavaScript code" but assuming that you mean any place in AngularJS code the $dialog service is probably a way to go.
It is very easy to use and in its simplest form you could just write:
$dialog.dialog({}).open('modalContent.html');
To illustrate that it can be really triggered by any JavaScript code here is a version that triggers modal with a timer, 3 seconds after a controller was instantiated:
function DialogDemoCtrl($scope, $timeout, $dialog){
$timeout(function(){
$dialog.dialog({}).open('modalContent.html');
}, 3000);
}
This can be seen in action in this plunk: http://plnkr.co/edit/u9HHaRlHnko492WDtmRU?p=preview
Finally, here is the full reference documentation to the $dialog service described here:
https://github.com/angular-ui/bootstrap/blob/master/src/dialog/README.md
To make angular ui $modal work with bootstrap 3 you need to overwrite the styles
.modal {
display: block;
}
.modal-body:before,
.modal-body:after {
display: table;
content: " ";
}
.modal-header:before,
.modal-header:after {
display: table;
content: " ";
}
(The last ones are necessary if you use custom directives) and encapsulate the html with
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
Open modal windows with passing data to dialog
In case if someone interests to pass data to dialog:
app.controller('ModalCtrl', function($scope, $modal) {
$scope.name = 'theNameHasBeenPassed';
$scope.showModal = function() {
$scope.opts = {
backdrop: true,
backdropClick: true,
dialogFade: false,
keyboard: true,
templateUrl : 'modalContent.html',
controller : ModalInstanceCtrl,
resolve: {} // empty storage
};
$scope.opts.resolve.item = function() {
return angular.copy(
{name: $scope.name}
); // pass name to resolve storage
}
var modalInstance = $modal.open($scope.opts);
modalInstance.result.then(function(){
//on ok button press
},function(){
//on cancel button press
console.log("Modal Closed");
});
};
})
var ModalInstanceCtrl = function($scope, $modalInstance, $modal, item) {
$scope.item = item;
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}
Demo Plunker
The AngularJS Bootstrap website hasn't been updated with the latest documentation. About 3 months ago pkozlowski-opensource authored a change to separate out $modal from $dialog commit is below:
https://github.com/angular-ui/bootstrap/commit/d7a48523e437b0a94615350a59be1588dbdd86bd
In that commit he added new documentation for $modal, which can be found below:
https://github.com/angular-ui/bootstrap/blob/d7a48523e437b0a94615350a59be1588dbdd86bd/src/modal/docs/readme.md.
Hope this helps!
Quick and Dirty Way!
It's not a good way, but for me it seems the most simplest.
Add an anchor tag which contains the modal data-target and data-toggle, have an id associated with it. (Can be added mostly anywhere in the html view)
Now,
Inside the angular controller, from where you want to trigger the modal just use
angular.element('#myModalShower').trigger('click');
This will mimic a click to the button based on the angular code and the modal will appear.
Different version similar to the one offered by Maxim Shoustin
I liked the answer but the part that bothered me was the use of <script id="..."> as a container for the modal's template.
I wanted to place the modal's template in a hidden <div> and bind the inner html with a scope variable called modal_html_template
mainly because i think it more correct (and more comfortable to process in WebStorm/PyCharm) to place the template's html inside a <div> instead of <script id="...">
this variable will be used when calling $modal({... 'template': $scope.modal_html_template, ...})
in order to bind the inner html, i created inner-html-bind which is a simple directive
check out the example plunker
<div ng-controller="ModalDemoCtrl">
<div inner-html-bind inner-html="modal_html_template" class="hidden">
<div class="modal-header">
<h3>I'm a modal!</h3>
</div>
<div class="modal-body">
<ul>
<li ng-repeat="item in items">
<a ng-click="selected.item = item">{{ item }}</a>
</li>
</ul>
Selected: <b>{{ selected.item }}</b>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</div>
<button class="btn" ng-click="open()">Open me!</button>
<div ng-show="selected">Selection from a modal: {{ selected }}</div>
</div>
inner-html-bind directive:
app.directive('innerHtmlBind', function() {
return {
restrict: 'A',
scope: {
inner_html: '=innerHtml'
},
link: function(scope, element, attrs) {
scope.inner_html = element.html();
}
}
});

Resources