0

I create a component whose purpose is to display an arbitrary component within itself, with a changeable padding property. (The example is conditional for simplicity).

<script setup lang="ts">
defineProps<{
  innerComponent: any;
  settings: { padding: number; backgroundColor: string };
}>();
</script>

<template>
  <div
    :style="`
      padding: ${settings.padding}px;
      background-color: ${settings.backgroundColor}`"
  >
    <component :is="innerComponent" />
  </div>
</template>

Let's create a simple component for the example.

<template>
  <p style="background-color: beige">it's just a test.</p>
</template>

That's how we use it, and it works great.

<script setup lang="ts">
import ExternalComponent from "./components/ExternalComponent.vue";
import InnerComponent from "./components/InnerComponent.vue";
</script>
<template>
  <ExternalComponent
    :inner-component="InnerComponent"
    :settings="{ padding: 200, backgroundColor: 'yellow' }"
  />
</template>

I wish it all looked even more aesthetically pleasing. For example, like this.

<InnerComponent v-inner="{ padding: 200, backgroundColor: 'yellow' }" />

Let's try using custom directives.

import { createApp, h } from "vue";
import App from "./App.vue";
const app = createApp(App);

app.directive("inner", (el, binding, vnode) => {

  //Here is supposedly expected to be something like
  el.outerHTML = h("ExternalComponent", {
    innerComponent: vnode,
    settings: binding.value,
  });

  //or
  vnode = h("ExternalComponent", {
    innerComponent: vnode,
    settings: binding.value,
  });

  //But, of course, something completely different :((
});

app.mount("#app");

Unfortunately, my knowledge is not enough to solve this problem. I would be glad to get any advice on what direction to dig.

vova
  • 125
  • 8
  • This isn't what directives are for, they primarily deal with DOM and not modify vnode. You need a component. You can use a slot instead of inner-component prop – Estus Flask Feb 09 '23 at 12:22
  • I was hoping that somehow it was possible. It's just that this syntax is the most succinct. – vova Feb 09 '23 at 12:28
  • What about v-for? – vova Feb 09 '23 at 13:07
  • There may be a better syntax depending on how exactly it's supposed to work, this depends on your case. Usually components like that are something like ``. v-for, etc are not really directives but Vue built-ins, they work on their own terms. – Estus Flask Feb 09 '23 at 13:38
  • In the case of slots, the interaction logic that can be hidden must be shown as slotProps. This is why I like the – vova Feb 09 '23 at 14:36
  • 1
    The question doesn't cover it. Consider reasking about your case, the possible answers depend on that. If you want a wrapper to add props to a wrappee or modify vnode hierarchy in some other way, that's still the case, can be done in wrapper's render function, e.g. https://stackoverflow.com/questions/73387918/vue-3-wrap-all-items-within-a-slot-with-a-custom-component-by-using-a-render-fu – Estus Flask Feb 09 '23 at 17:06

0 Answers0