Sync'ing v-if and the visibility of components



  • Hi,

    my app is becoming a little lagguish when I switch between tabs, so I decided to put a few v-if here and there on modals to prevent rendering them before they are actually opened.

    At first I wrote:

    <q-modal
      v-if="model"
      v-model="model"
     >
      My modal content here
    </q-modal>
    

    This works well except that the modal, when closed, disappears immediately when model becomes false, with no animation. To prevent that, I then bound on the hide event instead:

    <q-modal
      @hide="shown = false"
      v-if="shown"
      v-model="model"
     >
      My modal content here
    </q-modal>
    
    ...
    
    data () {
      return {
        shown: false
      }
    },
    watch: {
      model: function (val) {
        if (val) {
          this.shown = true
        }
      }
    }
    

    This works as expected, but it’s a pain to write that much code for every component I don’t want to render before necessary. I’m sure most people had to face this before but I don’t know what to search. I was hoping that a simple directive on the component would do the trick, or something like that. Thanks!



  • You should be able to use the same variable you are using for v-model and v-if.

     <q-modal
       v-if="model"
       v-model="model"
      >
       My modal content here
     </q-modal>
    

    I never really needed to do that, so I’m wondering why this happened with you. It’s really hard to tell without looking at your project. But some stuff that come to mind when having to render too many components at once are:



  • Thank you for the answer, it’s simple though, that’s because v-if hides the component at the very moment you set it to false, while v-model (the component) plays a closing animation and then hides the component like 300ms later. So the closing animation is never played because v-if is already set to false.



  • Are you tabbing between modals?

    Scott



  • The tabs lead to regular pages, the modals open only upon some actions.



  • How many tabs are in use and where, and when is the data in the modals (if there is any) being loaded?

    I’d venture to say, as @zeidanbm alludes to, your design is unfortunately flawed. Are the tab panes using the keep-alive prop? The workaround with v-if really shouldn’t be necessary.

    Scott



  • Thank you @s-molinari and @zeidanbm!
    Don’t get me wrong, I really appreciate your effort to help me 🙂 But the answer “optimize your app” is beside the point.

    However much time is involved in rendering a modal that has never been opened yet, is a waste of time to me. Even if I could reduce it to 100ms, it’s 100ms that still play against the feeling of instantaneity I want when switching tabs.

    The keep-alive property would be interesting if were ready to waste time just once at first rendering, but at the cost of more memory used.

    What I am looking for is a way to let the modal component play it closing animation when v-if becomes false. The equivalent of
    <transition name="fade"><p v-if="model"></p></transition>. I think I’ll just write the directive myself if no one did that before me. Thanks



  • @Evan You can use different varialbles with v-if and QModal and trigger modal change before the v-if. Similar to what you did in your initial post but without the watchers, instead use the events that come with QModal. Check this Codepen
    I don’t know if this would be less pain but i think it might be better than using the watchers.



  • @zeidanbm Thank you! This is more elegant indeed, less code is better.
    I’ll still check if the code can be reduced to a mere directive on the QModal (I’ve never created one yet) and let you know if I can make it.
    Thanks!



  • For the record, I can’t get satisfying results with a custom directive, as it doesn’t get called before the v-if property becomes true. I’d have to rewrite something similar to a v-if directive, and I don’t have enough time nor do I know if it’s feasible.