ng-click and ng-model not working in a popover - angularjs

I have an ng-click in in a bootstrap popover that doesnt seem to work. when I move it out of the popup into the page it seems to work. Also the ng-model value doesnt seem to update either.
<div id="popover-content" class="hide">
<input type="text" placeholder="Quote ID" ng-model="selectedItems.quote.label">
<button type="button" ng-click="newQuote()">New quote</button>
</div>
Is this because the popover is created in the dom and angular does not know it exists? Any ideas how I can get it to work? Thanks
EDIT:
Here is the newQuote
$scope.newQuote = function() {
$scope.selectedItems.quote = angular.copy(defaultQuote);
$scope.solution.quotes.push($scope.selectedItems.quote);
$scope.selectedItems.quote.label = 'New Quote';
$scope.addMessage('Quote created successfully', 2);
};
EDIT 2
Here is a plunker showing the issue - the alert is not displayed when ng-click="newQuote()" is fired
http://plnkr.co/edit/ANH98vlflPK9c5qA3ohO?p=preview

You should create a Directive to make angular works with Bootstrap Popover. You can take a look in your Developer console when using Bootstrap Popover. It actually does not reuse the DOM that you predefined - ie :
<input type="text" placeholder="Quote ID" ng-model="selectedItems.quote.label">
<button type="button" ng-click="newQuote()">New quote</button>
But add in a new piece of DOM - ie
<div class="popover fade bottom in" role="tooltip" id="popover770410" style="top: 30px; left: 0px; display: block;">
<div class="arrow" style="left: 15.9420289855072%;">
</div><h3 class="popover-title">New quote</h3><div class="popover-content">
<input type="text" placeholder="Quote ID" ng-model="selectedItems.quote.label" class="ng-pristine ng-untouched ng-valid">
<button type="button" ng-click="newQuote()">New quote</button>
</div>
</div>
Therefore Angular will not understand new piece of DOM because it has not compiled yet - ie : You cannot use ng-click as well as ng-modal. One way to work around this is to create a directive and compile your html content before passing that piece of DOM to Bootstrap Popover.
I have created this fiddle to demonstrate this idea.
As you can see :
I have compile you content and bind it to current scope
$compile(content)(scope);
Before passing that piece of DOM to popover
var options = {
content: compileContent,
html: true,
title: title
};
$(elem).popover(options);
With this way to can let Angular understand new piece of DOM added and do its work correspondingly.
Furthermore, actually there quite some directives that works with Bootstrap Popover that you can take a look at instead of creating new directives
AgularUI Bootstrap
Angular Strap
Reference :
http://tech.pro/tutorial/1360/bootstrap-popover-using-angularjs-compile-service
twitter bootstrap popover doesn't work with angularjs

Related

AngularJS- How to handle each button created by ng-repeat

I am new to AngularJS.
I have created <li> to which I used ng-repeat.
<li> contains images and buttons like like, comment and share which is inside <li> and created by ng-repeat.
I have made function which will replace empty like button to filled like button (By changing background image of button).
But problem is this trigger applies to only first like button and other buttons does not change.
How can I fix this?
Code:
HTML:
<html>
<body>
<ul>
<li ng-repeat="media in images"><div class="imgsub">
<label class="usrlabel">Username</label>
<div class="imagedb">
<input type="hidden" value="{{media.id}}">
<img ng-src="{{ media.imgurl }}" alt="Your photos"/>
</div>
<!-- <br><hr width="50%"> -->
<div class="desc">
<p>{{media.alt}}</p>
<input type="button" class="likebutton" id="likeb" ng-click="like(media.id)" ng-dblclick="dislike(media .id)"/>
<input type="button" class="commentbutton"/>
<input type="button" class="sharebutton"/>
</div>
</div> <br>
</li><br><br><br>
</ul>
</body>
</html>
JS:
$scope.like = function(imgid)
{
document.
getElementById("likeb").
style.backgroundImage = "url(src/assets/like-filled.png)";
alert(imgid);
}
$scope.dislike = function(imgid)
{
document.
getElementById("likeb").
style.backgroundImage = "url(src/assets/like-empty.png)";
}
Thanks for help & suggestions :)
The id for each button should be unique but in your case, it's the same for all buttons ('likeb').
You can set the value of the attribute 'id' for each button dynamically by using '$index' and passing '$index' to the functions as follows:
<input type="button" class="likebutton" id="{{$index}}" ng-click="like($index)" ng-dblclick="dislike($index)"/>
Then in your controller, you can use the functions with the passed value.
For example,
$scope.like = function(index)
{
document.
getElementById(index).
style.backgroundImage = "url(src/assets/like-filled.png)";
}
Another good alternative in your case would be to use the directive ngClass.
use 2 css class for styling liked and disliked state, and then put the class conditionally with ng-class instead of DOM handling. and if you really want to perform a DOM operation (I will not recommend) then you can pass $event and style $event.currentTarget in order to perform some operation on that DOM object.

AngularJS Bootstrap Popover Button Ignoring <BR />

We have an Angular Bootstrap popover tooltip that contains some html content and scope variables along with a button inside the popover.
Currently we have a small version running in Plunkr and the popover html is being displayed correctly including all break tags.
The problem seems to occur when we run in locally in Visual Studio where all of the break tags are recognized until the button is rendered, then it seems to be completely ignored and the button gets dropped at the top of the popover:
<div>
Name: {{ person.fullName }}
<br />
Dept: {{ person.deptId }}
<br />
Job Desc: {{ person.jobDesc}}
<br />
Phone:{{ person.phone}}
<br />
One!<br />
Two!<br />
Three!<br />
<input type="button" value="Click Me" class="btn btn-default" ng-click="changeName()">
We saw a couple of posts where $sce.trustAsHtml was used and added that as well as data-html='true'
scope.htmlPopover = $sce.trustAsHtml('./HTML/popoverTemplate.html');
element[0].setAttribute('data-html', 'true');
element[0].setAttribute('uib-popover-template', "htmlPopover");
element[0].setAttribute('popover-append-to-body', 'true');
element[0].setAttribute('popover-trigger', "'click'");
This did not solve our problem.
Both the Plunk and our local project are running Angular 1.6.2 and Angular Bootstrap 2.5.0.
Can't figure out why this would work in Plunkr and not in Visual Studio.
Am I missing something?
Thanks.
We had a css in our cshtml page where there was an existing .btn class that was causing a conflict.
Since I think the last css entry wins, I suspect that was causing the issue.
Once we removed that style, the button was displayed correctly.
Thanks.

Angular-UI Bootstrap toggle buttons in AngularJS

I originally had the default Bootstrap 3.3 toggle buttons in my app. These are the grouping of buttons that mimic the behavior of checkboxes or radio buttons.
I was trying to replace them with the ones here
I paste the code into my html, and at first it looks fine:
<div class="btn-group">
<label class="btn btn-default" ng-model="checkModel.left" btn-checkbox>Left</label>
<label class="btn btn-default" ng-model="checkModel.middle" btn-checkbox>Middle</label>
<label class="btn btn-default" ng-model="checkModel.right" btn-checkbox>Right</label>
</div>
Now I want to hook up the controller. So, I create a file "elements-buttons.controller.js" with the contents of the JS from the angular-ui site:
(function() {
'use strict';
angular.module('pb.ds.elements').controller('ButtonsController',
function($log) {
var _this = this;
_this.singleModel = 1;
_this.radioModel = 'Middle';
_this.checkModel = {
left: false,
middle: true,
right: false
};
});
})();
I put the controller into my router:
.state('elements.buttons', {
url: '/elements/buttons',
templateUrl: 'modules/elements/templates/elements-buttons.html',
controller: 'ButtonsController as buttons'
})
Now, as soon as I link the controller to my index.html, the button group loses all styling:
Which makes no sense to me at all. Inspecting the code in Chrome shows it's if fact lost all its classes for some reason:
<div class="btn-group">
<label class="" ng-model="buttons.checkModel.left" btn-checkbox="">Left</label>
<label class="" ng-model="buttons.checkModel.middle" btn-checkbox="">Middle</label>
<label class="" ng-model="buttons.checkModel.right" btn-checkbox="">Right</label>
</div>
Now, since I have used "controller as" syntax, I did make sure to try adding that to the model ng-model="buttons.checkModel.right" but with or without this same thing. No controller, looks fine. Controller, boom.
EDIT/UPDATE: There are no errors in the console of any kind.
I have created a jsfiddle in order to debug your problem.
Check it here.
And Im finding no problems on it.
Key points you should check:
Be sure you are adding all neccessaries files, such as ui-bootstrap.js
ui-bootstrap.css
jquery, since this are just directives for angular, it will also need jQuery (as the original bootstrap does)
include the dependency on ui-bootstrap on you app definition, pay attention to this line -> angular.module('app', ['ui.bootstrap', 'app.controllers']);
ng-app & ng-controller on the markup. Be sure you are not forgetting this
On the fiddle, Im not using ui-router, but you should check that the controller is indeed loading (you can add a console.log there and check that the controller is loaded).
I thing with this guidelines and the jsfiddle, you should be good to go

Close popover clicking somewhere outside in angular

I have something like this:
http://plnkr.co/edit/CoDdWWQz8jPPM4q1mhC5?p=preview
What I would like to do is closing the popover window after clicking somewhere outside. I know that there were similar questions but I would like to know how to do that in Angular. Problem is, my popover is located inside script tag.
<script type="text/ng-template" id="templateId.html">
This is the content of the template {{name}}
</script>
In bootstrap's documentation they have an example of a 'dismissable' popover.
The trick is to add trigger: 'focus' to your popover options. You then need to change your element to a 'focusable' element (in this example i have used a button)
Here is my fork of your example.
PS. it is worth mentioning that not all elements are natively 'focusable'. You can make sure that an element can become focusable, but adding the attribute tabindex (eg. tabindex="-1").
Looks like I have found an answer to my question. All we need to do is to apply this solution: How to dismiss a Twitter Bootstrap popover by clicking outside? to directive responsible for showing popover. What's more, we need to add data-toggle="popover" to our button.
And, surprisingly, it works very well.
If you want it to work seamlessly on any kind of elements without having to use any external code nor weird things, all you have to do is add this 2 attributes to your markup: tabindex="0" to make the element focusable, and popover-trigger="focus" to make it dismiss the popup once you click off.
Example with <i> tag which is not focusable:
<i popover-html="someModelWhichContainsMarkup" popover-trigger="focus"
tabindex="0" class="fa fa-question-circle"></i>
You can use following code:
<div ng-app="Module">
<div ng-controller="formController">
<button uib-popover-template="dynamicPopover.templateUrl" popover-trigger="focus" popover-placement="left" type="button" class="btn btn-default">Popover With Template</button>
<script type="text/ng-template" id="myPopoverTemplate.html">
<div>
<span>prasad!!</span>
</div>
</script>
</div>
</div>
In Script :
<script type="text/javascript">
var app = angular.module("Module", ['ui.bootstrap']);
app.controller("formController", ['$scope', function ($scope) {
$scope.dynamicPopover = {
templateUrl: 'myPopoverTemplate.html'
};
}]);
</script>
Works for me, add this attribute to the tag which is calling/opening the popup, DON'T MISS THE SINGLE QUOTES AROUND outsideClick
popover-trigger="'outsideClick'"
This opens only one popover and closes upon clicking outside of popover
popover-trigger="outsideClick"

Bootstrap 3 Tooltips with Angular

I'm attempting to use Boostrap 3 tooltips with Angular JS so that the tooltip displays the value of an object in the Angular scope. This works fine when the page loads, but when the value of the object in the scope is updated the tooltip still displays the original value.
HTML:
<div ng-app>
<div ng-controller="TodoCtrl">
<span data-toggle="tooltip" data-placement="bottom" title="{{name}}">Hello {{name}}</span>
<button type="button" ng-click="changeName()">Change</button>
</div>
Javascript:
function TodoCtrl($scope) {
$scope.name = 'Ian';
$scope.changeName = function () {
$scope.name = 'Alan';
}
}
$(document).ready(function () {
$('span').tooltip();
});
There's an example demonstrating my code so far and the issue in this Fiddle
Instead of:
<span data-toggle="tooltip" data-placement="bottom" title="{{name}}">Hello {{name}}</span>
Use:
<span data-toggle="tooltip" data-placement="bottom" data-original-title="{{name}}">Hello {{name}}</span>
Bootstrap Tooltip first checks data-original-title, so as long as you keep this value updated, you'll be fine. Check out this working Fiddle
My guess is that it is missing an apply for changed values, so angular knows nothing about that and does not update. I recommend angular ui bootstrap instead of raw bootstrap components for this reason.
http://angular-ui.github.io/bootstrap/
This way there is no need for jquery which is a bonus in my book.
EDIT:
try this in change handler for a quick and dirty workaround:
$('span').tooltip('hide')
.attr('data-original-title', $scope.name)
.tooltip('fixTitle');
But as i said, check out angular version as this hack has several issues....
For Latest Angular Versions Use: [attr.data-original-title]="dynamicTooltipMsg"
<button
data-toggle="tooltip"
[data-title]="dynamicTooltipMsg"
[attr.data-original-title]="dynamicTooltipMsg">
Testing
</button>

Resources