How to dynamically change template of popover in angular-strap - angularjs

I am using angularstrap to create a popover using a template. I am using the attribute ng-attr-data-template to provide link to the template. I am changing the mentioned attribute value using a function which is called on click of a button.
But the change is not being reflected to the popover. Please suggest the possible solution for this problem.
Here is the link to Plunkr
Code is as follows
index.html
<!DOCTYPE html>
<html ng-app="klk">
<head>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.min.js"></script>
<script src="//mgcrea.github.io/angular-strap/dist/angular-strap.js" data-semver="v2.0.4"></script>
<script src="//mgcrea.github.io/angular-strap/dist/angular-strap.tpl.js" data-semver="v2.0.4"></script>
<link rel="stylesheet" href="style.css" />
<script src="app.js"></script>
</head>
<body ng-controller="mainCtrl">
<hr/>
<button type="button" class="btn btn-info" placement="right" data-animation="am-flip-x"
ng-attr-data-template="{{link}}" data-auto-close="1" bs-popover >
{{link}}
</button>
<hr/>
<button class="btn btn-info" ng-click = "changeContent()">Change link</button>
</body>
</html>
app.js
var app = angular.module('klk', ['mgcrea.ngStrap']);
app.controller('mainCtrl', function($scope, $popover){
$scope.trackName = 'Click on the button and give us a name';
$scope.popov = function(el){
$popover(angular.element(el),
{
show: true,
placement: 'right',
template: 'link1.html',
animation: 'am-flip-x'
});
};
$scope.link = "link1.html";
$scope.change = true;
$scope.changeContent = function(){
$scope.change = !$scope.change;
if ($scope.change)
$scope.link = "link1.html";
else
$scope.link = "link2.html";
}
});
link1.html
<div class="popover">
<div class="arrow"></div>
<h3 class="popover-title"><strong>Heading 1</strong></h3>
<div class="popover-content">
pop content 1
</div>
</div>
link2.html
<div class="popover" >
<div class="arrow"></div>
<h3 class="popover-title"><strong>Heading 2</strong></h3>
<div class="popover-content">
pop content 2
</div>
</div>

If you are interested in changing the content of the template dynamically, it can be accomplished by using the following way.
Here is an example of modified Index.html. Notice that there is a data-content and a data-title that bound to model properties.
<!DOCTYPE html>
<html ng-app="klk">
<head>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.min.js"></script>
<script src="//mgcrea.github.io/angular-strap/dist/angular-strap.js" data-semver="v2.0.4"></script>
<script src="//mgcrea.github.io/angular-strap/dist/angular-strap.tpl.js" data-semver="v2.0.4"></script>
<link rel="stylesheet" href="style.css" />
<script src="app.js"></script>
</head>
<body ng-controller="mainCtrl">
<hr/>
<button type="button" class="btn btn-info" placement="right" data-animation="am-flip-x" data-title = "{{popover.title}}" data-content="{{popover.content}}" data-template="link3.html" data-auto-close="1" bs-popover >Click Me</button>
<hr/>
<button class="btn btn-info" ng-click = "changeContent()">Change link</button>
</body>
</html>
Here is the module and the controller, In this controller we have a model called popover with the properties title and content, this will be dynamic. For example, if you called the function changeContent it will toggle the content and make the content in popover change.
// Code goes here
var app = angular.module('klk', ['mgcrea.ngStrap']);
app.controller('mainCtrl', function($scope, $popover){
$scope.trackName = 'Click on the button and give us a name';
$scope.toggleContent=true;
$scope.popover = {
"title": "Original Content",
"content": "loading...",
};
$scope.changeContent=function(){
if($scope.toggleContent){
$scope.popover = {
"title": "Changed",
"content": "<p>hello the content has changed!</p>",
};
}else{
// show original content
$scope.popover = {
"title": "Original Content",
"content": "Hello Content 1...",
};
}
}
});
Here is a template that will have the content and the title that will be dynamic as it is bound to model properties title and content. Look for ng-bind-html
<div class="popover" tabindex="-1" ng-show="content">
<div class="arrow"></div>
<div class="popover-title" ng-bind-html="title"></div>
<div class="popover-content">
<form name="popoverForm">
<div class="form-actions">
<!--<button class="btn-sm pull-right close-popover" ng-click="$hide()">x</button>-->
</div>
<p ng-bind-html="content" style="min-width:300px;"></p>
</form>
</div>
</div>
A working example of this can be found here
http://plnkr.co/edit/FpqwcdcPNVI3zIzK6Ut1?p=preview

Related

angular-ui bootstrap popover behavior is not triggering properly

I'm using version 0.14.1 and my code is:
<div class="clearfix mbot20">
<h3 class="pull-left">Skill Category SORT: {{filterSelected}}</h3>
<span class="pull-right pathways-modal-popover-container">
<span class="sm-round-btn" popover-placement="bottom" uib-popover-template="data.sortUrl" popover-trigger="'none'" tabindex="0" popover-is-open="filterSelected === 'sort'">
<a class="clr-white" ng-click="filterSelected = 'sort'"><i class="glyphicon glyphicon-sort"></i></a>
</span>
<span class="sm-round-btn" popover-placement="bottom" uib-popover-template="data.filterUrl" popover-trigger="'none'" tabindex="0" popover-is-open="filterSelected === 'filter'">
<a class="clr-white" ng-click="filterSelected = 'filter'"><i class="glyphicon glyphicon-filter"></i></a>
</span>
</span>
</div>
So the idea is that you can click on either span and it should load the appropriate popover, but only one popover can be opened at a time. That's being controlled by filterSelected.
Now the behavior is strange. If I click on one of them, nothing happens. When I click again, the popover loads fine. When I click the other one, the popover disappears. Then I have to click the other one again.
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-animate.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.14.1.js"></script>
<script src="example.js"></script>
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<link href="style.css" rel="stylesheet">
</head>
<body ng-controller="PopoverDemoCtrl" ng-click="filterSelected='none'" style="height: 100%;">
<div>
<button popover-placement="bottom" uib-popover="On the Top!" type="button" popover-is-open="filterSelected === 'sort'" popover- trigger="'none'" ng-click="filterSelected == 'sort' ? filterSelected = 'none' : filterSelected = 'sort';$event.stopPropagation();"
class="btn btn-default">Top</button>
<button popover-placement="bottom" uib-popover="On the Bottom!" type="button" class="btn btn-default" popover-trigger="'none'" popover-is-open="filterSelected === 'filter'" ng-click="filterSelected == 'filter' ? filterSelected = 'none' : filterSelected = 'filter';$event.stopPropagation();">Bottom</button>
</div>
</body>
</html>
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('PopoverDemoCtrl', function ($scope) {
$scope.dynamicPopover = {
content: 'Hello, World!',
templateUrl: 'myPopoverTemplate.html',
title: 'Title'
};
});
/* Styles go here */
html, body {
height: 100%;
}
Think it should work, check
`http://plnkr.co/edit/dnuP47muv2OSxYXjqtc2?p=preview`
Make sure when you click you really click on tag a not the space between a and span

angular uib-popover-template input two-way binding

I am working on uib-popover recently, I found a problem that I am confused with.
I want to popover a template, in this template I have an input, at first the input have initial value.
I want to update the content real-time based on the input. When I just bind a variable, it does not work, while if I bind an object, it works. I can't figure this problem out.
index.html
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-animate.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-sanitize.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.4.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="PopoverDemoCtrl">
<hr/>
<hr/>
<hr/>
<button uib-popover-template="'myPopoverTemplate.html'" popover-placement="bottom-left" type="button" class="btn btn-default">Popover With Template</button>
{{dynamicPopover.title}}
<script type="text/ng-template" id="myPopoverTemplate.html">
<div class="form-group">
<input type="text" ng-model="dynamicPopover.title" class="form-control">
</div>
</script>
<button uib-popover-template="'inputContent.html'" popover-placement="bottom-left" type="button" class="btn btn-default">Popover With Template</button>
{{inputContent}}
<script type="text/ng-template" id="inputContent.html">
<div class="form-group">
<input type="text" ng-model="inputContent" class="form-control">
</div>
</script>
</div>
</body>
</html>
example.js
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ngSanitize', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('PopoverDemoCtrl', function($scope, $sce) {
$scope.dynamicPopover = {
title: 'Title'
};
$scope.inputContent = "hello";
});
Here is the plunker example https://plnkr.co/edit/IPXb5tddEPQPPAUrjdYx?p=preview, you could have a try.
You made an interesting point in your second plunk. I didn't catch this the first time but I think it may be because you are doing your popover input in a script tag. I would suggest using a custom directive if you could versus just doing it in an inline script. That way it is kept up to date with angular's digest cycle.
Example Directive:
customPopoverApp.directive('customPopover',['$compile','$templateCache',function($compile,$templateCache){
return {
restrict:'A',
transclude:true,
template:"<span>Click on me to show the popover</span>",
link:function(scope,element,attr){
var contentHtml = $templateCache.get("customPopover.html");
contentHtml=$compile(contentHtml)(scope);
$(element).popover({
trigger:'click',
html:true,
content:contentHtml,
placement:attr.popoverPlace
});
}
};
}]);
And to use it:
<button custom-popover="" popover-place="bottom">click on me to show the popover</button>
{{message}}
<script type="text/ng-template" id="customPopover.html">
<div class="form-group">
<input type="text" ng-model="message" class="form-control">
</div>
</script>
Here is a working plunk. I hope this is what you're looking for

Reply Textarea for particular post(using textarea), opening for all the comments

Hi I am trying to implement facebook kind of post and reply comments using angularjs. Below is my code
<doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="HomeCtrl">
<div class="container" style="margin-top:1%;">
<div class="row">
<textarea style="width:500px" ng-model="txt" placeholder="Add a comment..."></textarea></br></br>
<button type="button" class="btn btn-default" ng-click="postData(txt)" ng-model="btn">post</button>
</div>
</div>
<div class="container" style="margin-top:1%;">
<div class="row">
<div ng-show="comment" ng-repeat="data in datas track by $index">
{{data}}
<div>
Like
comment
share
</div>
<div ng-show="innerComment">
<textarea style="width:500px; height:30px;" ng-model="txt1"></textarea></br></br>
<button type="button" class="btn btn-default" ng-click="postReplied(txt1)" ng-model="btn" ng-show="postRepBtn">Reply</button>
<div ng-show="innercmt" ng-repeat="data1 in InnerData">
{{data1}}
</div>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script>
var app=angular.module('myApp', []);
app.controller('HomeCtrl', ['$scope', function($scope) {
$scope.comment=false;
$scope.innerComment=false;
$scope.datas=[];
$scope.InnerData=[];
$scope.innercmt=false;
$scope.postRepBtn=true;
$scope.postData=function(txt)
{
$scope.comment=true;
$scope.datas.push(txt);
$scope.txt='';
}
$scope.showInnerComment=function($index)
{
console.log($index)
$scope.innerComment=true;
}
$scope.postReplied=function(txt1)
{
$scope.InnerData.push(txt1);
$scope.innercmt=true;
//$scope.postRepBtn=false;
$scope.txt1='';
}
}]);
</script>
</body>
</html>
Now the problem I am facing is that (assuming I have posted 3 comments), I am not able to open reply(textarea) for that particular comment(link), Instead its opening the textarea(reply) for all the comments when clicking on any comment link.
I am not able to solve this issue.Or is there any other way to solve it?? Any help is appreciated.
Thanks
I am attching the images also
Make $scope.innerComment an array of Booleans.
$scope.innerComment = [];
Now modify it in your view as ng-show="innerComment[$index]"
This way you can set the value true for particular comment.
$scope.showInnerComment=function($index)
{
console.log($index)
$scope.innerComment[$index]=true;
}
Note: Whenever you add comment , push false in innerComment.

Loading image at the time of onclick event using angularjs is not working

I want to add data at the time of onclick event. Need to load image at the time of onclick event, after a small time interval add data. But my image is continuously loading. Any body give any suggestion.
My code is:
<!DOCTYPE html>
<head>
<title>Learning AngularJS</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js" type="text/javascript"></script>
<script language="javascript">
function ContactController($scope) {
$scope.contacts = [];
$scope.items = [ ];
$scope.add = function() {
setTimeout(function() {
$scope.$apply(function() {
$scope.items[0].lateLoader = ' xxxx ';
});
}, 1000);
$scope.count=$scope.count+1;
$scope.contacts.push($scope.newcontact);
$scope.newcontact = "";
}
}
</script>
</head>
<body >
<div ng-app="" ng-controller="ContactController">
<p>{{items.lateLoader}}
<i ng-hide="items.lateLoader"><img src="Filling broken ring.gif"></i>
</p>
{{ contacts.length }}
Content:<input type="text" ng-model="newcontact" />
<button ng-click="add()">Add</button>
<ul style="list-style-type: none;">
<li ng-repeat="contact in contacts"> <input name="" type="checkbox" value="">{{ contact }}</li>
</ul>
</div>
</body>
</html>
In your example I found a lot of mistakes. The HTML tag is not defined at the top, wrong use of angularJs and Angular module is not created properly etc.
I fixed all the mistakes. I hope it can help you.
Plunkr link: http://plnkr.co/edit/no8WOHdEc9wc3dHzzITv?p=preview
<!DOCTYPE html>
<html ng-app="app">
<head>
<title>Learning AngularJS</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script >
angular.module("app",[]).controller('ContactController',['$scope',
function($scope) {
$scope.contacts = [];
$scope.items = [];
$scope.add = function() {
setTimeout(function() {
$scope.$apply(function() {
$scope.items.lateLoader = 'xxxx ';
});
}, 1000);
//$scope.count=$scope.count+1;
$scope.contacts.push($scope.newcontact);
$scope.newcontact = "";
}
}
]);
</script>
</head>
<body >
<div ng-controller="ContactController">
<p>{{items.lateLoader}}
<i ng-hide="items.lateLoader">
<img src="https://encrypted-tbn1.gstatic.com
/images?q=tbn:ANd9GcQTaHe0F0J39SXbiRF43pz2wtyfD6kypCMrLxhWPkq9EACNgwO0iaMbJFM">
</i>
</p>
{{contacts.length}}
Content:<input type="text" ng-model="newcontact" />
<button ng-click="add()">Add</button>
<ul style="list-style-type: none;">
<li ng-repeat="contact in contacts">
<input name="" type="checkbox" value="">{{ contact }}
</li>
</ul>
</div>
</body>
</html>
And for more detail of angularJs please visit these links:(https://angularjs.org/)
(http://www.w3schools.com/angular/default.asp)

Change class of an element with a radio button in a modal (Angular UI-Bootstrap: Retrieving values from a modal dialog window)

I use a modal dialog and radio buttons to change the class of an element. The classes are theme-1, theme-2 and theme-3. I tried it with the directive ng-class, but this was not possible, because I need to provide an equal ng-model for the radio buttons.
With {{theme}} in the modal dialog, I get the value of the buttons. Outside the modal dialog, it do not work.
I can change the class even after closing the dialogue. But how can I do this in my ModalInstanceCtrl?
Do you have any tip?
HTML
<h1 ng-model="theme">The new class: {{theme}}</h1>
Angular UI Modal Dialog
<form name="myForm" ng-controller="NewInvoiceCtrl">
<div class="btn-group btn-theme">
<label class="btn btn-default btn-theme-label" ng-model="theme" btn-radio='"theme-1"'>Light</label>
<label class="btn btn-default btn-theme-label" ng-model="theme" btn-radio='"theme-2"'>Dark</label>
<label class="btn btn-default btn-theme-label" ng-model="theme" btn-radio='"theme-3"'>Grey</label>
{{theme}}
</div>
</form>
JS
var ModalInstanceCtrl = function($scope, $modalInstance, items) {
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
// Change Design
$scope.selectDesign = function() {
$modalInstance.dismiss('cancel');
};
};
With {{theme}} in the modal dialog, I get the value of the buttons.
Outside the modal dialog, it do not work.
In the main window, you can get what was selected in the dialog window like this:
index.html:
<!DOCTYPE html>
<html>
<head>
<!-- For html5 (default is UTF-8) -->
<meta charset="UTF-8">
<!-- For Bootstrap -->
<meta name="viewport" content="width=device-width, initial-scale=1"> <!-- For Bootstrap -->
<title>Test</title>
<!-- Bootstrap3 -->
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<!-- app.css -->
<link href="app.css" rel="stylesheet">
</head>
<body ng-app="myApp">
<div ng-controller="MainWindowCtrl">
<button class="btn btn-default" ng-click="open()">Open modal dialog window</button>
<div ng-show="main.theme">Selection from the modal dialog was: {{main.theme}}</div>
</div>
<!-- Angular 1.3.2 -->
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
<!-- Angular UI-Bootstrap -->
<script src="angular-ui-bootstrap-0.12.js"></script>
<!-- app.js -->
<script src="app.js"></script>
</body>
</html>
app.js:
var app = angular.module("myApp", ['ui.bootstrap']);
app.controller('MainWindowCtrl', ['$scope', '$modal', function($scope, $modal) {
$scope.open = function() {
var dialogWindow = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'DialogWindowCtrl',
});
dialogWindow.result.then(function(selectedTheme) {
$scope.main = {
theme: selectedTheme
};
});
};
}]);
app.controller('DialogWindowCtrl', ['$scope', '$modalInstance', function($scope, $modalInstance) {
var dialogWindow = $modalInstance;
//Set default value...
//ng-clicks in the dialog window change this value:
$scope.dialog = {
theme: 'theme1'
};
$scope.ok = function () {
dialogWindow.close($scope.dialog.theme); //***PASS DATA TO MAIN WINDOW****
};
$scope.cancel = function () {
dialogWindow.dismiss('cancel');
};
}]);
Retrieve two values from a modal dialog:
(Also set a default active button, and activate the clicked button.)
index.html:
<!DOCTYPE html>
<html>
<head>
<!-- For html5 (default is UTF-8) -->
<meta charset="UTF-8">
<!-- For Bootstrap -->
<meta name="viewport" content="width=device-width, initial-scale=1"> <!-- For Bootstrap -->
<title>Test</title>
<!--Bootstrap3 -->
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<!-- app.css -->
<link href="app.css" rel="stylesheet">
</head>
<body ng-app="myApp">
<div ng-controller="MainWindowCtrl">
<button class="btn btn-default" ng-click="open()">Open modal dialog window</button>
<div ng-show="main_data.theme">Theme from the modal dialog was: {{main_data.theme}}</div>
<div ng-show="main_data.border">Border from the modal dialog was: {{main_data.border}}</div>
</div>
<!-- Angular 1.3.2 -->
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
<!-- Angular UI-Bootstrap 0.12 -->
<script src="angular-ui-bootstrap-0.12.js"></script>
<!-- app.js -->
<script src="app.js"></script>
</body>
</html>
app.js:
var app = angular.module("myApp", ['ui.bootstrap']);
app.controller('MainWindowCtrl', ['$scope', '$modal', function($scope, $modal) {
$scope.open = function() {
$modal.open({
templateUrl: 'myModalContent.html',
controller: 'DialogWindowCtrl',
})
.result.then(function(dialog_data) {
$scope.main_data = dialog_data;
//equivalent to: $scope.main_data = {theme: 'selected theme', border: 'selected border'}
});
};
}]);
app.controller('DialogWindowCtrl', ['$scope', '$modalInstance', function($scope, $modalInstance) {
var dialogWindow = $modalInstance;
$scope.dialog_data = {
theme: 'theme1',
border: 'solid'
};
$scope.setTheme = function(theme) {
$scope.dialog_data.theme = theme;
}
$scope.ifThemeIs = function(theme) {
return $scope.dialog_data.theme === theme;
}
$scope.setBorder = function(border) {
$scope.dialog_data.border = border;
}
$scope.ifBorderIs = function(border) {
return $scope.dialog_data.border === border;
}
$scope.ok = function () {
dialogWindow.close($scope.dialog_data); //***PASS DATA TO MAIN WINDOW***
};
$scope.cancel = function () {
dialogWindow.dismiss('cancel');
};
}]);
myModalContent.html:
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<h4>Theme:</h4>
<div class="btn-group btn-theme">
<button class="btn btn-default btn-theme-label"
ng-click="setTheme('theme1')"
ng-class="{active: ifThemeIs('theme1')}">Light</button>
<button class="btn btn-default btn-theme-label"
ng-click="setTheme('theme2')"
ng-class="{active: ifThemeIs('theme2')}">Dark</button>
<button class="btn btn-default btn-theme-label"
ng-click="setTheme('theme3')"
ng-class="{active: ifThemeIs('theme3')}">Grey</button>
</div>
<div>Current theme choice: {{dialog_data.theme}}</div>
<h4>Border:</h4>
<div class="btn-group btn-theme">
<button class="btn btn-default btn-theme-label"
ng-click="setBorder('solid')"
ng-class="{active: ifBorderIs('solid')}">Solid</button>
<button class="btn btn-default btn-theme-label"
ng-click="setBorder('dashed')"
ng-class="{active: ifBorderIs('dashed')}">Dashed</button>
</div>
<div>Current border choice: {{dialog_data.border}}</div>
</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>

Resources