Stacking a modal over another modal using angularJS on clicking the backdrop - html

I am trying to make a modal appear on top of another modal (like a stack of modals) automatically when the user clicks on the backdrop of a modal or presses the escape button (in this case a dialog box to ask whether you want to progress further).
The problem is that I am not able to figure out how I can call the event's preventDefault() function as I feel that it is the solution to my problem. Currently, what happens is that on clicking the backdrop, the current modal vanishes and the second modal takes it's place instead of appearing above the current modal, putting it in the backdrop.
Here is my code snippet :
The beginning -
(function () {
'use strict';
angular
.module('controller.main', [])
.controller('Main', ['$location', '$state', '$uibModal', 'user', 'auth', 'model', function ($location, $state, $uibModal, user, auth, model) {
var vm = this;
The code in question that is supposed to do the expected task -
vm.openConfirmCancelDB = function (size)
{
$uibModal.open({
animation: vm.animationsEnabled,
templateUrl: '/views/confirmCancelProcessModal.html',
controller: 'Cancel',
controllerAs: 'cancel',
size: size,
backdrop: 'static',
resolve: {}
});
};
vm.openLogin = function (size)
{
var OLP = $uibModal.open(
{
animation: vm.animationsEnabled,
templateUrl: '/views/login.html',
controller: 'Modal',
controllerAs: 'modal',
size: size,
//backdrop: 'static',
resolve: {
inUser: function () {
var user = {};
return user;
}
}
});
OLP.result.then(function()
{
//event.preventDefault();
},
function ()
{
vm.openConfirmCancelDB('sm');
});
};
vm.register = function (size)
{
console.log(vm.registerform);
var RP = $uibModal.open(
{
animation: vm.animationsEnabled,
templateUrl: '/views/register.html',
controller: 'Registration',
controllerAs: 'modal',
//backdrop: 'static',
size: size,
resolve: {
inUser: function () {
var user = {
email: vm.email,
password: vm.password
};
return user;
}
}
});
RP.result.then(function()
{
//event.preventDefault();
},
function ()
{
vm.openConfirmCancelDB('sm');
});
};
openConfirmCancelDB() is the function that helps in opening the dialog box. The problem is how I can call preventDefault() function in order to get the current modal to stay in the backdrop while the dialog box appears on top of this modal. How can I go about accessing the event and its preventDefault function? Also, any other method that can help solve my problem is also fine with me.

Related

Needed factory working in angular js

Actually i was new to angular js i am trying to call my factory operation into controller i dont know where i am going wrong
and my js goes here
app.factory("myFactory",function(){
var something = {};
something.getsum = function() {
$scope.service = " heloo people"
}
return something;
});
app.controller("helloController", function($scope,myFactory) {
$scope.clickme = function() {
$scope.service=myFactory.getsum();
}
});
and my html goes here
<div ng-controller="hello controller">
<button ng-click="clickme"></button>
<h2>{{service}}</h2>
</div>
and my config goes here:
$urlRouterProvider.otherwise("/index/utilise");
$stateProvider
.state('index', {
abstract: true,
url: "/index",
templateUrl: "display.html",
controller:'mainController',
controllerAs: "parentCtrl",
})
.state('index.sample', {
url: "/home",
templateUrl: "content/sample.html",
})
.state('index.utilise', {
url: "/utilise",
templateUrl: "content/utilise.html",
})
})
First issue is that to use the myFactory factory in your controller you would need to inject it into the controller via dependency injection:
app.controller("helloController", function($scope, myFactory) {
$scope.clickme = function() {
$scope.service = myFactory.getsum();
}
});
Second issue you would not use $scope in the myFactory factory method getsum(), you would simply return the value you need:
app.factory("myFactory",function(){
var something = {};
something.getsum = function() {
return " heloo people";
}
return something;
});
Third issue is ng-click was not actually execute controller function clickme as there was parenthesis () as you would with any JavaScript function. It should be ng-click="clickme()" to actually call the function on the controller:
<div ng-controller="helloController">
<button ng-click="clickme()"></button>
<h2>{{service}}</h2>
</div>
Finally, it's unclear what the structure of your application based on the ui-router configuration your provided. With ui-router you wouldn't really have the need to use ng-controller as you can specify what controller any given view should be using. I've created multiple Plunkers, one and two, demonstrating the factory functionality with and without controllers specified for child routes. This should be more than enough to demonstrating calling a controller function in different situations.
Hopefully that helps!

Unable to access $scope model

In my main html, I have a view which loads templates.
<div data-ng-view></div>
It loads a html whenever the link is clicked.
app.config(["$routeProvider", function ($routeProvider) {
'use strict';
$routeProvider
.when("/", {
templateUrl: "events.html"
});
}]);
On this page (template) , I have a directive which loads another html file
app.directive('ngPost', function () {
'use strict';
return {
restrict: 'A',
templateUrl: 'postbox.html'
};
});
I then use this directive on my events.html page by using <div data-ng-Post></div>
In postbox, I have two input fields and a button
<input type="text" id="user" data-ng-model="username" />
<input type="text" id="mess" data-ng-model="message"/>
<button data-ng-click="Add(eventid-1, username, message)">Post</button>
Upon clicking the button, I have some operations, then I try to clear the input fields, but I cannot. Method here :
$scope.Add = function (index, uname, msg) {
var a = {user: uname, message: msg, time: new Date()};
$scope.data[index].messages.push(a);
$scope.message = ''; // clearing here
$scope.username ='';
};
The clearing does not happen, I do not know why. My controller that has this Add method wraps the <div data-ng-view></div>in the main html file so it is the outermost controller and should have access to all $scope models inside. Why does it not work?
Note that the operations before the clearing works with no problems
Your add method is in the parent scope. The parent's scope cannot see it's children, it works the other way around. The message and username properties are defined in the directive's child scope. From a child you can reference parent properties, but not the other way around.
If you add scope: false and transclude: false to your directive, it won't create it's own scope and instead use its parent's scope, so your directive would look something like this:
angular.module('app', []).controller("myController",myController);
function myController($scope){
var ctrl = this;
ctrl.hello ="Hello"
};
angular.module('app').directive("childThing", function() {
return {
template: '<div>{{message}}</div><div>{{username}}</div>',
scope: false,
transclude: false,
controller: function($scope) {
$scope.username="Mike Feltman"
$scope.message="Hi Mike"
}
}
})
and you can access the elements that the directive adds to the scope from the parent like this:
<div ng-controller="myController as ctrl">
{{username}} in the parent.
<div>{{ctrl.hello}}</div>
<child-thing></child-thing>
</div>
Update using your template:
{{username}} in the parent.
{{ctrl.hello}}
Javascript:
function myController($scope){
var ctrl = this;
ctrl.hello ="Hello"
$scope.add = function() {
alert($scope.username)
}
};
angular.module('app').directive("childThing", function() {
return {
template: '<input type="text" id="user" data-ng-model="username" /><input type="text" id="mess" data-ng-model="message"/>',
scope: false,
transclude: false,
}
})

templateUrl changes when refresh or reload page in AngularJS

I am using angular packet template. Here 11 pages loaded and 11 different buttons like the following:
Here is the route code:
state('app.pagelayouts.fixedsidebar1', {
url: "/fixed-sidebar",
templateUrl: "assets/views/page-1.html",
resolve: loadSequence('d3', 'ui.knob', 'countTo', 'dashboardCtrl'),
title: 'Fixed Sidebar',
ncyBreadcrumb: {
label: 'Fixed Sidebar'
},
controller: function ($scope) {
$scope.setLayout();
$scope.app.layout.isSidebarFixed = true;
$scope.$on('$routeChangeSuccess',function(){
$scope.templateUrl = $route.current.templateUrl;
})
}
})
.state('app.pagelayouts.fixedsidebar2', {
url: "/fixed-sidebar",
templateUrl: "assets/views/page-2.html",
resolve: loadSequence('d3', 'ui.knob', 'countTo', 'dashboardCtrl'),
title: 'Fixed Sidebar',
ncyBreadcrumb: {
label: 'Fixed Sidebar'
},
controller: function($scope) {
$scope.setLayout();
$scope.app.layout.isSidebarFixed = true;
}
}).
page-3.html, page-4.html and so on....
Suppose I am in page-1.html, when I refresh it doesn't stay in page-1. Goes to another page. But it should be stay at page-1.html. The templateUrl is changing.
How can i fix it ?
One obvious problem is that you have same url for all the routes.
You should update it with a parameter indicating the template to load, so that when page is refreshed, UI Router knows which state to activate based on the url. For example:
state('app.pagelayouts.fixedsidebar1', {
url: "/fixed-sidebar/1",
templateUrl: "assets/views/page-1.html",
resolve: loadSequence('d3', 'ui.knob', 'countTo', 'dashboardCtrl'),
title: 'Fixed Sidebar',
ncyBreadcrumb: {
label: 'Fixed Sidebar'
},
controller: function($scope) {
$scope.setLayout();
$scope.app.layout.isSidebarFixed = true;
}
});
If all your routes are similar, you can create a single route with a param like:
state('app.pagelayouts.fixedsidebar', {
url: "/fixed-sidebar/:id",
templateUrl: function($stateParams) {
return "assets/views/page-" + $stateParams.id + ".html";
},
resolve: loadSequence('d3', 'ui.knob', 'countTo', 'dashboardCtrl'),
title: 'Fixed Sidebar',
ncyBreadcrumb: {
label: 'Fixed Sidebar'
},
controller: function($scope) {
$scope.setLayout();
$scope.app.layout.isSidebarFixed = true;
}
});

Launching modal on parent from a directive

I have a view with a ui.bootstrap modal that has its own controller.
In the view, i have a directive that generates a number of buttons with a unique ID.
I want to be able to click on one of the buttons generated and call the main view's controller to launch the modal.
Here is the main view module:
/* global angular */
angular.module('my.jobs', [
'ui.router',
'ui.bootstrap'
])
.controller('DashboardJobsCtrl', function DashboardJobsController($rootScope, $scope, $log, $state, $modal) {
var self = this;
angular.extend(this, {
displayReceipt: function(jobId) {
var modalInstance = $modal.open({
animation: true,
templateUrl: 'receiptModal.html',
size: 'lg',
controller: function($scope, $modalInstance, jobsService) {
//CODE HERE FOR ADDING VALUES TO THE MODAL...
$scope.clear = function() {
$modalInstance.close();
};
}
});
}
});
});
Here is the directive:
angular.module('jobView', ['ui.router', 'ui.bootstrap'])
.directive('jobView', function($compile, $http, $templateCache, DOMAINS) {
return {
restrict: 'E',
scope: {
job: '=',
view: '#'
},
template: 'myTemplate.html',
link: function($scope, element, attrs) {
//ASSUME THERE IS CODE HERE FOR GENERATING UNIQUE ID FOR JOBS
//NEXT LINE I WANT TO CALL MODAL FROM THE MAIN VIEW MODULE
$scope.displayReceipt('jobId')
}
};
});
I know this is a simple scope issue, but it's driving me nuts that I can't make the connection.
Here is the perfect example. calling method of parent controller from a directive in AngularJS.
I have update your example below.
<job-View updateParent='displayReceipt()'></job-View>
angular.module('jobView', ['ui.router', 'ui.bootstrap'])
.directive('jobView', function($compile, $http, $templateCache, DOMAINS) {
return {
restrict: 'E',
scope: {
job: '=',
view: '#',
updateParent:'&'
},
template: 'myTemplate.html',
link: function($scope, element, attrs) {
//ASSUME THERE IS CODE HERE FOR GENERATING UNIQUE ID FOR JOBS
//NEXT LINE I WANT TO CALL MODAL FROM THE MAIN VIEW MODULE
$scope.displayReceipt('jobId')
}
};
});

Route Angular to New Controller after Login

I'm kind of stuck on how to route my angular app to a new controller after login. I have a simple app, that uses 'loginservice'... after logging in, it then routes to /home which has a different template from the index.html(login page).
I want to use /home as the route that displays the partial views of my flightforms controllers. What is the best way to configure my routes so that after login, /home is the default and the routes are called into that particular templates view. Seems easy but I keep getting the /login page when i click on a link which is suppose to pass the partial view into the default.html template:
var app= angular.module('myApp', ['ngRoute']);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/login', {
templateUrl: 'partials/login.html',
controller: 'loginCtrl'
});
$routeProvider.when('/home', {
templateUrl: 'partials/default.html',
controller: 'defaultCtrl'
});
}]);
flightforms.config(['$routeProvider', function($routeProvider){
//sub pages
$routeProvider.when('/home', {
templateUrl: 'partials/default.html',
controller: 'defaultCtrl'
});
$routeProvider.when('/status', {
templateUrl: 'partials/subpages/home.html',
controller: 'statusCtrl'
});
$routeProvider.when('/observer-ao', {
templateUrl: 'partials/subpages/aobsrv.html',
controller: 'obsvaoCtrl'
});
$routeProvider.when('/dispatch', {
templateUrl: 'partials/subpages/disp.html',
controller: 'dispatchCtrl'
});
$routeProvider.when('/fieldmgr', {
templateUrl: 'partials/subpages/fieldopmgr.html',
controller: 'fieldmgrCtrl'
});
$routeProvider.when('/obs-backoffice', {
templateUrl: 'partials/subpages/obsbkoff.html',
controller: 'obsbkoffCtrl'
});
$routeProvider.when('/add-user', {
templateUrl: 'partials/subpages/users.html',
controller: 'userCtrl'
});
$routeProvider.otherwise({
redirectTo: '/status'
});
}]);
app.run(function($rootScope, $location, loginService) {
var routespermission=['/home']; //route that require login
$rootScope.$on('$routeChangeStart', function(){
if( routespermission.indexOf($location.path()) !=-1)
{
var connected=loginService.islogged();
connected.then(function(msg) {
if(!msg.data) $location.path('/login');
});
}
});
});
and my controllers are simple. Here's a sample of what they look like:
var flightformsControllers = angular.module('flightformsController', []);
flightforms.controller('fieldmgrCtrl', ['$scope','$http','loginService',
function($scope,loginService) {
$scope.txt='You are logged in';
$scope.logout=function(){
loginService.logout();
}
}]);
Any ideas on how to get my partials to display in the /home default.html template would be appreciated.
1) Move all the routing into the main app.config, and remove the duplicate route for /home.
2) change this line
var flightformsControllers = angular.module('flightformsController', []);
to
var flightforms = angular.module('flightforms', []);
3) change the app definition line to inject the flightforms module:
var app= angular.module('myApp', ['ngRoute', 'flightforms']);
That should get ya close.
For one of your comments, its a good idea to have an interecptor which catches any 401 un-authenticated errors from the server. This way, if a user's session expires before a route change, they will still have to login again to start a new session. Something like this in app.config should do it.
$provide.factory('logoutOn401', ['$q', '$injector', function ($q, $injector) {
return {
'responseError': function(response) {
if (response.status === 401) {
$location.path('/login')
return $q.reject();
} else {
return $q.reject(response);
}
}
};
}]);
$httpProvider.interceptors.push('logoutOn401');