Watch window clicks if terms and conditions not accepted - javascript

Right on the first user login to my app I display a terms and conditions pop up. It can be easily closed in Dev Tools and the app can be freely used. How can I possible watch a sessionStorage variable requireTerms? requireTerms changes from true to false depending on whether the terms and conditions have been accepted.
I want to detect a click if the modal has been closed in html editor and re-open pop-up again.
Is there an AngularJS way of setting up a config to do that?
I've got this function in one of my services
var service = this;
service.showTerms = function() {
$uibModal.open({
templateUrl: 'app/terms/terms.html',
controller: 'tsAndCs as vm',
size: 'md',
backdrop: false,
keyboard: false
}).result.then(function(response) {
}, function() {
});
};
so I can basically call appState.showTerms(); however I am trying to figure out how to detect that window has been forced to be closed and call the function.
#edit
I thought of having a variable requireTermsOpened (which will be set to false only when user actually clicks on 'Accept') when the modal is displayed and writing something like
var requireTerms = sessionStorage.getItem('requireTerms');
var requireTermsOpened = sessionStorage.getItem('requireTermsOpened');
if(requireTerms && requireTermsOpened) {
appState.showTerms();
}

$uibModal.open({
templateUrl: 'app/terms/terms.html',
controller: 'tsAndCs as vm',
size: 'md',
backdrop: false,
keyboard: false
}).result.then(function(response) {
})
.catch(function() {
// Here you can add your code, its the event that gets called when the modal is dimissed
});
Please test it, I am quite sure it will help you, sorry if its bad formatted, I believe you got the idea, right?

You can try something like the below code. Also check this plunker for your given example scenario.
Controller:
$scope.modelFn = function() {
var modalInstance = $uibModal.open({
templateUrl: 'confirmationWindow.html',
windowClass: 'modal',
controller: function ($scope, $uibModalInstance) {
$scope.confirm = function(userAgreement) {
$uibModalInstance.close(userAgreement);
};
$scope.cancel = function() {
$uibModalInstance.dismiss('cancel');
};
},
size: 'md',
backdrop: false,
keyboard: false
});
modalInstance.result.then(function(selectedItem) {
if (selectedItem) {
alert('Selected check box and clicked OK!');
}else{
alert('Clicked OK Button without Selecting Checkbox!');
}
}, function() {
alert('Clicked Cancel button or Considered cancel on click of outside the Model popup window!');
});
};
Template:
<div ng-controller="MainCtrl">
<script type="text/ng-template" id="confirmationWindow.html">
<div class="modal-header">
<h3 class="modal-title">Terms & Conditions</h3>
</div>
<div class="modal-body">
<p>...........</p>
<p>
<input type="checkbox" ng-model="userAgreement"/>
Are you agreed with all terms and conditions?</p>
</div>
<div class="modal-footer">
<button class="btn btn-warning" ng-click="confirm(userAgreement)">Confirm</button>
<button class="btn btn-default" ng-click="cancel()">Cancel</button>
</div>
</script>
<button class="btn" ng-click="modelFn()">Open Modal</button>
</div>

Related

call $state.go in modal angularjs

i have add in the controller of my modal an $state.go on my submit button function , at the first time it is invocked but when i try to open again the modal and submit it another time the $state.go didn't invocked.
ModalCtrler.js
$scope.addElet= function(){
------
$state.go('state1',{OBJ: OBJ});
}
the modal is defined in my run app.js:
myApp.run(function($rootScope, $modal,$state) {
$rootScope.$on('$stateChangeStart', function(event, toState,toParams) {
if (toState.name == 'addPopup') {
$modal.open({
templateUrl : 'add.html',
controller : 'ModalCtrler',
backdrop: 'static',
keyboard: false,
});
event.preventDefault();
}
}
}
the modal is called when i click in ui-serf :
<a ui-sref="addPopup({OBJ: OBJ})">
<button type="button" class="btn btn-add pull-right">ADD</button>
</a>
Am i missing somthing in my code? anu idea?
Issue solved by relaoding the state:
$state.go('state1', {OBJ: OBJ}, { "reload": 'state1''});
Thanks to link stackoverflow
I think your problem is:
You do nothing with modal before you call $state.go('state1',{OBJ: OBJ});
Try to hide it and only after call $state.go
var modalInstance = $modal.open({
templateUrl : 'add.html',
controller : 'ModalCtrler',
backdrop: 'static',
keyboard: false,
});
and something like:
$scope.addElet= function(){
$modalInstance.close(); // or $modalInstance.dismiss();
$state.go('state1',{OBJ: OBJ});
}

Implement common methods in two angular js controllers to open common html page

I am working on AngularJS application, in which I need to show common popup on creating an item. The popup will be same for all application, but the implementation of method of save and close will be different in each of calling controller.
Below is the code of common html page :
saveItem.html
<div class="modal-header">
<i class="fa fa-times-circle" data-dismiss="modal" aria-hidden="true" ng-click="vm.closeItem()" style="color: #061530;font-size: 25px;float: right;" role="button" tabindex="0"></i>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" class="close" data-dismiss="modal" aria-hidden="true"
ng-click="vm.createItem()">Create another item
</button></div>
I used ngDialog to open common page. Below code is used to open the html page :
FirstController and SecondController :
ngDialog.open({
template: 'app/confirmation/saveItem.html',
scope: $scope,
showClose: false
});
What I want ?
I want different implementation of createItem() and closeItem() methods in FirstController and SecondController.
But when I implementing both methods in-
FirstController :
function closeItem() {
ngDialog.close();
}
function createdItem() {
//implemtation on FirstController
}
In SecondController
function closeItem() {
ngDialog.close();
}
function createdItem() {
//implemtation on SecondController
}
But it working in FirstController only. How can I write different implementation in both controllers?
Also is there any way to preserve previous state with ngDialog?
Add the methods to the scope that you provide for the dialog:
$scope.closeItem = function() { ngDialog.close(); }
$scope.createdItem = function() { // do whatever }
ngDialog.open({
template: 'app/confirmation/saveItem.html',
scope: $scope,
showClose: false
});
In the documentation for ngDialog, you can specify the controller you want to use for the dialog:
Controller that will be used for the dialog window if necessary. The
controller can be specified either by referring it by name or directly
inline.
ngDialog.open({
template: 'externalTemplate.html',
controller: 'SomeController' });
One way is to load different controllers for each situation:
function openFirstDialog() {
ngDialog.open({
template: 'app/confirmation/saveItem.html',
scope: $scope,
showClose: false,
controller: 'FirstController'
});
}
function openSecondDialog() {
ngDialog.open({
template: 'app/confirmation/saveItem.html',
scope: $scope,
showClose: false,
controller: 'SecondController'
});
}
Another solution would be to use a $scope variable to decide the action:
function openFirstDialog() {
$scope.firstController = true;
ngDialog.open({
template: 'app/confirmation/saveItem.html',
scope: $scope,
showClose: false
});
}
function openSecondDialog() {
$scope.firstController = false;
ngDialog.open({
template: 'app/confirmation/saveItem.html',
scope: $scope,
showClose: false
});
}
Then check the $scope variables in your dialog controller:
function closeItem() {
ngDialog.close();
}
function createdItem() {
if($scope.firstController) {
//implemtation on FirstController, go to page 1
}
else {
//implemtation on SecondController, go to page 2
}
}

What is the best way to call a method in a controller from a service in angular?

I've done some research on this question both in SO and on Google as well. But none of the answers serve my purpose.
I have a modal in an HTML view, which I use to show popup notifications in my app.
I want to show some buttons ('OK', 'Cancel', 'Login', etc.,) in a div on modal which I pass dynamically as a JS object. Name of the button being the key and the callback function being the value.
Examples:
{
"Login": function(){....}
}
{
"OK": function(){...},
"Cancel": function(){...}
}
Now I pass this kind of objects to a method showPopup(message, buttonMap) in the controller of the popup modal I have in view.
message being the display message on the popup and buttonMap being the object in examples.
Controller:
angular.module('core').controller('PopupController', ['$rootScope', 'LogService', 'MessageHandlerService',
function ($rootScope, LogService, MessageHandlerService) {
var ctrl = this;
ctrl.buttonMap = {};
ctrl.btnWidth = 100;
$rootScope.$on('popup', showPopup);
function showPopup (event, message, buttonMap) {
$('#genericModalDialog .popup-content p').html(message);
ctrl.buttonMap = buttonMap;
var numberOfButtons = Object.keys(buttonMap).length;
ctrl.btnWidth = (100 - numberOfButtons*2)/numberOfButtons;
$("#genericModalDialog").modal('show');
}
ctrl.callbackFor = function callbackFor(key) {
ctrl.buttonMap[key].call(null);
};
}
]);
Service:
angular.module('core').service('PopupService', ['$rootScope', 'LogService', 'CacheService', 'MessageHandlerService',
function ($rootScope, LogService) {
this.isPopupShown = function (){
return $("#genericModalDialog").hasClass('in');
}
this.showPopup = function (message, btnMap){
$rootScope.$broadcast('popup', message, btnMap);
}
this.closePopup = function (){
$("#genericModalDialog").modal('hide');
}
}
]);
View:
<div ng-controller="PopupController as popupCtrl" class="modal fade" id="genericModalDialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="vertical-alignment-helper">
<div class="modal-dialog vertical-align-center" style="width:94%;">
<div class="modal-content">
<div class="modal-body">
<br/><br/>
<div class="popup-content">
<p align="center"></p><br/>
<div class="popup-action">
<button type="button" class="btn" style="width:{{popupCtrl.btnWidth}}%; margin:1%" ng-repeat="(buttonName, callBack) in popupCtrl.buttonMap" ng-click="popupCtrl.callbackFor(buttonName)">{{buttonName}}</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Since I don't want to instantiate PopupController in every other controller/service, I've written a service called PopupService which has a method that can called and will $broadcast an event called "popup" on $rootscope and I am handling this event in PopupController. Everything is triggered and working properly in this case. The only problem I face is the delay in rendering the popup on the UI, I see the message as soon as the popup is displayed but the rendering of buttons is very slow (approx 3 secs) this is because of loading of some other web page in the background.
When I searched about the issue on the internet I also found this total setup can be changed to a directive and the rendering of dynamic content (in this case the popup and buttons on it.) could be placed in a link function of the directive.
Another approach I saw was directly handling the DOM manipulation in the service which of course is not a good way.
Did I miss any other approach or a solution to this issue?
All I want to know is what would the best way be, to handling this situation which is programmatically and design wise good.
If I am not clear please let me know. I'll try explaining the problem again.
Directive would be a much better choice that the DOM manipulation. Additionally you should consider changing the usage of jQuery dialog into a https://angular-ui.github.io/bootstrap/#/modal.
Here is an example how it can be done:
1) Create the directive
app.directive('myModal', function() {
return {
restrict: 'E',
scope: {
items: "=",
message: "="
},
replace: true,
templateUrl: "directiveTemplate.html",
controller: function($scope, $uibModal, $log) {
$scope.open = function(size) {
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
items: function() {
return $scope.items;
},
message: function() {
return $scope.message;
}
}
});
modalInstance.result.then(function(selectedItem) {
$scope.button = selectedItem.name;
$scope[selectedItem.callback](selectedItem.name);
});
};
}
}
});
2) Create modalInstance directive
app.controller('ModalInstanceCtrl', function($scope, $uibModalInstance, items, message) {
$scope.items = items;
$scope.message = message;
$scope.close = function(item) {
$uibModalInstance.close(item);
};
});
3) create directive template directiveTemplate.html
<div>
{{buttonClicked}}
<br> {{button}}
<button type="button" class="btn btn-default" ng-click="open('sm')">{{message}}</button>
</div>
4) create popup template 'myModalContent.html'
{{message}}
<button ng-repeat="item in items" type="button" class="btn btn-default" ng-click="close(item)">{{item.name}}</button>
5) define you controller where you will have list of buttons and message to be displayed in the popup (for demo purpose here are two different list of items and two messages)
app.controller('ModalDemoCtrl', function($scope) {
$scope.message = "modal 1";
$scope.items = [{
name: 'item1',
callback: "test1"
}, {
name: 'item2',
callback: "test2"
}, {
name: 'item3',
callback: "test3"
}];
$scope.message2 = "modal 12222";
$scope.items2 = [{
name: 'item1222',
callback: "test1"
}, {
name: 'item2222',
callback: "test2"
}, {
name: 'item3222',
callback: "test3"
}];
$scope.test1 = function(message) {
$scope.buttonClicked = "clicked test1";
}
$scope.test2 = function(message) {
$scope.buttonClicked = "clicked test2";
}
$scope.test3 = function(message) {
$scope.buttonClicked = "clicked test3";
}
});
and in order to you the directive you need:
<div ng-controller="ModalDemoCtrl">
<my-modal items="items" message="message"></my-modal>
</br>
<my-modal items="items2" message="message2"></my-modal>
</div>
If you have directive accessed from different angular application instances, than just inject directive application into the needed one (make sure the directive and modal instance to have a their own defined module ex: var app = angular.module('myPopupDynamicModule', ['ngAnimate', 'ui.bootstrap']); and this is the one to be used for injection into other modules following this example: var app2 = angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap', 'myPopupDynamicModule']);)

Button on Accordion Header redirecting angularjs

I'm getting a peculiar problem. I have a nested accordion and I need a button like Edit on every accordion. When the button is clicked, I need to call a different function. What I'm doing is on click of the edit button I'm trying to use $event.stopPropagation() which will stop accordion functionality. But this isn't happening when I pass $event.stopPropagation(). It is redirecting to some other URL.
I'm posting some of my huge code. If any further info is required please comment.
HTML
<accordion-heading>
{{course.className}}
<button type="button"
ng-show="course.classId!=$scope.null"
class="pull-right btn btn-default btn-sm"
ng-click="editCourse(course,$event)">
Edit Course
</button>
</accordion-heading>
JS
$scope.editCourse = function(course, ev) {
ev.stopPropagation();
course.courseEditPermission = true;
}
app.js
.config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider) {
$httpProvider.defaults.headers.common['Access-Control-Allow-Headers'] = '*';
delete $httpProvider.defaults.headers.common['X-Requested-With'];
$routeProvider
.when('/login', {
controller: 'LoginController',
templateUrl: 'modules/authentication/views/login.html',
hideMenus: true
})
.when('/home', {
controller: 'HomeController',
templateUrl: 'modules/home/views/home.html'
})
.otherwise({
redirectTo: '/xyz'
});
}])
I don't know why it is redirecting but in my JS I provided routes, so I think event.stopPropagation is getting some anonymous URL, so it is redirecting to "/xyz" as I have mentioned.
You need to add event.preventDefault() handler like this:
$scope.editCourse = function(course, ev) {
ev.preventDefault();
ev.stopPropagation();
course.courseEditPermission = true;
}

Using different info messages in one Ctrl with $modal service (AngularJS)

I've a question to my problem. I'm using on each page an info button who's opening when you click on it. For the modal window I'm using an own defined service who's giving the values to the controller of the modal window. For each page exists an different info message and I want to use only one View for all info messages. But only the message for the corresponding page should be displayed. How can I define this?
Here is a code of Home view Info btn:
<button type="button" class="btn pull-right" ng-click="msgBtn()">
click on info
</button>
The same code is in Person view.
How can I tell the modalCtrl that the msgBtn() was clicked on Person view and give me the message of person info?
Here is my solution example:
//First the HomeCtrl:
$scope.info = function (message) {
modalService.infoDia(message);
};
//HomeView:
<button type="button" class="btn" ng-click="info('Home')">
Click Info
</button>
//PersonCtrl:
$scope.info = function (message) {
modalService.infoDia(message);
};
//PersonView:
<button type="button" class="btn" ng-click="info('Person')">
Click Info
</button>
//infoDia Service:
...
return {
infoDia: function (message) {
return $modal.open({
templateUrl: 'info.html',
controller: function ($scope, params) {
$scope.message = params.message;
},
resolve: {
params: function () {
return {
message: message;
}
}
}
});
}
}
//ModalView:
...
<div class="modal-body">
<p ng-if="message == 'Home'">
This is the home information dialog.
</p>
<p ng-if="message == 'Person'">
This is the person information dialog.
</p>
</div>
...
You can have a property named something like infoMsg in both homeCtrl and personCtrl and access it in you modal view using {{infoMsg}}. But this will force you to add infoMsg property to each of your controllers scope whereever you are going to use the modal. Better you can have your home and person controllers pass the message string to the modal controller through the service. This will reduce coupling and will give your code more flexibility. This is all I can tell without seeing your code.
If you just want to show a message then this is pretty easily achieved. To put #ankur's answer in a form of code, it could be something like below.
Have a Info service, taking message as a parameter.
app.factory('Info', function($modal) {
return {
show: function(message) {
$modal.open({
templateUrl: 'info-modal-template.html',
controller: function($scope, params) {
$scope.message = params.message;
},
resolve: {
params: function() {
return {
message: message
};
}
}
});
}
};
});
Then inject and call it from within your HomeCtrl.
app.controller('HomeCtrl', function(Info) {
var vm = this;
vm.info = function(message) {
Info.show(message);
};
});
Where HTML template is simply.
<div ng-controller="HomeCtrl as vm">
<button type="button"
class="btn btn-default"
ng-click="vm.info('Home message')">
Home button
</button>
</div>
Answer to your new question posted as an answer.
// Home
app.controller('HomeCtrl', function($scope, modalService) {
$scope.info = function() {
modalService.infoDia('Home');
};
});
<button type="button" class="btn" ng-click="info()">Click Info</button>
// Person
app.controller('PersonCtrl', function($scope, modalService) {
$scope.info = function() {
modalService.infoDia('Person');
};
});
<button type="button" class="btn" ng-click="info()">Click Info</button>
// Service
app.factory('modalService', function($modal) {
return {
infoDia: function(message) {
return $modal.open({
templateUrl: 'info.html',
controller: function($scope, params) {
$scope.message = params.message;
},
resolve: {
params: function() {
return {
message: message
};
}
}
});
}
};
});
<div class="modal-body">
<p>{{ message }}</p>
</div>

Categories

Resources