Toggling a Twitter Bootstrap (3.x) Modal using AngularJS - angularjs

I've been trying to get a Bootstrap Model to be hidden on load, and then show it after clicking a button, but have been unsuccessful so far. I am pretty new to AngularJS so bear with me if I'm not doing this correctly. Here's what I've got so far:
Modal Angular Directive (modal.js):
angular.module('my.modal', ['modal.html'])
.directive('myModal', function () {
return {
restrict: 'E',
transclude: true,
replace: false,
templateUrl: 'modal.html',
link: function(scope, element, attrs) {
element.modal('hide')
scope.toggleModal = function() {
if (attrs.showModal === true) {
element.modal('hide')
attrs.showModal = false
} else {
element.modal('show')
attrs.showModal = true
}
}
}
};
});
Modal Template (modal.html):
<div id="{{id}}" showModal="false" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<div class="content" ng-transclude></div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="showModal = false">Cancel</button>
</div>
</div>
</div>
</div>
And finally, the button to toggle the modal (index.html):
...
<my-modal>
<p>Some content</p>
</my-modal>
<button class="btn btn-default" type="button" ng-click="toggleModal()">Toggle me!</button>
...
All this does is show the modal on page load (between my header and all the other content, so it's not floating above anything) and the toggle button does not work.

I've managed to get it working by using the Bootstrap 3 Modal properties and dynamically changing styling and classes of the modal directive based on it's show or hide state, though there are no animations:
Modal Angular Directive (modal.js):
angular.module('my.modal', ['modal.html'])
.directive('myModal', [function () {
return {
restrict: 'E',
transclude: true,
replace: false,
templateUrl: 'modal.html',
controller: 'ModalCtrl',
link: function(scope, element, attrs) {
if (attrs.title === undefined) {
scope.title = 'Modal Title Placeholder';
} else {
scope.title = attrs.title;
}
scope.$watch('showModal', function (value) {
if (value) {
scope.displayStyle = 'block';
scope.modalFadeIn = 'in';
} else {
scope.displayStyle = 'none';
scope.modalFadeIn = '';
}
});
}
};
}).controller('ModalCtrl', ['$scope', function ($scope) {
$scope.toggleModal = function() {
$scope.showModal = !$scope.showModal;
};
$scope.$open = function() {
$scope.showModal = true;
};
$scope.$close = function() {
$scope.showModal = false;
};
});
Modal Template (modal.html):
<div role="dialog" tabindex="-1" class="modal fade" ng-init="showModal = false" ng-show="showModal" ng-style="{display: displayStyle}" ng-class="modalFadeIn">
<div class="modal-backdrop fade in" style="height: 100%"> </div>
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">{{title}}</h3>
</div>
<div class="modal-body">
<div class="content" ng-transclude></div>
</div>
</div>
</div>
</div>
The call to open the modal can be done using the open or toggleModal function. A custom button needs to be placed in the modal to close the modal.

Related

how to open and close the Bootstrap modal pop inside directive link function?

I need to open the bootstrap modal pop up inside directive under some function , how could do with in directive.
Instead of these need to use angualr to open dialog.
var show = function () {
$('#myModal1').modal({ backdrop: 'static', keyboard: false });
$element.css('display', 'block');
};
Like as need to hide with angular
var hide = function () {
$('#myModal1').modal(toggle);
$element.css('display', 'none');
};
myApp.directive('loadingStatusMessage', function () {
return {
link: function ($scope, $element, attrs) {
var show = function () {
$('#myModal1').modal({ backdrop: 'static', keyboard: false });
$element.css('display', 'block');
};
var hide = function () {
$('#myModal1').modal(toggle);
$element.css('display', 'none');
};
$scope.$on('loadingStatusActive', show);
$scope.$on('loadingStatusInactive', hide);
hide();
}
};
});
html:
<div class="modal fade" id="myModal1" tabindex="-1" role="dialog"
aria-labelledby="myModalLabel" loading-status-message
style="position:fixed; display:none;">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<button type="button" class="close"
data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<div class="alert alert-success" role="alert">
<strong>Technical Error Occurred.Please contact the System Administrator for the further support!!</strong>
</div>
</div>
</div>
</div>
</div>

Show/Hide Angular Directive On Button Click

I have a HTML page with three buttons. I also have two Angular directives. What I'm trying to accomplish is when button a is clicked, I want directive 1 to show and directive 2 to hide. When button 2 is clicked, I want directive 1 to hide and directive 2 to show. Here is are my directives:
.directive('topPosts', function () {
return {
restrict: 'E',
templateUrl: 'topPosts.html',
controller: 'PostsController'
}
});
.directive('otherPosts', function () {
return {
restrict: 'E',
templateUrl: 'otherPosts.html',
controller: 'PostsController'
}
});
here is my controller:
.controller('PostsController', ['$scope', 'PostsFactory', function($scope, PostsFactory) {
$scope.posts = [];
$scope.showTopPosts = true;
$scope.showOtherPosts = false;
$scope.topPosts = function() {
$scope.showTopPosts = true;
$scope.showOtherPosts = false;
};
$scope.otherPosts = function() {
$scope.showTopPosts = false;
$scope.showOtherPosts = true;
};
$scope.areTopPosts = function(posts) {
return posts.privacy === 'public' && posts.comments > 10 && posts.views > 9000 && posts.title.length < 40;
};
$scope.areOtherPosts = function(posts) {
return posts.comments <= 10 && posts.views <= 9000 && posts.title.length >= 40;
};
var init = function() {
PostsFactory.getPosts.success(function(data) {
$scope.posts = data;
});
};
init();
}]);
here is my partial that holds both directives:
<div class="container">
<top-posts ng-show='showTopPosts'></top-posts>
<other-posts ng-show='showOtherPosts'></other-posts>
</div>
and here is my index.html:
<body ng-controller='PostsController'>
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<a class="navbar-brand" href="/main"></a>
</div> <!-- END NAVBAR-HEADER -->
</div> <!-- END CONTAINER-FLUID -->
</nav>
<div class="container">
<div class="btn-group" role="group">
<button type="button" class="btn btn-default" ng-click="topPosts()">Top Posts</button>
<button type="button" class="btn btn-default" ng-click="otherPosts()">Other Posts</button>
<!-- <button type="button" class="btn btn-default" ng-click="dailyTopPost()">Daily Top Post</button> -->
</div>
</div>
<div ng-view class='slide-animation'></div>
What's currently happening is the functions are getting called, but the directives are not showing/hiding on the button clicks.
I put work code in a codepen and it seems to be working fine http://codepen.io/arthur_souviron/pen/pEMMaJ/
I think your issue come from the way you store $scope.showTopPosts
and $scope.showOtherPosts. Try to store them inside an object instead of setting them directly under $scope
Eg :
$scope.data = {
showTopPosts: true,
showTopPosts: false
}
and in your template : <top-posts ng-show="data.showTopPosts"></top-posts>
Simply add a div before the directive:
<div class="container">
<div ng-show='showTopPosts'><top-posts ></top-posts></div>
<div ng-show='showOtherPosts'><other-posts ></other-posts></div>
</div>

Adding html to UI bootsrap popover inside directive

I am an angular beginner and I wish to add an html button inside a popover that I am creating within a directive. Specifically, my directive allows the user to highlight text on the page and a popover will then appear around the selected text. It works for plain text content in the popover but not html. This is the directive as it is now
app.directive('replybox', function ($timeout, $window, $compile, $sce) {
var linkFn = function (scope, element, attrs) {
var exampleText= element.find('p');
var btn = element.find('button');
var windowSelection="";
exampleText.bind("mouseup", function () {
scope.sel = window.getSelection().toString();
windowSelection=window.getSelection().getRangeAt(0);
if(scope.sel.length>0) {
scope.showModal = true;
scope.$apply();
}
});
btn.bind("click", function () {
range = windowSelection;
var replaceText = range.toString();
range.deleteContents();
var div = document.createElement("div");
scope.pophtml = $sce.trustAsHtml("<p>hello world</p> <button>x</button>");
div.innerHTML = '<poper>' + replaceText + '</poper>';
var frag = document.createDocumentFragment(), child;
while ((child = div.firstChild)) {
frag.appendChild(child);
}
$compile(frag)(scope);
range.insertNode(frag);
scope.selection="None";
});
};
return {
link: linkFn,
restrict: 'A',
scope: {
entities: '=',
selection:'='
},
template: `<ng-transclude></ng-transclude>
<div class="modal fade in" style="display: block;" role="dialog" ng-show="showModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
{{sel}}
</div>
<div class="radio">
<div ng-repeat="x in entities">
<div class="radio">
<label>
<input type="radio" name="choice" ng-model="$parent.selection" ng-value = "x">
{{x}}
</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="showModal=false">
Ok
</button>
</div>
</div>
</div>
</div>`,
transclude: true
};
});
The part that is not working is this part
scope.pophtml = $sce.trustAsHtml("<p>hello world</p> <button>x</button>");
div.innerHTML = '<poper>' + replaceText + '</poper>';
I have a feeling there is something wrong with the above two lines.

Reusable modal window directive. How can I pass directive-attributes-values to controller

I want to make a reusable modal-window-directive (i found a pair modal-window examples, but that's not what i want, or they do not work properly).
It should look something like this:
(1) title-, body-text and function-name (for the function, which is binded to the action-button in the template) are defined directly within directive
<my-modal
modal-title="Modal Window Title"
modal-body="This is my Modal Window Body"
click-main-html-action-button="myControllerActionFunction()">
</my-modal>
(2) The HTML-template for modal window must pick up the corresponding values
<div class="panel-default">
<div class="panel-heading">
{{title}}
</div>
<div class="panel-body">
<div class="row">
<div class="form-group col-sm-12">**{{body}}**</div>
</div>
<div class="col-sm-12 text-center">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-ng-click="templatestartaction(); $event.stopPropagation()">Start action</button>
</div>
</div>
</div>
(3) Button-function for modal window must be defined In the controller
app.controller('controller', function($scope) {
scope.title = "";
scope.body = "";
$scope.myControllerActionFunction = function () {
console.log('myControllerActionFunction', title);
};
})
The question is: how can I read the attrs values from (1)
(modal-title = "Modal Window Title", etc.) and the function name
(click-main-html-button action = "myControllerActionFunction ()") and
pass it to the model and function definition in the controller
(3), so that it is displayed in the html-template (2)?
I can read the attributes from (1), but I do not know how i pass it in controller.
(4)
app.directive('myModal', function () {
return {
transclude: true,
restrict: 'E',
//template: '<div ng-transclude></div>',
templateUrl: "directives/modal/view/modalWindowTemplate.html"
scope: {
templatestartaction: '&clickMainHtmlActionButton'
},
link: function (scope, element, attrs) {
scope.title = attrs.modalTitle;
scope.body = attrs.modalBody;
}
};
});
You need to define title and body in the controller like
$scope.modalProps = {
title: 'My modal title',
body: 'My modal body'
};
Use this in the html
<my-modal
modal-title="modalProps.title"
modal-body="modalProps.body"
click-main-html-action-button="myControllerActionFunction()">
</my-modal>
And define it for the directive
app.directive('myModal', function () {
return {
transclude: true,
restrict: 'E',
//template: '<div ng-transclude></div>',
templateUrl: "directives/modal/view/modalWindowTemplate.html"
scope: {
templatestartaction: '&clickMainHtmlActionButton'
title: '=modalTitle',
body: '=modalBody'
},
...

AngularJS reusable modal bootstrap directive

I'm new with AngularJS. I'm trying to implement a reusable modal Bootstrap.
This is the index.html:
<div ng-controller="mymodalcontroller">
<modal lolo="modal1" modal-body='body' modal-footer='footer' modal-header='header' data-ng-click="myRightButton()"></modal>
Launch Demo Modal
</div>
This is the module, controller and directive:
var myModal = angular.module('myModal', []);
myModal.controller('mymodalcontroller', function ($scope) {
$scope.header = 'Put here your header';
$scope.body = 'Put here your body';
$scope.footer = 'Put here your footer';
$scope.myRightButton = function (bool) {
alert('!!! first function call!');
};
});
myModal.directive('modal', function () {
return {
restrict: 'EA',
scope: {
title: '=modalTitle',
header: '=modalHeader',
body: '=modalBody',
footer: '=modalFooter',
callbackbuttonleft: '&ngClickLeftButton',
callbackbuttonright: '&ngClick',
handler: '=lolo'
},
templateUrl: 'partialmodal.html',
transclude: true,
controller: function ($scope) {
$scope.handler = 'pop';
},
};
});
And this is the html template:
<div id="{{handler}}" class="modal fade">
<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">{{header}}</h4>
</div>
<div class="modal-body">
<p class="text-warning">{{body}}</p>
</div>
<div class="modal-footer">
<p class="text-left">{{footer}}</p>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-ng-click="callbackbuttonright(), $event.stopPropagation()">Save changes</button>
</div>
</div>
</div>
</div>
I want the 'Launch Alert' button (in the modal) executes the alert and it does it well. The problem is that it is launched when clicking the 'Cancel' button in the Modal and when the window closes. Any ideas?
Here is the working code:CodeThank you.
I would suggest you not bind to ng-click. It does some other magic stuff that can screw with things. There is also a syntax error in your partial.
I've fixed those issues in my fork here:
http://plnkr.co/edit/2jK2GFcKSiKgMQMynD1R?p=preview
To summarize:
script.js:
Change your callbackbuttonright binding from ngClick to ngClickRightButton
myModal.directive('modal', function () {
return {
restrict: 'EA',
scope: {
title: '=modalTitle',
header: '=modalHeader',
body: '=modalBody',
footer: '=modalFooter',
callbackbuttonleft: '&ngClickLeftButton',
callbackbuttonright: '&ngClickRightButton',
handler: '=lolo'
},
templateUrl: 'partialmodal.html',
transclude: true,
controller: function ($scope) {
$scope.handler = 'pop';
},
};
});
index.html:
Change data-ng-click to data-ng-click-right-button
<modal lolo="modal1" modal-body="body" modal-footer="footer" modal-header="header" data-ng-click-right-button="myRightButton()"></modal>
Another minor issue:
partialmodal.html:
Change , to ;
<button type="button" class="btn btn-primary" data-ng-click="callbackbuttonright(); $event.stopPropagation()">Launch Alert</button>
If anyone is still interested, here is a example I recently worked on with bootstrap modal and angularjs directive.
HTML:
<modal visible="showModal1" on-sown="modalOneShown()" on-hide="modalOneHide()">
<modal-header title="Modal Titel 1"></modal-header>
<modal-body>
<h3>This is modal body</h3>
</modal-body>
<modal-footer>
<button class="btn btn-primary" ng-click="hide(1)">Save</button>
</modal-footer>
</modal>
JavaScript:
var myModalApp = angular.module('myModalApp',[]);
myModalApp.directive('modal', function(){
return {
template: '<div class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true"><div class="modal-dialog modal-sm"><div class="modal-content" ng-transclude><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button><h4 class="modal-title" id="myModalLabel">Modal title</h4></div></div></div></div>',
restrict: 'E',
transclude: true,
replace:true,
scope:{visible:'=', onSown:'&', onHide:'&'},
link:function postLink(scope, element, attrs){
$(element).modal({
show: false,
keyboard: attrs.keyboard,
backdrop: attrs.backdrop
});
scope.$watch(function(){return scope.visible;}, function(value){
if(value == true){
$(element).modal('show');
}else{
$(element).modal('hide');
}
});
$(element).on('shown.bs.modal', function(){
scope.$apply(function(){
scope.$parent[attrs.visible] = true;
});
});
$(element).on('shown.bs.modal', function(){
scope.$apply(function(){
scope.onSown({});
});
});
$(element).on('hidden.bs.modal', function(){
scope.$apply(function(){
scope.$parent[attrs.visible] = false;
});
});
$(element).on('hidden.bs.modal', function(){
scope.$apply(function(){
scope.onHide({});
});
});
}
};
}
);
myModalApp.directive('modalHeader', function(){
return {
template:'<div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button><h4 class="modal-title">{{title}}</h4></div>',
replace:true,
restrict: 'E',
scope: {title:'#'}
};
});
myModalApp.directive('modalBody', function(){
return {
template:'<div class="modal-body" ng-transclude></div>',
replace:true,
restrict: 'E',
transclude: true
};
});
myModalApp.directive('modalFooter', function(){
return {
template:'<div class="modal-footer" ng-transclude></div>',
replace:true,
restrict: 'E',
transclude: true
};
});
function ModalController($scope){
$scope.title = "Angularjs Bootstrap Modal Directive Example";
$scope.showModal1 = false;
$scope.showModal2 = false;
$scope.hide = function(m){
if(m === 1){
$scope.showModal1 = false;
}else{
$scope.showModal2 = false;
}
}
$scope.modalOneShown = function(){
console.log('model one shown');
}
$scope.modalOneHide = function(){
console.log('model one hidden');
}
}
Compared to other options, below given the minimalist approach using Angular Bootstrap and an angular factory. See a sample snippet below.
Reusable modal view - ConfirmationBox.html
<div class="modal-header">
<h3 class="modal-title">{{title}}</h3>
</div>
<div class="modal-body">
{{message}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary btn-warn" data-ng-click="ok(); $event.stopPropagation()">OK</button>
<button type="button" class="btn btn-default" data-ng-click="cancel(); $event.stopPropagation()">Cancel</button>
</div>
Reusable module and shared factory, for handling the reusable modal dialog
angular.module('sharedmodule',['ui.bootstrap', 'ui.bootstrap.tpls'])
.factory("sharedService",["$q", "$modal", function ($q, $modal)
{
var _showConfirmDialog = function (title, message)
{
var defer = $q.defer();
var modalInstance = $modal.open({
animation: true,
size: "sm",
templateUrl: 'ConfirmationBox.html',
controller: function ($scope, $modalInstance)
{
$scope.title = title;
$scope.message = message;
$scope.ok = function ()
{
modalInstance.close();
defer.resolve();
};
$scope.cancel = function ()
{
$modalInstance.dismiss();
defer.reject();
};
}
});
return defer.promise;
}
return {
showConfirmDialog: _showConfirmDialog
};
}]);
Portion of your View, using the shared modal dialog
<a data-ng-click="showConfirm()">Go Back to previous page</a>
Controller of your view, opening your shared reusable modal dialog and handling notifications (Ok and Cancel)
var myModule = angular.module("mymodule", ['sharedmodule', 'ui.bootstrap', 'ui.bootstrap.tpls']);
myModule.controller('myController', ["$scope", "sharedService", "$window",
function ($scope, sharedService, $window)
{
$scope.showConfirm = function ()
{
sharedService.showConfirmDialog(
'Confirm!',
'Any unsaved edit will be discarded. Are you sure to navigate back?')
.then(function ()
{
$window.location = '#/';
},
function ()
{
});
};
}]);

Resources