So I am using the AngularJS Bootstrap modal (http://angular-ui.github.io/bootstrap/). Which is working fine but I was wondering if I could create a basic template that can take in a title and the content.
Then it would populate my template with these info. The template would have a close button, cancel button, overlay, etc. Is there an easy way to do this AngularJS?
This is taken from the example and it's about what I have. My content is in the templateUrl. It would be nice to pass in the modal template so I don't have to keep recreating the title and close buttons for every modal I create.
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
});
Found a way to do it with directives. It opens up a modal with a custom directive that has a template. Then whatever you have in your modal will be inserted into your custom template. This is nice because it holds more than just a message. It can be filled with forms, alert, or anything you want.
This was my directive:
app.directive('modalDialog', function() {
return {
restrict: 'E',
replace: true,
transclude: true,
link: function(scope) {
scope.cancel = function() {
scope.$dismiss('cancel');
};
},
template:
"<div>" +
"<div class='modal-header'>" +
"<h3 ng-bind='dialogTitle'></h3>" +
"<div ng-click='cancel()'>X</div>" +
"</div>" +
"<div class='modal-body' ng-transclude></div>" +
"</div>"
};
});
Modal ('yourTemplate.html'):
<modal-dialog>
<div> Your body/message </div>
</modal-dialog>
Javascript:
app.controller('YourController', ['$scope', '$modal', function($scope, $modal) {
$scope.openModal = function () {
$modal.open({
templateUrl: 'yourTemplate.html',
controller: ModalController
});
};
}]);
var ModalController = function ($scope, $modalInstance) {
$scope.dialogTitle = 'Your title';
};
Checkout John Papa's Hot Towel Angular BootStrap "template". You can pick it up from there:
https://github.com/johnpapa/HotTowel-Angular/blob/master/NuGet/HotTowel-NG/app/common/bootstrap/bootstrap.dialog.js
Related
Suppose i have a directive CARD
.directive('card', [function() {
return {
restrict: 'E', // Element directive,
templateUrl: 'scripts/directives/card.html'
};
and a controller say CARDCONTROLLER
.controller('cardController',function($scope){
$scope.directivename = 'card';
});
and a HTML file say CARD.HTML
<div>
<{{directivename}}></{{directivename}}>
</div>
But the above doesnot work.
Does any one have any idea about how to accomplish this?
EDIT.
I dont want to generate the directive dynamically.Its just that i want to bind it through the controller without/with changing anything in directive
you must add the controller to your directive.
.directive('card', function() {
return {
restrict: 'E', // Element directive,
templateUrl: 'scripts/directives/card.html',
controller: 'cardController'
}
})
this should do the trick.
call your directive like,
<div>
<data-card>
// add code
</data-card>
</div>
You can define controller in your directive also
.directive('myDirective', function() {
return {
restrict: 'E',
templateUrl: 'scripts/directives/card.html',
controller: function($scope) {
//write your controller code here
},
controllerAs: 'myController'
};
});
see the below snippet , you will get idea how you can do this.
var app = angular.module('myapp',[]);
app.directive('card',function() {
return {
restrict: 'E', // Element directive,
template: '<h5>I am directive template</h5>'
};
});
app.controller('cardController',function($scope,$compile,$element){
$scope.directivename = 'card';
var template = $compile("<"+$scope.directivename+"/>")($scope);
$element.append(template);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp" ng-controller="cardController">
</div>
I want to close all the modal pop up boxes when a user clicks on a close button of the final confirmation modal popup.
But the modal windows that are open do belong to different controllers. Here is the snippet :
function getQuickCasePopup($scope, $uibModal, $rootScope) {
var templateUrl = BasePath + 'App/Transaction/Views/common/QuickCaseSearch.tpl.html';
var controller = 'QuickCaseSearchCtrl';
OpenModal($scope, $uibModal, null, templateUrl, controller, null, null, '', $rootScope);
}
function getAddCasePopup($scope, $uibModal, $rootScope) {
var templateUrl = BasePath + 'App/Transaction/Views/common/CreateCase.tpl.html';
var controller = 'AddCaseCtrl';
OpenModal($scope, $uibModal, null, templateUrl, controller, null, null, '', $rootScope);
}
function getAdvanceCasePopup($scope, $uibModal, $rootScope) {
var templateUrl = BasePath + 'App/Transaction/Views/common/AdvanceCaseSearch.tpl.html';
var controller = 'AdvanceCaseCtrl';
OpenModal($scope, $uibModal, null, templateUrl, controller,null, null, 'lg', $rootScope);
}
function OpenModal($scope, $uibModal, $stateParams, templ, ctrl, grid, row, size, $rootScope) {
var CssClass = '';
if (size === 'lg') {
CssClass = 'app-modal-window';
}
var ModalInstance = ModalInstance || $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: templ,
controller: ctrl, // Logic in instantiated controller
windowClass: CssClass
});
And the confirmation pop - up code looks like :
$("#iConfirmationModal").modal();
$("#iConfirmationModal").on('hidden.bs.modal', function () {
//$(".app-modal-window").dialog("close"); //Did not work
$state.go('transaction.search', {});
});
So I want to close all the modal pop-ups and then redirect . Can I achieve the same ?
The modal is a singleton object so you can call $scope.$close() and it all close all modal instance
You may have multiple options,
create a service which will manage all modal status.
Use $emit\$broadcast for notifications.
use third part libraries like amplifyjs and use there pub\sub operations.
I am using angular ui for bootstrap for its modals:
http://angular-ui.github.io/bootstrap/#/modal
I am opening a modal with a controller and templateUrl with:
var modalInstance = $uibModal.open({
animation: true,
templateUrl: $scope.templateUrl,
controller: $scope.controller,
size: 'lg',
resolve: {
formModel: item
}
});
where formModel is the model I will use in the modal.
Here is the controller for the modal:
app.controller('commentCtrl', ['$scope', '$modalInstance', 'formModel', function ($scope, $modalInstance, formModel) {
$scope.formModel = {};
var loadFormModel = function () {
if (formModel !== undefined) {
$scope.formModel = formModel;
}
};
loadFormModel();
}]);
This modal has child directives and needs to pass properties of formModel to them
template:
<div>
<child model="formModel.Comment"></child>
</div>
but child is created before the modal's controller has loaded formModel. Inside the child I want to use model as:
app.directive('child', function () {
return {
restrict: 'E',
template: '<textarea ng-model="model"></textarea>',
link: linkFn,
controller: controllerFn,
scope: {
model: '='
}
};
});
Edit:
I've found that I can do:
<div>
<child model="formModel" property="Comment"></child>
</div>
...
app.directive('child', function () {
return {
restrict: 'E',
template: '<textarea ng-model="model[property]"></textarea>',
link: linkFn,
controller: controllerFn,
scope: {
model: '=',
property: '#'
}
};
});
Is there a better way to do this without the extra attribute?
Edit 2:
I have found where the bug is:
http://plnkr.co/edit/kUWYDvjR8YArdqtQRHhi?p=preview
See fItem.html for some reason having any ng-if causes the binding to stop working. I have put a contrived ng-if='1===1' in for demonstration
This happens because ng-if directive creates new inherited scope, so the bug is just a common scope prototypal inheritance pitfall.
The most concise way to get around it is to use controllerAs syntax in conjunction with bindToController, the avoidance of undesirable scope inheritance side effects is the most common use case for them. So it will be
app.directive('fItem', function () {
return {
restrict: 'E',
replace: true,
templateUrl: 'fItem.html',
controller: ['$scope', function ($scope) {
}],
controllerAs: 'vm',
bindToController: true,
scope: {
model: '='
}
};
});
and
<div class="input-group">
<textarea ng-if='1===1' ng-model="vm.model" class="form-control"></textarea>
</div>
Not sure what you are trying to do. If you need just to wait until variable is resolved, you need just use promise: (Here is simple one using $timeout, if you use i.e. $http - you ofc dont need $q and $timeout)
resolve: {
something: function () {
return $q(function(resolve, reject) {
setTimeout(function() {
resolve('Hello, world!');
}, 3000);
});
Then modal will be opened only after promise is resolved.
http://plnkr.co/edit/DW4MzIO4ej0JorWRgWIK?p=preview
Also keep in mind that you can wrap you object, so if in scope you have $scope.object = {smth : 'somevalue'} :
resolve: {
object: function () {
return $scope.object;
});
And in modal controller:
$scope.object = object;
Now object in initial controller scope and object in modal scope point to same javascript object, so any time you change one - another changes. You are free to use object.smth in modal template as usual property. And as soon as it will change you will see changes.
How to trigger event before closing bootstrap modal on angularjs directive ,
angular.module('app').controller("myModal", function myModal($scope, $modalInstance) {
$scope.modalInstance = $modalInstance;
});
template
< div> My modal < /div>
and directive
angular.module('app').directive('mymodal',function( $rootScope ){
return{
restrict : 'E',
replace : true,
templateUrl :'mymodal.html',
scope :{
modalInstance :'='
},
link: function (scope, elem, attr) {
scope.modalInstance.result.then(function() {
console.log('close');
}, function() {
console.log('dimiss');
});
}
});
I want to have confirm message before closing modal after click on backdrop.
call modal dialog from here
$scope.openModal = function() {
$scope.modalInstance = $modal.open({
animation: true,
template: '<mymodal modal-instance="modalInstance"></mymodal>',
controller: 'myModal',
backdrop: true,
keyboard: true,
});
}
Check out this answer, it works for me.
var instance = $modal.open(...);
instance.result.then(function(){
//Get triggers when modal is closed
}, function(){
//gets triggers when modal is dismissed.
});
I just started working with AngularJs and am having some problems in the management of multiple directives.
The two directives have to perform the following tasks:
1) Create an animation when the page is loaded with animated
2) Create a background parallax on some div
Through some resources found on the net I could get aa two directives that individually work well, but if I try to make them work together with the outer one prevents the internal directives to do their jobs.
This is the code(html):
<div ng-view ng-controller="MyCtrl" anim-class>
<section parallax-background parallax-ratio="0.5" style="background: url(img/parallax1.jpg);">
//some code
</section>
</div>
This is the code(js):
var app = angular.module("myApp", [
"ngRoute",
"ngAnimate",
]);
app.config(function($routeProvider, $locationProvider) {
$routeProvider.
when("/first-page", {
templateUrl: "first-page.html",
animate: "slideTop"
}).
when("/second-page", {
templateUrl: "second-page.html",
animate: "slideTop"
}).
otherwise({
redirectTo: "/first-page"
});
});
app.controller("MyCtrl", function($scope) {
});
// PAGE ANIMATE DIRECTIVE
app.directive('animClass',function($route){
return {
link: function(scope, elm, attrs){
var enterClass = $route.current.animate;
elm.addClass(enterClass)
scope.$on('$destroy',function(){
elm.removeClass(enterClass)
elm.addClass($route.current.animate)
})
}
}
});
// PARALLAX DIRECTIVE
app.directive('parallaxBackground', ['$window', function($window) {
return {
restrict: 'A',
transclude: true,
template: '<div ng-transclude></div>',
scope: {
parallaxRatio: '#',
},
link: function($scope, elem, attrs) {
var setPosition = function () {
var calcValY = (elem.prop('offsetTop') - $window.pageYOffset) * ($scope.parallaxRatio ? $scope.parallaxRatio : 1.1 );
// horizontal positioning
elem.css('background-position', "50% " + calcValY + "px");
};
// set our initial position - fixes webkit background render bug
angular.element($window).bind('load', function(e) {
setPosition();
$scope.$apply();
});
angular.element($window).bind("scroll", setPosition);
angular.element($window).bind("touchmove", setPosition);
} // link function
};
}]);
How can I make sure that the two ( or more ) directives are working properly .
Thank You.