Home  >  Q&A  >  body text

Vue 3 action to add wrapper for each child element

I have a form component that looks like this:

<form-component>
    <text-component name="test1" />
    <select-component name="test2" />
</form-component>

I need the FormComponent to apply a wrapper div around each child

From the above code, the output of FormComponent should be like this:

<form>
    <div class="mb-3">
        <text-component name="test1" />
    </div>

    <div class="mb-3">
        <select-component name="test2" />
    </div>
</form>


P粉648469285P粉648469285290 days ago866

reply all(1)I'll reply

  • P粉415632319

    P粉4156323192024-01-03 09:29:49

    Here is a workaround:

    const formChildren = [{
      name: 'test1',
      is: TextComponent  
    }, {
      name: 'test2',
      is: SelectComponent  
    }]
    
    <form-component :children="formChildren" />
    

    FormComponent.vue

    <template>
      <form>
        <div 
          v-for="(child, index) in children"
          :key="index"
          class="mb-3"
        >
          <component v-bind="child" />
        </div>
      </form>
    </template>
    <script setup>
    defineProps(['children'])
    </script>
    

    This is a working demo as you suggested in the comments, looping over the contents of $slots.default().

    If you prefer writing your logic in template syntax, that's the right way to go, and I don't see anything wrong with that.

    I personally prefer the first approach, as my tendency is to (usually) keep template syntax to a minimum. Keeping components in an object or map structure allows me to have fine control and automate tasks such as:

    • verify
    • Activity Management
    • Apply dynamic defaults from configuration object
    • Handling browser/device exceptions

    My preference probably comes from working a lot in configuration-driven environments where business logic is typically stored in objects. There's nothing wrong with writing it in template syntax, but overall I find it limiting.

    reply
    0
  • Cancelreply