Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

secondman's avatar

Text and HTML in Slots Kills Component

I have created some reusable Modal components moving our app away from jQuery and Bootstrap.

I patterned these components after the components in Laravel Jetstream (Inertia) stack.

First I have a top level DialogContainer which houses the transitions and backdrop and then a generic slot. This top level component is also wrapped in a call to portal-vue so that all my modals are sent to the dialog-helper.

For brevity I'll remove all the Tailwind classes which are straight from TailwindUI.

<template>
  <portal to="dialog-helper">
    <Transition attrs>
      ...
      <div v-show="show" class="classes">
        <slot v-if="show" />
      </div>
    </Transition>
  </portal>
</template>

Next I have several different types of Dialogs, a Fullscreen, Footed, Confirm, Plain Panel etc. These all have named slots for different sections, and are wrapped with the DialogContainer

Confirm Dialog

<template>
  <DialogContainer :show="show" :max-width="maxWidth" :closeable="closeable" @close="closeDialog">
    ...
    <h3 class="classes">
      <slot name="title" />
    </h3>
    ...
    <div class="classes">
      <slot name="content" />
    </div>
    ...
    <div class="classes">
      <CancelButton />
      <ConfirmButton />
    </div>
    ...
  </DialogContainer>
</template>

Then when I want to use the confirm dialog in a template:

<ConfirmDialog :show="isOpen" @close="isOpen = false" @confirmed="someMethod">
  <template #title>Are You Sure You Want to Delete This Item?</template>
  <template #content>Deleting this will cause a complete nuclear meltdown, this isn't reversable!</template> // this works

  <template #content>
    <div class="row">
      <div class="form-group col-md-12" :class="{ 'has-error': validation.max }">
        <label class="control-label">Maximum Percentage</label>
        <input class="form-control" v-model="form.max" placeholder="Maximum ..." type="number" />
        <span class="help-block" v-if="validation.max">
          {{ validation.max[0] }}
        </span>
      </div>
    </div>
  </template> // This works fine, no problems.

  <template #content>
    <div class="alert alert-warning">
      Romantic notes required for Christmas will get auto-populated on the document when rendered.
    </div>
  </template> // won't open and gives no error in console

  <template #content>
    <WarningAlert> // even wrapped in a component ... 
      <p>Romantic notes required for Christmas will get auto-populated on the document when rendered.</p>
    </WarningAlert>
  </template> // NOPE, this doesn't work either.
</ConfirmDialog>

Can anyone tell me what I'm doing wrong, this exact strategy works in Jetstream, but something isn't working for me here.

0 likes
0 replies

Please or to participate in this conversation.