Tips on applying a transition to a v-dialog with "dynamic width" and utilizing width="unset"

Currently, I am in the process of developing a form component enclosed within a v-dialog. This particular form component will consist of various child components that are displayed based on user input selection. In order to ensure that the dialog width adjusts according to its content, I have set the width of the v-dialog to "unset".

The challenge arises when attempting to incorporate transitions with dynamic widths. Since the width of the form within the dialog is unknown beforehand and subject to change, traditional transition methods do not seem to work effectively.

I have explored different approaches such as utilizing refs to retrieve the width of the form component, but setting the width to unset seems to impede the transition effect. While fixed widths showcase smooth transitions, dynamic widths pose a unique obstacle in achieving the same level of transition fluidity.

<div id="app">
  <v-app id="inspire">
    <div class="text-center">
      <v-dialog v-model="dialog" width="unset">
        <template v-slot:activator="{ on }">
          <v-btn color="red lighten-2" dark v-on="on">
            Click Me
          </v-btn>
        </template>
        <v-card>
          <v-select v-model="selectedForm" :items="items">
          </v-select>
          <div v-if="selectedForm==='form-a'" class='form-a'>FormA</div>
          <div v-if="selectedForm==='form-b'" class='form-b'>FormB</div>
          <v-card-actions>
            <v-spacer></v-spacer>
            <v-btn color="primary" text @click="dialog = false">
              I accept
            </v-btn>
          </v-card-actions>
        </v-card>
      </v-dialog>
    </div>
  </v-app>
</div> 

new Vue({
  el: "#app",
  vuetify: new Vuetify(),
  data() {
    return {
      selectedForm: "form-a",
      items: ["form-a", "form-b"],
      dialog: false
    };
  }
});

Codepen demo with fixed width usage: https://codepen.io/duongthienlee/pen/MWaBLXm
Codepen demo showing dynamic width implementation: https://codepen.io/duongthienlee/pen/GRpBzmL

In my Codepen examples, I have predefined the width, but in actual scenarios, the width of form-a and form-b components remains undetermined. These widths are essentially inherited by their parent div, which is the v-dialog, thus necessitating the use of an 'unset' width value for the dialog.

To illustrate the concept of "dynamic width": consider form-a containing a select input. Upon selecting an item, an API call is made to fetch input labels. Subsequently, form-a dynamically renders multiple input fields based on the server response. As a result, the width of form-a fluctuates based on the retrieved information.

Answer №1

Here is a solution that might suit your needs.

Update the v-dialog element as follows:

<v-dialog v-model="dialog" :width="forms.find(x => x.name===selectedForm).width">

Adjust the data() method to include a new property called forms:

data() {
    return {
      selectedForm: "form-a",
      items: ["form-a", "form-b"],
      dialog: false,
      forms: [
        {
          name: 'form-a',
          width: 200
        },
        {
          name: 'form-b',
          width: 1000
        }
      ]
    };
  }

Answer №2

To achieve the desired effect, you need to determine the size of the displayed form and then apply it to the dialog box. This is a common practice when animating content with varying dimensions. One approach to accomplish this is as follows:

  1. Hide the form initially
  2. Allow time for the form to render
  3. Retrieve the width of the form and assign it to the dialog box
  4. Show the form again

An important aspect involves properly waiting for DOM (setTimeout) and Vue ($nextTick) recalculations. While in this example I did not have to wait for Vue's $nextTick, you may need to do so if you are dealing with nested form components:

<div class="form-container">
  <div :style="formStyle('form-a')" class='form-a' ref="form-a">FormA</div>
  <div :style="formStyle('form-b')" class='form-b' ref="form-b">FormB</div>
</div>
computed:{
  formStyle(){
    return form => ({
      visibility: this.selectedForm == form ? 'inherit' : 'hidden',
      position: this.selectedForm == form ? 'inherit' : 'absolute'
    })
  }
},
methods: {
  async onSelectChange(form){
    // simulate asynchronous request
    await new Promise(resolve => setTimeout(resolve, 1000))
    this.selectedForm = form
    this.recalculate()
  },
  async recalculate(){
    // wait for DOM to update
    await new Promise(resolve => setTimeout(resolve))
    const formEl = this.$refs[this.selectedForm]
    this.dialogWidth = formEl.clientWidth
    this.dialogHeight = formEl.clientHeight
  },
  ...
}

If you want to see a working example, check out this code snippet: https://codepen.io/cuzox/pen/yLYwoQo

Answer №3

If my understanding is correct, you can achieve this using CSS. You may consider replacing all fixed widths in the form with

  width: fit-content;

For instance, in your codepen:

.form-a {
  width: fit-content;
  height: 350px;
  background: blue;
}
.form-b {
  width: fit-content;
  height: 500px;
  background: red;
}

Answer №4

The v-dialog component generates a div element with the class of v-dialog: https://i.sstatic.net/OS86l.png

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

It appears that the animation only functions properly when the width is set to a specific value, rather than just being "unset". One workaround is to determine the width of the child element and dynamically adjust the width of the v-dialog component using a variable.

To learn how to obtain the width of a child element in VueJS, check out VueJS get Width of Div.

If you give this solution a try, please let me know if it works for you as I find this approach quite fascinating.

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 store values in LocalStorage by clicking?

Is there a way to store this value in localstorage whenever the user clicks either up or down??? <script> var Clicks = 800; function UpClick() { Clicks = Clicks + 25; document.getElementById('CountedClicks').innerHTML = C ...

Overflow of content within a rectangular element

One challenge I'm facing is creating HTML/CSS code that automatically adjusts the website layout (blocks and content) when I resize the browser window. For example: I encounter text overflow issues in a block I've created when I minimize the brow ...

Issue updating user information in Laravel 7

I've been searching for a solution, but I haven't been able to update the "status" field in the users table. I recently added two additional fields to Laravel's default user table. Here is the migration code I used: public function up() { ...

Utilize JavaScript to eliminate tags surrounding a text node

If my HTML code looks something like this: <div id="text"> This is some text that has an area <span class="highlight">highlighted with different formatting</span> and then some more text. </div> I am trying to figure ...

Struggling with vertical alignment issues in a div element

Can anyone help me figure out how to vertically align a div? I've been struggling with it and can't seem to get it right. What am I missing? body { border: 1px solid red; height: 500px; } #contactUs { border: 1px solid blue; vertical-align: bo ...

Two collapsible menus featured in the navigation bar

My navbar is displaying two collapse menus, but when one is active and I open the second one, the collapsed content from the second menu gets added to the end of the first one's content. How can I close the other menu when opening the second one? h ...

Safari experiencing issues with Brightcove's chromeless video player controls

There seems to be an issue with BrightCove's Chromeless player. When hovering over the controls (pause, play, and move to a specific time in the video), they appear but clicking on them causes them to just disappear instead of pausing/playing or movi ...

Connections between Wordpress websites and CSS styling

My inquiry consists of three parts: I am currently in the process of constructing a portfolio website using Wordpress, and I have encountered some peculiar links. For instance, on my about page, the link appears as localhost/AFolder/anotherfolder/ind ...

When content editable is assigned a value, it skews the direction of the writing

I am currently working on an editable text component with the 'editable' attribute. However, I am facing an issue where the text is not aligning in the correct direction as I type - the first character always ends up at the end of the text. Expe ...

Load the div iframe when it is clicked

I'm looking for a way to optimize the loading of div elements on my website. Currently, when the page is loaded, all divs are also loaded but remain hidden until clicked. Is there a method to delay loading the content of a specific div until it's ...

Passing data from an object to a Vue component

Looking to pass props to a component? Have the props stored in an object and want to implement something like this: <v-btn btn.size.sm btn.size.md btn.size.lg > {{ btn.text }} </v-btn> The btn object is structured as follows: btn = ...

dompdf: Setting a white margin on an A4 size paper

I'm currently utilizing dompdf, a PHP library, to generate PDF pages and I've encountered an issue with setting the correct dimensions. Whenever I apply the CSS property: @page { size: 21cm 29.7cm; } .... and let's say I want the top ...

What is the best way to select the child of the second-to-last child?

In the structure of my HTML code, I have an unordered list with a class "menu" containing several list items and corresponding anchor tags like this <ul class="menu"> <li> <a href="#1"></a> </li> <div&g ...

Is it possible to display two PrimeFaces growl components on a single page with distinct positions?

How can I place several p:growl components on the same page in different positions - one on the left, one on the right, and one in the center? When I try to override the style for each growl individually, it affects all of them like this: <style type= ...

Experiencing a Blank File Issue in Laravel DomPDF When Sending Request with Axios

I've been working on a project using Laravel DOMPDF, Axios, and Vue.js to generate PDF files. While I am able to download the file successfully, it turns out that the downloaded file is blank with a size of 0 bytes. Can anyone shed some light on why t ...

Adjust the height of the page to fit the available screen space on mobile devices

Seeking a solution to ensure my web app fills the entire height of the device. Currently utilizing 100vh on the body tag, however, Safari tab on iOS adds an additional height which causes users to have to scroll down to view the full page. Any suggestions ...

A guide to showcasing JSON data on a webpage using JavaScript

I am currently working on a SOAP WSDL invocation application in MobileFirst. The response I receive from the SOAP WSDL is in JSON format and is stored in the result variable. When trying to access the length of the response using result.length, I encounter ...

Enhancing your project with Laravel and VueJS for seamless completion

I've spent hours attempting to define relationships for a completion system, but I've hit a roadblock. I have two tables: Users and Episodes. In my views, I want to determine if a User has completed an Episode. To accomplish this, I created a " ...

Unable to scroll the HTML page to view the complete content

View the CSS images (2 total) and the HTML image below: CSS top CSS bottom HTML ...

The CSS styling does not seem to be affecting the text button's appearance

I am currently creating a website using Bootstrap 5, and I'm facing an issue with making the header image responsive on mobile devices. While it looks great on desktops, laptops, and tablets, on mobile screens, the text and button alignment is off. I& ...