Vue: v-else not work when together with v-show on custom component

Created on 8 Apr 2016  ·  27Comments  ·  Source: vuejs/vue

Vue.js version

1.0.21

Reproduction Link

http://www.webpackbin.com/412B9bgJb

Steps to reproduce

click Toggle button

What is Expected?

when MyComponent is showing, the msg should be hidden

What is actually happening?

the msg always shows

bug discussion

Most helpful comment

What i'm trying to say is that it's been noted that trying to mimic JS logic in templates isn't generally a good idea. This is why we have dropped trying to add v-switch and v-case. If logic in templates is to exist then it should be as simple as possible.

Making v-show and v-hide work with v-else may just cause unnecessary confusion. Especially when scanning templates. You will by default try to spot a matching v-if to the v-else as it makes contextual sense.

This is achievable in user land by a simple negate, i'd avoid adding more to Vue than is necessary. Expression logic in templates should be simple, so it should be just as simple to adding ! to the expression. If any expression is complex then it really should be handled in the JS.

All 27 comments

I'm taking a look, not sure if it's a bug or not

Ok, confirmed. It only happens on v-show though, it works on v-if
Thanks for the bug submission! :smile:

Here's a jsfiddle https://jsfiddle.net/vny4z8kj/1 (I cannot edit the webpackbin...)

seems to do the exact opposite on templates
http://codepen.io/ThatTomPerson/pen/vGdyoB

@ThatTomPerson v-show doesn't work on <template> by design, so that's working as intended.

@yyx990803 Ah ok, I'll just replace it with a div and hope the designer doesn't notice 😄

v-show shouldn't be connected to v-else. As this doesn't natively translate to traditional programmatical logic.

@blake-newman the v-show is just an _if_ that hides instead of removing. v-else turns out to be very handy, it definitely reads better than v-show="!expr"

BTW I didn't forgot about the issue. I couldn't allocate enough time for it in the past two weeks 😞
I'll find some time this weekend for sure

@posva Understand about the internals. Question in my mind is: 'Should v-show be combined with v-else?'

One issue is that v-else is currently terminable. Which means the logic behind how v-else works will completely differ based on the prefixing directive. I believe in my own opinion that this would be confusing.

What happents if there is a v-if and a v-show what would v-else be applied to. This is a weird case, but it is very valid to have v-if and v-show available on a single element.

The v-show would to apply to both I guess. I'm not sure about the use case thought

I think v-else should be replaced by v-show="!expr", and let v-if work as it is but I'm not sure this would solve the real problem which I cannot recall clearly but it has to deal with directives priorities that were not applied for components (component is a directive itself with a given priority)

I understand that it is tempting to get v-show to work with v-if once you think about it, but at first it felt a bit counter-intuitive because there would be no v-if to look for.

I also agree that the framework shouldn't be changed to accommodate this behaviour.

@posva If targeting both, there may also be issues.

What if the case is that you don't want the v-show="!expr" and want the v-else applied to the v-if only. Lot more complexity involved internally where this could be done easily in user land.

But why would you need to use v-id and v-show ?

You have a scenario where you don't want the code to evaluate further, using v-if as terminable. At the same time you want v-show/v-hide to show and hide without removing an instance. I think it's very confusing to have a logical directive available to two other directives.

In that case you should use a :style bind because v-show and v-if are meant for content toggling. Both can trigger transitions

I don't see how :style could fix what @blake-newman just described.
But I do agree with you that v-show and v-if are used for content toggling. One works with v-else the other one doesn't. Makes sense to me that the framework behaves like this.

@ruiposse v-show toggles a display: none on the element

<div v-if="show" :style="style"></div>
computed: {
  style () {
    if (!this.show) {
      return { display: 'none' }
    } else {
      return {}
    }
  }
}

Of course it does, that's why you use v-show to do that and you don't have a v-else along with it.

I might have not understood what @blake-newman said. I don't understand what you're trying to say, sorry... You can add a div at the end with a v-else and change the this.show on the computed property by something else. I was trying to show you how to achieve a v-if + v-show + v-else with v-else only affecting the v-if although I'm don't even know if there's a bug about that atm

What i'm trying to say is that it's been noted that trying to mimic JS logic in templates isn't generally a good idea. This is why we have dropped trying to add v-switch and v-case. If logic in templates is to exist then it should be as simple as possible.

Making v-show and v-hide work with v-else may just cause unnecessary confusion. Especially when scanning templates. You will by default try to spot a matching v-if to the v-else as it makes contextual sense.

This is achievable in user land by a simple negate, i'd avoid adding more to Vue than is necessary. Expression logic in templates should be simple, so it should be just as simple to adding ! to the expression. If any expression is complex then it really should be handled in the JS.

We're not mimicking js logic here, otherwise there should be no v-if nor v-show.

Making v-show and v-hide work with v-else ...

v-hide doesn't exist so I'm not sure what's your point there. v-else is already supposed to work with v-show but it doesn't work with components, that's the bug.

A simple negate duplicates the expression in multiple places which isn't good.

We cannot drop v-else support.

Also I don't understand what happened with @ruiposse , I really think you misunderstood what I was talking about: I am not talking about supporting v-show alongside v-if. And then @blake-newman brought the "v-else should not be used with v-show" subject. Can you both of you explain very shortly what are you trying to say and if it has anything to deal with the original bug, please?

<template>
  <my-component v-show="showMy"></my-component>
  <h1 v-show="!showMy">{{ msg }}</h1>
  <button v-on:click="toggle">Toggle</button>
</template> 

v-else is a conditional statement styled directive. ifand else are programmatically bound to each other in languages. v-show on the other hand has no relevance to any language. Expectations when looking at a template with v-else and v-show could be misleading.

It seems like an anti pattern to extend v-else to work with v-show. No real need as you can achieve easily with negating the expression, which in my view is alot more declarative.

Implementing this as suggested will complicate the internals of Vue to deal with such use case, which is fully achievable in user land.

MDN if else spec: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/if...else

In the original bug, looking at the webpackbin you provided, you're expecting v-else to work with v-show. I don't think this is something that the framework should support.

@blake-newman is literally saying the same thing!

In my opinion v-else shouldn't work with v-show, that's it.
I don't really know how to be much more clear than this.

In the original bug, looking at the webpackbin you provided, you're expecting v-else to work with v-show. I don't think this is something that the framework should support.

We cannot introduce such a breaking change in 1.1

After reading through the discussion, I'm inclined to agree that v-else should not work with v-show in the first place. That's going to be the case in 2.0 and this is going to be a wontfix for 1.x since the workaround is trivial.

At least fix the document.

@Centaur I'm doing that this evening. Thanks for reminding it. No need to be salty 😛

Was this page helpful?
0 / 5 - 0 ratings