vue.jsvuejs2

Conditionally rendering parent element, keep inner html


Is there any built-in way to go about conditionally showing a parent element?

To illustrate:

<a v-show-but-keep-inner="someCondition">
    <span>This is always rendered no matter what</span>
</a

Solution

  • I think it's a job for custom directive. I made this one as a quick POC:

    Vue.directive('showButKeepInner', {
      bind(el, bindings) {
        bindings.def.wrap = function(el) {
          // Find all next siblings with data-moved and move back into el
          while (el.nextElementSibling && el.nextElementSibling.dataset.moved) {
            el.appendChild(el.nextElementSibling).removeAttribute('data-moved')
          }
          el.hidden = false
        }
    
        bindings.def.unwrap = function(el) {
          // Move all children of el outside and mark them with data-moved attr
          Array.from(el.children).forEach(child => {
            el.insertAdjacentElement('afterend', child).setAttribute('data-moved', true)
          })
          el.hidden = true
        }
      },
    
      inserted(el, bindings) {
        bindings.def[bindings.value ? 'wrap' : 'unwrap'](el)
      },
    
      update(el, bindings) {
        bindings.def[bindings.value ? 'wrap' : 'unwrap'](el)
      }
    })
    
    new Vue({
      el: '#app',
      data: {
        someCondition: false
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
    
    <div id="app">
      <p>
        <button v-on:click="someCondition = !someCondition">{{ someCondition }}</button>
      </p>
      <a v-show-but-keep-inner="someCondition" href="/">
        <span>This is always rendered no matter what</span>
      </a>
    </div>