-2

What I'm trying to achieve

I'm trying to pass Component into the slot.

The question/information

How do I pass the Component into the slot so that It will be rendered? This works fine as long as I pass strings / plain html.

Additional question

If this is not possible - then how can I pass component into other component with the structure like below?

Parent

Template code

<template>
  <card-with-title card-title="Title">
    <template #card-body>
      <row-fontawesome-icon-with-text v-for="mailDto in lastProcessedEmails"/>
    </template>
  </card-with-title>
</template>

Script code - the important part

<script>
import SymfonyRoutes                     from '../../../../../core/symfony/SymfonyRoutes';
import GetLastProcessedEmailsResponseDto from '../../../../../core/dto/api/internal/GetLastProcessedEmailsResponseDto';
import MailDto                           from '../../../../../core/dto/modules/mailing/MailDto';

import CardWithTitleComponent              from '../../../../base-layout/components/cards/card-with-title';
import RowFontawesomeIconWithTextComponent from '../../../../other/row-fontawesome-icon-with-text';

export default {
  components: {
    'card-with-title'                : CardWithTitleComponent,
    'row-fontawesome-icon-with-text' : RowFontawesomeIconWithTextComponent,
  },
<...>

Child

<!-- Template -->
<template>
  <div class="col-12 col-lg-4 mb-4">
    <div class="card border-light shadow-sm">
      <div class="card-header border-bottom border-light">
        <h2 class="h5 mb-0">{{ cardTitle }}</h2>
      </div>
      <div class="card-body">
        <slot name="card-body"></slot>
        <slot></slot>
      </div>
    </div>
  </div>
</template>

<!-- Script -->
<script>
export default {
  props: [
      "cardBody",
      "cardStyle",
      "cardTitle"
  ],
}
</script>

I did research about the question, I've seen in documentation how does the named slots work like, but non of the posts / blogs entries answer / solve my Problem.

Examples of checked resources:

Volmarg Reiso
  • 437
  • 4
  • 11
  • @Volmarg Your template should work fine (see [demo](https://codesandbox.io/s/fontawesome-component-in-slot-vue-3-bg4jj?file=/src/components/CardParent.vue)). What problem are you seeing? – tony19 Dec 25 '20 at 20:09

1 Answers1

-2

I've found the solution... It's pretty much... terrifying. Vue is not checking if the array is empty, on the v-for it tries to loop over and then throws error.

Personally, from other languages / frameworks - this should not happen.

But well, this is the solution:

<!-- Template -->
<template>

  <card-with-title card-title="Title">
    <template #card-body>
      <div v-if="[lastProcessedEmails.length]">

        <row-fontawesome-icon-with-text v-for="mailDto in lastProcessedEmails">
          <template #icon>
            <i class="font-weight-bold">
              <i v-if="mailDto.status === mailStatusSent"         :class="fontawesomeIconClassesSent"></i>
              <i v-else-if="mailDto.status === mailStatusPending" :class="fontawesomeIconClassesPending"></i>
              <i v-else                                             :class="fontawesomeIconClassesError"></i>
            </i>
          </template>

          <template #title>
            {{ mailDto.subject }}
          </template>

          <template #title-context>
            {{ mailDto.created }}
          </template>
        </row-fontawesome-icon-with-text>

      </div>
    </template>
  </card-with-title>

</template>

The whole problem was that:

  data(){
    return {
      lastProcessedEmails: [],
    }
  },

The lastProcessedEmails is updated via Axios Call.

Volmarg Reiso
  • 437
  • 4
  • 11