# Slot

Una volta completata la fase di configurazione, se si vuole dare ulteriore personalizzazione alle nostre pagine si possono utilizzare gli slot (opens new window)

Vediamoli nel dettaglio.

TIP

Lo slot viene inizializzato all'interno del componente con la sintassi <template #nome-slot="props"></template>

Se non ti servono le variabili nello slot basta fare semplicemente <template #nome-slot></template>

Nel file data.js per definire un componente custom nella sidebar bisognerà utilizzare la seguente sintassi

Slot Descrizione
[key] Inserendo il nome della chiave messo nel data.js è possibile usare un componente custom
const SIDEBAR_DATA = [
  {
    key: 'custom-filter', // il nome deve essere univoco
    componentType: 'custom',
  },
  {
    key: 'custom-filter-2', // il nome deve essere univoco
    componentType: 'custom',
  }
]

Il filtro custom andrà importato nel file CommonFilters.vue nel seguente modo

<template>
  <ThuxCommonFilterComponent
   :use-common-filters="useCommonFilters"
   :fields="fields"
  >
    <template #custom-filter>
     <ComponenteCustom /> <!-- qui andrà il componente custom -->
    </template>
    <template #custom-filter-2>
     <ComponenteCustom2 /> <!-- qui andrà il componente custom -->
    </template>
  </ThuxCommonFilterComponent>
</template>

# List

Il componente Lista ha diversi slot con cui personalizzarlo:

TIP

Lo slot viene inizializzato all'interno del componente con la sintassi <template #nome-slot="props"></template>

Se non ti servono le variabili nello slot basta fare semplicemente <template #nome-slot></template>

I principali sono:

Slot Descrizione
header Il contenuto dell'header della pagina
advanced-search Cosa si apre al click del pulsante della ricerca avanzata
detail Cosa si apre al click del pulsante dettaglio
edit Cosa si apre al click del pulsante modifica
body Il corpo principale della pagina, se non si vuole per esempio usare la tabella ma qualcos'altro
table Definizione del componente tabella
sidebar Il contenuto della Sidebar

Ci sono slot specifici anche per la sezione dell'Header della pagina

Slot Descrizione
header-components-top Eventuali componenti da mostrare sopra la pagina
header-components-bottom Eventuali componenti da mostrare sotto il titolo della pagina
header-title Il titolo della pagina personalizzato
header-actions pulsanti da mostrare a destra del titolo (di default sono la ricerca avanzata, pulsante che apre la sidebar e l'aggiungi)
other-header-actions-left Se si vogliono aggiungere altri pulsanti a sinistra oltre a quelli di default
other-header-actions-right Se si vogliono aggiungere altri pulsanti a destra oltre a quelli di default

Ci sono slot specifici per la Lista

Slot Descrizione
header-primary Cosa mostrare sopra la tabella (di default ci sono le azioni)
other-headers-buttons Se si vogliono aggiungere altri componenti a destra dell'header
footer cosa mostrare sotto la tabella (di default c'è la paginazione)
<template>
  <ThuxListGenericComponent
    v-bind="{ ...$attrs }"
    :use-list="useList"
    :use-advanced-search="useAdvancedSearch"
    :reset="reset"
    :use-action-select="useActionSelect"
    :use-pagination="usePagination"
  >
    <template #edit>
      <Edit
        v-if="useList.showEditForm.value"
        :id="useList.componentId"
        @close-form="useList.closeForm"
      />
    </template>
    <template #table>
      <Table
        :list="list"
        @open-edit-form="useList.openEditForm"
        @open-detail-form="useList.openDetailForm"
      />
    </template>
    <template #sidebar>
      <CommonFilters />
    </template>
  </ThuxListGenericComponent>
  <router-view />
</template>

Di seguito alcuni esempi del funzionamento dei vari slot:

# Esempi principali

header

An image

<template #header>
  <div class="row">
    <h3 class="q-mr-md">Header personalizzato</h3>
    <q-btn color="primary">Pulsante di test</q-btn>
  </div>
</template>
advanced-search

An image

<template #advanced-search>
  <div v-show="useAdvancedSearch.showAdvancedSearch.value" class="row">
    <q-input class="q-mr-md" model-value="">Advanced search personalizzato</q-input>
    <q-btn flat color="primary">Salva</q-btn>
  </div>
</template>
detail

An image

<template #detail>
  <Detail
    v-if="useList.showDetailForm.value"
    :id="useList.componentId"
    @close-form="useList.closeForm"
  />
</template>
edit

An image

<template #edit>
  <Edit
    v-if="useList.showEditForm.value"
    :id="useList.componentId"
    @close-form="useList.closeForm"
  />
</template>
body

An image

<template #body>
  <PortfolioCards v-show=cards class="q-mb-md" :cards="cards" />
  <div class="row q-col-gutter-md">
    <div class="col-12 col-md-6">
      <DonutApexChart
        v-if="Array.isArray(list) && totalAmount !== null"
        :list="list"
        :total-amount="totalAmount"
      />
    </div>
    <div class="col-12 col-md-6">
      <ProductDataApexChart
        v-for="(fund, index) in fundList"
        :colors="getFundColor(index)"
        :key="fund"
        :wallet="fund"
      />
    </div>
  </div>
</template>
table

An image

<template #table>
  <Table
    :list="list"
    @open-edit-form="useList.openEditForm"
    @open-detail-form="useList.openDetailForm"
  />
</template>
sidebar

An image

<template #sidebar>
  <TransactionsWidget />
</template>

# Esempi Header

header-components-top

An image

<template #header-components-top>
  <q-btn color="primary" class="q-mb-md q-mr-md">{{ i18n.t('Pulsante di prova') }}</q-btn>
  <q-btn color="red" class="q-mb-md ">{{ i18n.t('Pulsante di prova 2') }}</q-btn>
</template>
header-components-bottom

An image

<template #header-components-bottom>
  <q-btn color="primary" class="q-my-md q-mr-md">{{ i18n.t('Pulsante di prova') }}</q-btn>
  <q-btn color="red" class="q-my-md ">{{ i18n.t('Pulsante di prova 2') }}</q-btn>
</template>
header-title

An image

<template #header-title>
  <h4 class="text-primary">Titolo personalizzato</h4>
</template>
header-actions

An image

<template #header-actions>
  <q-btn color="primary" class="q-my-md q-mr-md">{{ i18n.t('Pulsante di prova') }}</q-btn>
  <q-btn color="red" class="q-my-md ">{{ i18n.t('Pulsante di prova 2') }}</q-btn>
</template>
other-header-actions-left

An image

<template #other-header-actions-left>
  <q-btn color="primary" class="q-my-md q-mr-md">{{ i18n.t('Pulsante di sinistra') }}</q-btn>
</template>
other-header-actions-right

An image

<template #other-header-actions-right>
  <q-btn icon="thx-info-empty" class="btn btn-primary">{{ i18n.t('Pulsante destra') }}</q-btn>
</template>

# Esempi Lista

header-primary

Spostare la paginazione sopra

An image

<template #header-primary>
  <ThuxFooterPaginationComponent
    :use-pagination="usePagination"
    :list="useList.list.value"
    :per-page="usePagination.perPage.value"
    :page="usePagination.page.value"
    @change="usePagination.changePage"
  />
</template>
other-header-buttons

An image

<template #other-header-buttons>
  <q-btn icon="thx-info-empty" class="btn btn-primary">{{ i18n.t('Pulsante prova') }}</q-btn>
</template>
footer

An image

<template #footer>
  <div class="text-right full-width q-py-md text-bold text-primary">FOOTER PERSONALIZZATO</div>
</template>

# Table

Il componente Tabella ha diversi slot con cui personalizzarlo:

TIP

Lo slot viene inizializzato all'interno del componente con la sintassi <template #nome-slot="props"></template>

Se non ti servono le variabili nello slot basta fare semplicemente <template #nome-slot></template>

<template>
  <ThuxTableComponent
    :list="list"
    :use-table="useTable"
    @open-edit-form="$emit('open-edit-form', $event)"
    @open-detail-form="$emit('open-detail-form', $event)"
  >
   <template #other-buttons-actions-left>  <!--  Utilizzo degli slot -->
      <q-btn icon="thx-info-empty" />
    </template>
  </ThuxTableComponent>
</template>

I principali sono:

props.item.[name]

Per accedere all'elemento della tabella bisogna usare props.item

An image

<template #body-cell-name="props">
  {{ props.item }}
</template>
Slot Descrizione
header-cell-[name] Il contenuto della cella dell'header avente quel [name]
body-cell-[name] Il contenuto della cella della tabella avente quel [name]
other-buttons-actions-left pulanti aggiuntivi a sinistra di quelli di default
other-buttons-actions-right pulanti aggiuntivi a destra di quelli di default
mobile-row riga completamente custom (solo per la versione mobile)

Attenzione!

Lo slot mobile-row funziona solo se nel LIST_DATA nel data.js il campo mobileGrid=true

<template>
  <ThuxTableComponent
    :list="list"
    :use-table="useTable"
    @open-edit-form="$emit('open-edit-form', $event)"
    @open-detail-form="$emit('open-detail-form', $event)"
  >
    <template #body-cell-name="props">Custom {{ props.item.name }}</template>
    <template #other-buttons-actions-left>
      <q-btn icon="thx-info-empty" />
    </template>
  </ThuxTableComponent>
</template>

# Esempi principali

header-cell-[name]

An image

<template #header-cell-name="props">
  {{ props.item }}
</template>
body-cell-[name]

An image

<template #body-cell-name="props">
  <div class="fund-table-info">
    <div v-if="props.item.image" class="fund-image mr-5">
      <img :src="props.item.image" :alt="props.item.name" />
    </div>
    <div class="fund-name">
      <span class="fw-600">{{ props.item.name }}</span>
      <span class="fund-desc">{{ props.item.description }}</span>
    </div>
  </div>
</template>

<template #body-cell-past_annual_return="props">
  <span v-if="props.item.past_annual_return" class="tag tag-orange">
    {{ props.item.past_annual_return }}% {{ i18n.t('p.a.') }}
  </span>
</template>

<template #body-cell-underlying="props">
  <span v-if="props.item.underlying">
    {{ props.item.underlying }}
  </span>
  <span v-else>
    {{ i18n.t('N.A.') }}
  </span>
</template>

<template #body-cell-term="props">
  <span v-if="props.item.maturity_date && formatDateDiff(props.item.maturity_date, 'years') > 0">
    {{ formatDateDiff(props.item.maturity_date, 'years') }}
    <span v-if="formatDateDiff(props.item.maturity_date, 'years') > 1">
      {{ i18n.t('years') }}
    </span>
    <span v-else>{{ i18n.t('year') }}</span>
  </span>
  <span v-else>-</span>
</template>

<template #body-cell-typology="props">
  <span class="text-capitalize">
    {{ props.item.typology }}
  </span>
</template>

<template #body-cell-automatic_early_redemption="props">
  <span v-if="props.item.automatic_early_redemption">
    <q-icon name="thx-check" size="16px" class="text-light-green"></q-icon>
  </span>
  <span v-else>
    <q-icon name="thx-cancel" size="16px" class="text-red"></q-icon>
  </span>
</template>
other-buttons-actions-left

An image

<template #other-buttons-actions-left>
  <q-btn icon="thx-info-empty" />
</template>
other-buttons-actions-right

An image

<template #other-buttons-actions-right="props">
  <q-btn
    class="btn btn-outline-primary btn-table-cta"
    :title="i18n.t('Select Now')"
    icon="thx-nav-arrow-right"
    @click="$emit('open-detail-form', props.item.id)"
  >
    {{ i18n.t('Select') }}
  </q-btn>
</template>
mobile-row

An image

<template #mobile-row="props">
  <div class="mobile-row fund-mobile-row">
    <div class="fund-table-info">
      <div v-if="props.item.product.image" class="fund-image mr-5">
        <img :src="props.item.product.image" :alt="props.item.name" />
      </div>
      <div class="fund-name">
        <span class="fw-600">{{ props.item.product.name }}</span>
        <span class="fund-desc">{{ props.item.product.description }}</span>
        <span class="fund-desc">{{  }}</span>
      </div>
    </div>
    <div class="fund-value">
      <span v-if="props.item.product.product_data_dict.price > 0">
        {{ formatCurrency(props.item.product.product_data_dict.price) }}
      </span>
      <ProfitOrLossBadge
        :amount="props.item.product.product_data_dict.price"
        :percent="props.item.weight * 100"
        :show-amount="false"
      />
    </div>
  </div>
</template>

# Detail

Il componente Dettaglio ha diversi slot con cui personalizzarlo

Attenzione!

Abbiamo 2 tipi di componenti:

  • ThuxDetailPageComponent - È un dettaglio inserito in una pagina nuova (di solito con un routing diverso rispetto alla lista), utile per modelli con molti campi
  • ThuxDetailComponent - È invece un form definito sopra la tabella (non ha routing diverso), utile per modelli con pochi campi

Entrambi utilizzano gli stessi slot

TIP

Lo slot viene inizializzato all'interno del componente con la sintassi <template #nome-slot="props"></template>

Se non ti servono le variabili nello slot basta fare semplicemente <template #nome-slot></template>

I principali sono:

Slot Descrizione
row-[rowKey] Inserendo il nome della chiave messo nel data.js è possibile creare una riga custom
cell-[cellKey] Inserendo il nome della chiave messo nel data.js è possibile creare una cella custom
inline-row-[rowKey] Inserendo il nome della chiave messo nel data.js è possibile creare una riga custom nell'inline row
inline-cell-[cellKey] Inserendo il nome della chiave messo nel data.js è possibile creare una cella custom nell'inline row
parent-row-[parentKey]-[rowKey] Inserendo il nome della chiave messo nel data.js nel parent e la chiave della relativa riga è possibile creare una riga custom nel componente padre
parent-cell-[parentKey]-[cellKey] Inserendo il nome della chiave messo nel data.js nel parent e la chiave della relativa cella è possibile creare una cella custom nel componente padre
inline-parent-row-[parentKey]-[rowKey] Inserendo il nome della chiave messo nel data.js nel parent e la chiave della relativa riga è possibile creare una riga custom nel componente padre dell'inline row
inline-parent-cell-[parentKey]-[cellKey] Inserendo il nome della chiave messo nel data.js nel parent e la chiave della relativa riga è possibile creare una cella custom nel componente padre nell'inline row

Ci sono slot specifici anche per la sezione dell'Header della pagina (Solo per ThuxDetailPageComponent)

Slot Descrizione
header-components-top Eventuali componenti da mostrare sopra la pagina
header-components-bottom Eventuali componenti da mostrare sotto il titolo della pagina
header-title Il titolo della pagina personalizzato
header-actions pulsanti da mostrare a destra del titolo (di default sono salva e chiudi)
other-header-actions-left Se si vogliono aggiungere altri pulsanti a sinistra oltre a quelli di default
other-header-actions-right Se si vogliono aggiungere altri pulsanti a destra oltre a quelli di default

Attenzione!

Se si vuole importare in un dettaglio una lista bisogna richiamare il componente lista passando la prop :table-only="true"

esempio

<template #row-fund-transaction-list>
  <h4 class="mb-5">{{i18n.t('Movements')}}</h4>
  <TransactionList
    v-if="useDetail.form.value.id"
    :productId="useDetail.form.value.id"
    :table-only="true"
  />
</template>

# Esempi principali

row-[rowKey]

An image

<template #row-fund-graph>
  <ProductDataApexChart v-if="productDataList" :list="productDataList" />
</template>


<template #row-fund-info>
  <FundInfo :fund="useDetail.form" class="my-10" />
</template>


<template #row-fund-transaction-list>
  <h4 class="mb-5">{{i18n.t('Movements')}}</h4>
  <TransactionList
    v-if="useDetail.form.value.id"
    :productId="useDetail.form.value.id"
    :table-only="true"
  />
</template>
cell-[cellKey]

An image

<template #cell-code>
  <q-btn flat color="primary">Pulsante custom</q-btn>
</template>
inline-row-[rowKey]

An image

<template #inline-row-custom-row>
  <q-input v-model="test" class="full-width" color="primary">riga custom</q-input>
</template>
inline-cell-[cellKey]

An image

<template #inline-cell-contractor>
  <q-input class="col-6" v-model="test" color="primary">cella custom</q-input>
</template>
parent-row-[parentKey]-[rowKey]

An image

<template #parent-row-parent_client-row_1>
  <q-input class="full-width q-mb-md" v-model="test" color="primary">riga custom</q-input>
</template>
parent-cell-[parentKey]-[cellKey]

An image

<template #parent-cell-parent_client-cell_1>
  <q-input class="col-6 q-mb-md" v-model="test" color="primary">cella custom</q-input>
</template>
inline-parent-row-[parentKey]-[rowKey]

An image

<template #inline-parent-row-parent_client-row_1>
  <q-input class="full-width q-mb-md" v-model="test" color="primary">riga inline padre custom</q-input>
</template>
inline-parent-cell-[parentKey]-[cellKey]

An image

<template #inline-parent-cell-parent_client-cell_1>
  <q-input class="col-6 q-mb-md" v-model="test" color="primary">cella inline padre custom</q-input>
</template>

# Esempi Header

header-components-top

An image

<template #header-components-top>
  <q-btn color="primary" class="q-mb-md q-mr-md">{{ i18n.t('Pulsante di prova') }}</q-btn>
  <q-btn color="red" class="q-mb-md ">{{ i18n.t('Pulsante di prova 2') }}</q-btn>
</template>
header-components-bottom

An image

<template #header-components-bottom>
  <q-btn color="primary" class="q-my-md q-mr-md">{{ 'Pulsante di prova' }}</q-btn>
  <q-btn color="red" class="q-my-md">{{ 'Pulsante di prova 2' }}</q-btn>
</template>
header-title

An image

<template #header-title>
  <h4 class="text-primary">Titolo personalizzato</h4>
</template>
header-actions

An image

<template #header-actions>
  <q-btn color="primary" class="q-my-md q-mr-md">{{ i18n.t('Pulsante di prova') }}</q-btn>
  <q-btn color="red" class="q-my-md ">{{ i18n.t('Pulsante di prova 2') }}</q-btn>
</template>
other-header-actions-left

An image

<template #other-header-actions-left>
  <q-btn color="primary" class="q-my-md q-mr-md">{{ i18n.t('Pulsante di sinistra') }}</q-btn>
</template>
other-header-actions-right

An image

<template #other-header-actions-right>
  <q-btn icon="thx-info-empty" class="btn btn-primary">{{ i18n.t('Pulsante destra') }}</q-btn>
</template>

# Esempi Dettaglio

body

An image

<template #body>
  TEST
</template>
sidebar

An image

<template #sidebar>
  <InvestWidget
    v-if="useDetail.form && useDetail.form.value.id"
    :fund="useDetail.form.value"
    :active-tab="route.params.activeTab"
  />
</template>