Using Vue.js's nextTick method within a computed property

I am currently working on a "context menu" component. The computed properties top and left are used to determine the menu position based on the $event property. However, I encountered an issue where the menu element is not rendered yet when trying to open the context menu, making it impossible to calculate the top value without knowing the menu's offsetHeight. To address this, I came up with a solution using a "nextTick hack" inside the computed property:

top() {
  if (!this.menuIsRendered) { // by default, menuIsRendered is false 
    this.$nextTick(() => {
      this.menuIsRendered = true
    })

    return 0
  }

  ... // After menu element is rendered, calculate the top value
},

Do you think this approach is acceptable? I believe there might be a better way to handle this situation.

Here is the complete code for the component:

<template>
  <div ref="menu" :style="{top: `${top}px`, left: `${left}px`}"
    v-click-outside="close" @contextmenu.prevent v-if="show">
    <slot></slot>
  </div>
</template>

<script>
export default {
  props: [
    'show',
    'event'
  ],
  data() {
    return {
      menuIsRendered: null,
    }
  },
  computed: {
    top() {
      if (!this.menuIsRendered) {
        this.$nextTick(() => {
          this.menuIsRendered = true
        })

        return 0
      }

      let top = this.event.y
      let largestHeight = window.innerHeight - this.$refs.menu.offsetHeight - 25

      return top > largestHeight ? largestHeight : top + 1
    },
    left() {
      if (!this.menuIsRendered) {
        return 0
      }

      let left = this.event.x
      let largestWidth = window.innerWidth - this.$refs.menu.offsetWidth - 25

      return left > largestWidth ? largestWidth : left + 1
    },
  },
  methods: {
    close() {
      this.$emit('close')
    },
  }
}
</script>

How to use the component:

<context-menu @close="close" :event="event" :show="show">
  <div @click="doAction">Perform Action</div>
  <div @click="doAnotherAction">Execute Another Action</div>
</context-menu>

Answer №1

Traditionally, computed properties are expected to be synchronous. However, if you wish to have these properties be asynchronous, it is recommended to utilize the following plugin: https://github.com/foxbenjaminfox/vue-async-computed

By integrating this plugin, Vue allows for computations that can take place asynchronously. Without its implementation, achieving this functionality would not be possible.

Now, you have the capability to define asynchronous computed properties using the asyncComputed attribute :

asyncComputed: {
  userBio () {
    return Vue.http.get('/get-bio-by-id/' + this.userId)
      .then(response => response.data.bio)
  }
}

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

I am trying to use getColumnCount() and getPhysicalNumberOfCells methods in my Selenium WebDriver script but they are not

Currently, I am dealing with .xlsx spreadsheets in Selenium using a combination of Selenium-2.53.1 jar and Apache poi-3.17 jars. However, when attempting to retrieve the total number of columns through methods like getColumnCount() and getPhysicalNumberO ...

Show a checkmark or X depending on the condition in Javascript

I have an array of data that I want to compare to the input in a text field. If the input matches an element in the array, I want to display a checkmark, and if it doesn't match, I want to display a crossmark. However, I'm having an issue where ...

Is there a workaround for utilizing a custom hook within the useEffect function?

I have a custom hook named Api that handles fetching data from my API and managing auth tokens. In my Main app, there are various ways the state variable "postId" can be updated. Whenever it changes, I want the Api to fetch new content for that specific p ...

External function does not support jQuery types

In my theme.js file, I currently have the following code: jQuery(function ($) { accordion($) }) const accordion = ($) => ... By placing the accordion function directly into the jQuery function, Typescript is able to assist with the installed jquery ...

What causes the literal loop to produce additional commas in its output?

Having some trouble understanding template literals in javascript, particularly the syntax. Whenever I run this loop, it seems to output extra commas between each iteration: character = () => { const traits = ["Knowledge", "Agility","Strength", "Ch ...

Running PHP scripts from JavaScript

Currently working on a PHP project that involves a dropdown select button in a webpage. The goal is to call a JavaScript function whenever the value of the dropdown changes, and then pass this selected value to retrieve additional details from a MySQL da ...

Redirecting to a new page in JavaScript as the clock nears the top of the hour after 5 minutes

I am looking to automatically redirect a user to another page when it is 5 minutes until the start of the next hour. In military time (24-hour clock), this means I want the redirect to occur at times like... 11:55 12:55 13:55 14:55 15:55 etc So far, I ...

Error: The function wrapper.find().simulate('keypress', {key: 'Enter', keycode: 13}) is not working as expected

Let's discuss further about this query vue-btn isn't triggering on pressing the enter key I have designed a sign-in page where users can log in by pressing 'Enter' on the keyboard. Now, I aim to perform a unit test that simulates pres ...

What is the best way to retrieve the current font size of a link element?

Is there a way to determine the font size of an element in pixels or points? Are there alternative methods available to achieve this? I am looking to increase the size of <a href="...">MAKE ME BIGGER</a> by 130%, 140%, N% based on its current ...

Leveraging jQuery selectors to manipulate data received from an Ajax response

I am encountering an issue with an Ajax call and response. Previously, I had a block of regular javascript code that successfully transformed my select element into a select2 widget. However, when I attempt to convert the select element into a select2 usi ...

Executing a route function in node.js without specifying a form action

When working with node.js and express.js applications, a form action is typically used to call a route function. This is done by specifying the route in the form element like so: <form action="/home"> .... </form> Once the form is submitted, ...

The program is functioning properly, however it is only showing me the last 5 entries when using Ajax

My code is functioning correctly, but it's only displaying the last 5 records out of over 100. Strangely, without using Ajax, all records are displayed. I'm working on developing MLM Software with 15 levels where records are displayed based on re ...

Creating a flexible grid layout that adjusts to show either one or two columns on smaller mobile screens

NOTE: This is not a duplicate as the layout order for columns and rows is specifically tailored for mobile devices. I am attempting to showcase this grid design on mobile devices with the following sequence: First row: header (1 column, full width) Secon ...

The functionality of "perfect-scrollbar" (jQuery plugin) may not be properly initialized when the container it is in is being populated by Angular.js

I have a unique setup on my website where I dynamically generate food and drinks menus using a json file with Angular.js. The issue arises with the implementation of "perfect-scrollbar", which seems to require a scroll-wheel event to work properly on these ...

Arrangement of images in an array

Here's the scenario I'm facing. https://i.stack.imgur.com/FbAfw.jpg So, I have an array of images that I want to use to create a gallery with a specific layout. I've tried using grid and playing around with :nth-child(even) and :nth-child( ...

Triggering Submit Button Based on Checkbox Value in jQuery

Hey there, I'm encountering an issue. Let's say I have two types of checkboxes - one for person and one for company. If I submit the form without checking any of the person or company checkboxes, I want jQuery to display an alert. Otherwise, the ...

Vue 3 + Vite: The router path was not found

I'm currently working on a project using Vue 3 and Vite, where I need to verify if the user is logged in with AWS Cognito before accessing the main page. Here's an example of my router.js: import { createRouter, createWebHistory } from &apo ...

When there is a data change caused by JavaScript, the `.on('change' ...) event will not be triggered

I'm experiencing an issue with triggering an event when the value of an input textbox changes: $('.packeta-selector-branch-id').on('change', function () { alert('hello'); }) Currently, this event only fires when I manua ...

How can I use JavaScript or CSS to identify the specific line on which certain words appear in the client's browser?

Imagine I have the following HTML structure: <div> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco labor ...

Transmitting HTTP headers using Node.js

Within my Node JS Express application, I have an API endpoint called 'download' that returns a buffer to the calling application along with a header named 'status', which is a Javascript object. The response from Node sends the buffer ...