VueJS causing roles checking to run forever, creating an infinite loop

Customizing the navigation bar to display elements based on user roles:

<b-navbar-toggle
    right
    class="jh-navbar-toggler d-lg-none"
    href="javascript:void(0);"
    data-toggle="collapse"
    target="header-tabs"
    aria-expanded="false"
    aria-label="Toggle navigation">
  <font-awesome-icon icon="bars"/>
</b-navbar-toggle>

<b-collapse is-nav id="header-tabs">
  <b-navbar-nav class="ml-auto">
    <b-nav-item-dropdown
        right
        id="pass-menu"
        v-if="hasAnyAuthority('ROLE_USER') && authenticated"
        :class="{'router-link-active': subIsActive('/pass')}"
        active-class="active"
        class="pointer">
                <span slot="button-content" class="navbar-dropdown-menu">
                    <font-awesome-icon icon="ticket-alt"/>
                    <span>First element</span>
                </span>
    </b-nav-item-dropdown>

    <b-nav-item-dropdown
        right
        id="dictionaries-menu"
        v-if="hasAnyAuthority('ROLE_ADMIN') && authenticated"
        :class="{'router-link-active': subIsActive('/dictionary')}"
        active-class="active"
        class="pointer">
                <span slot="button-content" class="navbar-dropdown-menu">
                    <font-awesome-icon icon="book"/>
                    <span>Second element</span>
                </span>
    </b-nav-item-dropdown>
  </b-navbar-nav>

Sometimes, setting different roles for these elements causes an issue where an infinite loop occurs and the system becomes unresponsive.

The code snippet below shows how roles are checked in Vue component:

@Component
export default class JhiNavbar extends Vue {
  @Inject('loginService')
  private loginService: () => LoginService;

  @Inject('accountService') private accountService: () => AccountService;
  public version = VERSION ? 'v' + VERSION : '';
  private currentLanguage = this.$store.getters.currentLanguage;
  private languages: any = this.$store.getters.languages;
  private hasAnyAuthorityValue = false;

  created() {}

  public get authenticated(): boolean {
    return this.$store.getters.authenticated;
  }

  public hasAnyAuthority(authorities: any): boolean {
    this.accountService()
      .hasAnyAuthorityAndCheckAuth(authorities)
      .then(value => {
        this.hasAnyAuthorityValue = value;
      });
    return this.hasAnyAuthorityValue;
  }
}

Below is the service responsible for managing user accounts:

export default class AccountService {
  constructor(private store: Store<any>, private router: VueRouter) {
    this.init();
  }

  public init(): void {
    this.retrieveProfiles();
  }

  public retrieveProfiles(): void {
    axios.get('management/info').then(res => {
      if (res.data && res.data.activeProfiles) {
        this.store.commit('setRibbonOnProfiles', res.data['display-ribbon-on-profiles']);
        this.store.commit('setActiveProfiles', res.data['activeProfiles']);
      }
    });
  }

  // Other methods related to account retrieval and authorization checks...

A workaround provided by @bigless involves creating separate functions to check for admin and user roles:

...
  private hasAdminAuthorityValue = false;
  private hasUserAuthorityValue = false;
...
  public hasAdminAuthority(): boolean {
    this.accountService()
      .hasAnyAuthorityAndCheckAuth('ROLE_ADMIN')
      .then(value => {
        this.hasAdminAuthorityValue = value;
      });
    return this.hasAdminAuthorityValue;
  }

  public hasUserAuthority(): boolean {
    this.accountService()
      .hasAnyAuthorityAndCheckAuth('ROLE_USER')
      .then(value => {
        this.hasUserAuthorityValue = value;
      });
    return this.hasUserAuthorityValue;
  }

Answer №1

The issue at hand is a result of Vue's reactivity system. When an async method is used within a v-if statement, it can lead to undesired behavior as Vue tracks all reactive dependencies of the method. If any dependency changes, the statement is re-evaluated, causing the function to be called again.

Furthermore, this issue arises specifically when different roles are involved due to the shared property hasAnyAuthorityValue being a reactive dependency for the aforementioned method.

To elaborate, suppose privileges are obtained for ROLE_USER synchronously and then later updated asynchronously in a promise. This setup can work if the async result remains consistent (i.e., one role). However, when the value of hasAnyAuthorityValue fluctuates between ROLE_USER and ROLE_ADMIN with async results, it creates an infinite loop.

There are several solutions to address this issue. For instance, saving the results of both hasAnyAuthority(any) as data properties during the component's creation phase or using distinct property names for each role instead of relying on a shared property.

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

Is it possible to dynamically store JavaScript code in a variable and then have JavaScript execute it?

I'm uncertain if my current method is the most appropriate for my goal. Essentially, I am fetching data from a database using an ajax call, and I want this data to populate a JavaScript library where the layout is structured like this: data[ item{ ...

"Bootstrap is functioning properly on my local environment, but it seems to

Utilizing the MVC framework and bootstrap has been successful for optimizing my website locally. However, when I upload it to the server, none of the CSS is being rendered. Additionally, the front page, meant to be a carousel slider, appears as a vertical ...

Using indexOf() in JavaScript

Recently, I delved into learning JavaScript through the guide of Beginning Javascript 5th edition. However, I am stumped by a perplexing JavaScript script function getCookieValue(name) { var value = document.cookie; var cookieStartsAt = value.indexOf(" " ...

How can I simulate or manipulate the element's scrollHeight and clientHeight in testing scenarios?

In my JavaScript code, I have a function that checks if an HTML paragraph element, 'el', is a certain size by comparing its scrollHeight and clientHeight properties: function isOverflow(element: string): boolean { const el = document.getEleme ...

Unable to make CSS footer stay at the bottom of the page following the utilization of V-for to display a list of items in

Footer seems to be misbehaving by not staying at the bottom and instead showing under the items rendered using v-for. This issue is only happening on this page while it is working fine on others. <template> <div> <!-- Item renderin ...

Tips for identifying a webpage and making class modifications based on it

I am working on a customized bar with 4 distinct parts. Each part corresponds to a different page on the website. I want each part of the bar to change color based on which page the user is currently browsing. For example, if the user is on page A, I want ...

Unable to extract query parameters from URL using Express JS as req.query returns an empty object

I came across discussions about this issue here and here, but unfortunately, the solutions provided didn't work for me. I'm attempting to extract parameters from the URL using req.query. In my server.js file, I've implemented the following: ...

Positioning broadcasted videos on a web page using the OpenTok API

Currently, I am utilizing opentok to connect to the broadcast service and obtaining the flash player object at the bottom of my page. I am seeking guidance on how to position it within a specific div container. The following code snippet demonstrates how ...

The functionality in the React Native code that uploads images to an S3 bucket is currently failing to initiate the network request

I have been using a redux-observable epic to upload images to my AWS S3 bucket through react-native-aws3. It has been functioning smoothly for quite some time. However, recently it seems to have stopped entering the .map and .catch blocks of code. I suspec ...

Displaying entries of input data

I have an application that includes a modal window with filters, but I am looking to add another type of filter. However, I am struggling with implementing it in React and would appreciate any help with the code or recommended links. Essentially, I want t ...

AngularJS allows developers to easily create radio boxes with pre-selected items

Can anyone help me figure out how to set the selected item as checked when using a radio button list? Here is an example of my code: <div ng-repeat="vehicle in filteredVehicle"> <input type="radio" name="radiog_lite" id="radio_{{$index}}" class= ...

Is it possible to invoke an AngularJs service by clicking a button?

Recently, I've been working on some AngularJS code involving a service and controller. angular.module('myModule', []).service("AttendanceService", function ($http) { this.getdata = function () { return $http({ ...

Ways to incorporate a custom JavaScript function that is activated by an external server system?

I'm currently exploring a JavaScript widget that needs to operate within specific constraints: The widget initiates a request to a third-party server using a callback URL The third-party server pings the callback URL after a set period, triggering a ...

What order does JavaScript async code get executed in?

Take a look at the angular code below: // 1. var value = 0; // 2. value = 1; $http.get('some_url') .then(function() { // 3. value = 2; }) .catch(function(){}) // 4. value = 3 // 5. value = 4 // 6. $http.get('some_url') ...

What methods can I use to ensure precision in my raycasting while maneuvering the mouse over various sections of a LineSegment?

I have created a demonstration for drawing a LineSegment using three.js. I have implemented vertexColors in the material and assigned colors to the vertices. When hovering over different parts of the LineSegment, I change the color of the selected vertex ( ...

What is the best way to activate multiple events within an overlapping area containing multiple divs at the same

How can I trigger events on same level divs that overlap in different areas? When there are multiple divs overlapping, only one of them gets triggered. Is there a way to trigger events on all overlapped same level divs? Here is an example code snippet: ...

Maximizing the power of datatables with ajax integration

Exploring pagination with AJAX on datatables.net is something I want to try. I have two input fields where users can enter start and end dates, followed by the table structure below: <table class="table table-hover" id="example"> < ...

Updating JSON when the color changes in Go.js can be achieved by implementing event listeners and

I've been using Go.js for creating Flow charts and saving the json data into a SQL database. However, I'm facing difficulties in updating the json data. Here is the code snippet: myDiagram.addDiagramListener("ChangedSelection", function (e1) { ...

Strategies for detecting and handling blank data in JSON parsing with JavaScript

Here is a function that retrieves details: function GetSomeDetails(Param) { Json_Parameters = JSON.stringify(Param); $.ajax({ type: "POST", url: "MainPage.aspx/MyMethod", data: J ...

What could be causing my if statement to fail even though the condition is met?

I'm attempting to generate dynamic fields based on my chosen attributes. I have two array objects called addAttributes and fakeAttributes. The fakeAttributes contain the details of the selected attributes. I have a dropdown select component that displ ...