Unable to preventDefault() function from working within .then method

Snippet:

angular
  .module('mean-starter')
  .run(run)
;

function run($rootScope, Auth, $state) {
  function stopStateChange (message, event, redirect) {
    console.log(event);
    event.preventDefault();
    alert(message);

    if (redirect) {
      $state.go(redirect);
    }
  }

  $rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
    if (typeof toState.authenticate === 'undefined') { // this route doesn't require permissions
      return;
    }

    event.preventDefault(); // WORKS HERE

    Auth
      .getCurrentUser()
      .then(function (currentUser) {
        event.preventDefault(); // DOESN'T WORK HERE
        var isLoggedIn = !!currentUser._id;
        var isAdmin = isLoggedIn && currentUser.role === 'admin';
        var isAuthorized = isLoggedIn && currentUser._id.toString() === toParams.id;

        if (toState.authenticate.loggedOut && isLoggedIn) { // this route requires you to be logged out
          stopStateChange("You're logged in.", event);
        }
        else if (!isLoggedIn) {
          stopStateChange('Must be logged in to access this route.', event, 'login');
        }
        else if (toState.authenticate.authorized && !isAuthorized && !isAdmin) {
          stopStateChange('You are not authorized to access that route.', event);
        }
        else if (toState.authenticate.isAdmin && !isAdmin) {
          debugger;
          event.preventDefault();
          stopStateChange('You must be an admin to access this route.', event);
        }
      })
    ;
  });
}

Upon logging in as a non-admin and visiting localhost:3000/admin:

  1. An alert pops up with the message, "You must be an admin to access this route."
  2. I am directed to the admin page where I can see all restricted content.

Why is this happening?

When examining in the debugger, the event.preventDefault seems to be executed. Here's the event object displayed:

https://i.sstatic.net/oxTKO.png

The defaultPrevented property is set to true!


UPDATE: The behavior works outside of the .then block but fails within it. Surprisingly, even though defined inside .then.


UPDATE 2: It appears that the event triggers its default action BEFORE reaching the .then, making the .then too late for interception.

Answer №1

It seems your second assumption is quite accurate. The browser actions are actually finalized once all the ongoing event handlers have completed their tasks. Interestingly, in the past, a common way to prevent the default action was by having the event handler return false or 0. This process can be described as semi-synchronous - occurring within an asynchronous function but getting resolved at the conclusion of the current event loop.

To work around this issue, it is advisable to invoke .preventDefault() prior to executing your promise.

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

Learn how to update a fixed value by adding the content entered into the Input textfield using Material-UI

I made a field using the Input component from material-ui: <Input placeholder="0.00" value={rate} onChange={event => { this.setState({ `obj.rate`, event.target.value }); }} /> Whenever I input a rate into this field, ...

The onbeforeunload event is activated in the parent page when it is specified in the child page

Seeking a way to activate the window.onbeforeunload method when a user attempts to refresh the browser, and display a message to prompt them to save their current work before leaving. I am currently working on an AngularJS application. Here is the URL of m ...

Exploring Next.js dynamic imports using object destructuring

import { UDFCompatibleDatafeed } from "./datafeeds/udf/src/udf-compatible-datafeed.js"; I'm facing a challenge in converting the above import to a dynamic import in Next.js. My attempt was as follows: const UDFCompatibleDatafeed = dynamic(( ...

Choosing multiple items using ng-checked and ng-model in AngularJS

I am working with an Ionic application and encountering a minor issue, much like AngularJS. <ion-list class="list-inset subcategory" ng-repeat="item in shops"> <ion-checkbox class="item item-divider item-checkbox-right" ng-model="selectAll" ...

What is the best way to upgrade to a specific version of a child dependency within a module?

npm version: 7.24.2 Looking for assistance on updating a child dependency. The dependency in question is: vue-tel-input This dependency relies on libphonenumber-js with version ^1.9.6 I am aiming to update libphonenumber-js to version ^1.10.12. I have ...

The tagging feature in ui-select isn't working properly, showing an error message that says "Cannot read property 'length' of undefined"

Looking to set up a ui-select for keyword tagging. Initially, when adding a new tag everything works fine, but after removing all tags and adding a new one, I get the error: Cannot read property 'indexOf' of undefined Check out the demo here ...

JavaScript struggles to obtain the timezone information when Daylight Saving Time is

Can someone help me with setting a user's timezone offset for PHP through ajax? When a page is loaded with session data, if there is no pre-existing data, the following script is inserted into the page: <script type="text/javascript"> $(doc ...

Disabling a button does not automatically shift the focus to the next element in the tab order

Is there a way to limit the number of times a button can be clicked using jQuery? For example, I want a button that can only be clicked three times before disabling itself automatically. test.html <div class="main"> <input class="one" type="t ...

The functionality of jQuery.hover with AJAX is malfunctioning

I am facing an issue with my jquery hover combined with $.post method. My initial intention was to create a series of select buttons where hovering would trigger a change in the image being displayed (the image path would be loaded via $.post). The image ...

What is the best way to create a clickable <li> element from AJAX search results that display dynamic HTML?

Utilizing AJAX technology, I have implemented a live search feature that populates results from a database as the user types in a text field. The results are presented in an unordered list format. My goal is to allow users to click on an item within the li ...

What possible reasons could be causing the ng-show directive to malfunction?

This form displays contact information. <div class="row" ng-controller="contactsCtrl"> <form ng-show="addFormShow"> <h3>Add Contact</h3> <!-- Add form --> <div class="row"> <div class="large ...

Modifying app aesthetics on-the-fly in Angular

I am currently working on implementing various color schemes to customize our app, and I want Angular to dynamically apply one based on user preferences. In our scenario, the UI will be accessed by multiple clients, each with their own preferred color sch ...

Which is better for validation in Angular - $viewValue or $modelValue?

Being new to Angular, I am seeking validation on my form handling technique. Specifically, I want to notify the user with an appropriate message if they input more than 100 characters in a field. I am currently utilizing $viewValue for this purpose. Would ...

Efficient Ways to Store Text and Images in Vue.js

I have developed a tool that enables users to upload an image and overlay custom text on it, which can be viewed and edited in the browser. My query is whether it is feasible to save the combined image and text as separate files (e.g., jpg/png) using VueJS ...

Ways to showcase angular scope data within a placeholder while avoiding the use of angular expressions

Initially, I utilized angular expressions {{value}} to present values within elements. However, upon noticing that unrevealed expressions continue to display on the front end during loading delays, I switched to using ng-bind. <div> <h1>Hell ...

Mutation observer fails to observe an element if it is housed within a function

I am attempting to initialize the liveChatAvailable value as true and set the isLoading value to false once the crispClient element loads onto the page. However, when the observer object is placed within a function, the if (crispClient) code does not exec ...

Easily done! Using JavaScript to generate a blinking cursor on a table

Working on a project to develop a dynamic version of the classic game Tic-Tac-Toe... However... Every table cell is displaying an irritating flashing cursor, almost like it's behaving as an input field. Any insights into why this is happening...? O ...

How can you make sure that mouse events pass through the KineticJS stage?

Is it possible to have a PanoJS3 component covering the entire screen with a KineticJS stage on top, but still allow touch events to pass through the KineticJS stage to what lies beneath? I want shapes on the stage or layer to receive the touch events, wh ...

Can you verify that the client's date and time locale are accurate in JavaScript before proceeding with processing?

For my application, I am seeking the current locale datetime. However, before retrieving the date, it is crucial to verify that the local date and time are accurate. If the user has adjusted the date and time incorrectly on their machine, I must prompt a ...

What is the best way to update the key for the sorting field in a meteor collection query?

I am struggling to replace the name key with a value passed in via a parameter this.params.sortby in the code below. Any help would be appreciated. For example, if: this.params.sortby=location I would like the following: Template.MyTemplate.helpers({ ...