Steps for displaying a confirmation popup and redirecting to a new route using AngularJS

Is it possible to display a confirmation popup with "Yes" and "No" buttons every time there is a route change in my AngularJS App?

I attempted the following approach. This event gets triggered before the route change, but despite selecting 'NO', it does not prevent the user from navigating to a different route.

 $scope.$on('$locationChangeStart', function (event) {
      if (vm.counterObject.myList.length > 0) {
        var answer = confirm("Are you sure?")
        if (answer) {
          event.preventDefault();
        }
      }
    });

Can anyone point out where I might be making a mistake?

Answer โ„–1

Success! I finally managed to make this work in my testing AngularJS application. The method I used was inspired by Ben Nadel's blog. I've included the entire controller code below:

Update: The key difference in this new approach lies in the order of operations within the function. The problem with the previous method was that Angular didn't have enough time to update before allowing the $location.path() to proceed, leading it to trigger an event listener still. By using stopWatchingLocation() to cancel that listener and giving Angular time to digest, we resolved this issue.

Essentially, the critical change was made in the proceedWithLocationChange function:

Execute this first: stopWatchingLocation();

then

$timeout(() => {$location.path( targetPath ).search( targetSearch ).hash( targetHash )},10);
}

This approach worked perfectly in my environment

'use strict';
angular.module('myApp.view1', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/view1', {
    templateUrl: 'view1/view1.html',
    controller: 'View1Ctrl'
  });
}])

.controller('View1Ctrl', ['$scope', '$location', '$timeout', function($scope, $location, $timeout) {


$scope.currentLocation = $location.url();
$scope.myList =  [1,2,3]
$scope.$on(
    "$locationChangeSuccess",
    function handleLocationChangeSuccessEvent( event ) {
        $scope.currentLocation = $location.url();
    }
);

var startWatchingTimer = $timeout( startWatchingForLocationChanges, 0, false );
var stopWatchingLocation = null;

function handleLocationChangeStartEvent( event ) {
    event.preventDefault();
    var targetPath = $location.path();
    var targetSearch = $location.search();
    var targetHash = $location.hash();

    if ($scope.myList.length > 0) {
        if (confirm('Leave the page?')) {
            proceedWithLocationChange(targetPath, targetSearch, targetHash)
        }
    } else {
        proceedWithLocationChange(targetPath, targetSearch, targetHash)
    }
}

function proceedWithLocationChange(targetPath, targetSearch, targetHash) {
    stopWatchingLocation();
    $timeout(() => {$location.path( targetPath ).search( targetSearch ).hash( targetHash )},10);
}




function startWatchingForLocationChanges() {
    console.log("watching");
    stopWatchingLocation = $scope.$on( "$locationChangeStart", handleLocationChangeStartEvent );
}

}]);

Answer โ„–2

If you wish to display a modal from a page-partial, the structure would look like this:

<div ng-controller="MainCtrl" class="container">
  <button ng-click="toggleModal('OK')" class="btn btn-default">Click Me</button>
  <modal visible="showModal">
      Add any extra content or buttons here
  </modal>
</div>

Create a directive to handle the modal visibility.

mymodal.directive('modal', function () {
    return {
      template: '<div 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">&times;</button>' + 
                '<h4 class="modal-title">{{ buttonClicked }} was clicked!!</h4>' + 
              '</div>' + 
              '<div class="modal-body" ng-transclude></div>' + 
            '</div>' + 
          '</div>' + 
        '</div>',
      restrict: 'E',
      transclude: true,
      replace:true,
      scope:true,
      link: function postLink(scope, element, attrs) {
          scope.$watch(attrs.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('hidden.bs.modal', function(){
          scope.$apply(function(){
            scope.$parent[attrs.visible] = false;
          });
        });
      }
    };
  });

Lastly, when the button is clicked, you can redirect the user.

mymodal.controller('MainCtrl', function ($scope) {
    $scope.showModal = false;
    $scope.buttonClicked = "";
    $scope.toggleModal = function(btnClicked){
        $scope.buttonClicked = btnClicked;
        $scope.showModal = !$scope.showModal;
        if(btnClicked == "OK") {
        $window.location.href = '/index.html';
        }

    };
  });

Answer โ„–3

When working with AngularJs, you have the ability to utilize a run function to monitor the $stateChangeStart event and execute actions accordingly. This function is triggered before the transition occurs, allowing you to prevent or redirect to a different location. These actions can also be implemented at the component level.

angular.module('MyApp').run(performRedirect);
/** @ngInject */
function performRedirect($rootScope, $window, SomeService) {
    const stateChangeStart = $rootScope.$on('$stateChangeStart', (event) => {
        // implement your logic and take appropriate action
        if (SomeService.hasPermission()) {
            event.preventDefault();
            $window.location = '/path/to/redirect';
        }
    });
    $rootScope.$on('$destroy', performRedirect);
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Locate all instances of words that begin with a certain character and are immediately followed by numbers within

I am searching for words that start with "mc" and are followed by digits only. let myString = "hi mc1001 hello mc1002 mc1003 mc1004 mc mca"; Expected output = [mc1001, mc1002, mc1003, mc1004] This is how I tackled it: const myRegEx = /(?:^|\s)mc(. ...

Trigger a function when clicking outside the element, similar to how a Bootstrap modal is closed

I have successfully created a popup box using angular in my project. It appears when I click on an icon and disappears when I click on the close button. However, I would like it to also close if someone clicks outside of the popup. Can anyone help me with ...

Guarantee of SQL integration within JavaScript

I am trying to retrieve the value of the message variable, but all I see in the console is the following: result [object Promise] async function Testing() { let response = await new Promise((resolve, reject) => { db.query("SELECT * FROM `ni ...

What could be causing the consistent Mocha "timeout error" I keep encountering? Additionally, why does Node keep prompting me to resolve my promise?

I'm encountering a timeout error repeatedly, even though I have called done(). const mocha = require('mocha'); const assert = require('assert'); const Student = require('../models/student.js'); describe('CRUD Tes ...

UTF-8 characters not displaying correctly in Python 3 when received through WebSocket?

I am encountering an issue with sending a JavaScript unicode star character. When interpreted by Python, the unicode characters are being displayed as the letter รข, both in the console and log file. Furthermore, other unicode characters also seem to be ...

Contrast between the expressions '$(<%= DDL.ID %>) and $('<%= DDL.ID %>')

I spent hours trying to attach an event to a drop-down list with no success. I even sought help in a JavaScript chat room, but couldn't find a solution. However, by randomly attempting the following code: $('<%= ddl.ID %>').bind(&apos ...

Creating a Wireframe in Three.js Using a RawShaderMaterial with LineSegments

In the midst of my work on a project, I encountered a dilemma with rendering an intricate wireframe using THREE.LineSegments. My objective is to gradually animate the vertices within this LineSegments material (referred to as warehouse in the project), but ...

Implementing Security Measures for ExpressJS Static File Server

Recently, I set up an authentication system following a tutorial on express.js and passport.js. In the past, my express server setup used modRewrite as shown below: var express = require('express'); var modRewrite = require('connect-mod ...

Using special symbols in HTML5 data attributes

Is it feasible to locate all DOM elements using jQuery with wildcard characters in the attribute name? Take into consideration the following HTML code: <input id="val1" type="text" data-validate-required data-validate-minlength ...

Transferring URL from web.config to an AngularJS .html view

In my current project, I am working on an application that utilizes Asp.net MVC along with Angularjs. One challenge I encountered is how to pass a URL, which is stored as a key in the web.config file, to a link within an Angularjs .html view. For example, ...

Using ElectronJS requires the usage of the import keyword to load ES Modules

I've recently delved into Electron development by exploring the Electron Docs. I opted for ES6 syntax with import/export, while the documentation showcased the use of require. To align with ES Module standards, I updated my package.json file with typ ...

Tips for automatically filling in fields when a button is clicked in a React application

I'm attempting to pre-fill the form fields that are duplicated with data from already filled fields. When I click the "Add Fields" button, new fields are replicated, but I want them to be pre-populated with data from existing fields. How can I access ...

Unexpected result when trying to return a value from a recursive function

Attempting to solve the problem of calculating the number of ways a number can be decoded, with 1 as a, 3 as c, and 26 as z. The function seems to calculate the correct count, but for some reason only returns undefined. It appears that the recursive calls ...

Using an array of JSON objects to set up a Backbone.js bootstrap-initialized application

Trying to bootstrap a backbone collection by using an array of JSON objects has led to some unexpected errors. When attempting to call reset on the collection object, an error from Backbone is thrown - Uncaught TypeError: undefined is not a function. Inte ...

Adding an image or icon inside a tooltip using ChakraUI or CSS in a React project

Looking to enhance my tooltip using the Chakra UI library by adding an image/icon directly into it. Instead of just displaying the label, I want the MdWarningAmber Icon to be visible within the tooltip itself, rather than next to the button that triggers t ...

Discover the Phillips Hue Bridge within the operational web application on a separate network

Utilizing the node-hue-api package on a Node.js/Express server to interact with the Hue API, I've developed an admin section of a website exclusively accessible to me for controlling my Hue lights. The functionality works seamlessly in my local develo ...

What is the process for removing an item from an array that is stored in the backend server?

Apologies for my lack of experience in coding, but I encountered an issue where clicking on the item redirected me to a page and resulted in an error instead of deleting it. I attempted to delete the item using the product ID, but it was not successful. Ev ...

The functionality of the Angular directive ngIf is not meeting the desired outcome

We are currently working on transferring data from one component to another using the approach outlined below. We want to display an error message when there is no data available. <div *ngIf="showGlobalError"> <h6>The reporting project d ...

Creating a customized post method in Angular's resource API

I am looking to streamline my code for posting data to a SharePoint list by utilizing a resource factory. Currently, I have been posting data using the following method: this.save = function(data) { data["__metadata"] = { "type": getItemTypeForListNam ...

Error: Attempting to access the 'getCroppedCanvas' property of an undefined value in VueJs

I've been exploring the vue-cropperjs library, but every time I execute the code, I encounter error messages: Uncaught TypeError: Cannot read property 'getCroppedCanvas' of undefined Uncaught TypeError: Cannot read property 'replace&ap ...