/ Gists / Function in props
On gists

Function in props

Vue.js

example.vue Raw #

// DataGrid.vue
<script setup>
const props = defineProps({
  items: {
    type: Array,
    required: true
  },
  // Render funkce pro transformaci dat nebo komplexní logiku
  cellRenderer: {
    type: Function,
    default: null
  },
  // Funkce pro custom formátování dat v buňce
  formatters: {
    type: Object,
    default: () => ({})
  }
})

const formatCell = (value, column) => {
  // Pokud existuje custom formatter pro tento sloupec, použij ho
  if (props.formatters[column]) {
    return props.formatters[column](value)
  }
  
  // Základní formátování podle typu dat
  if (value instanceof Date) {
    return value.toLocaleDateString()
  }
  if (typeof value === 'number') {
    return value.toLocaleString()
  }
  return value
}
</script>

<template>
  <div class="data-grid">
    <slot name="header" />
    
    <div class="grid-body">
      <template v-for="item in items" :key="item.id">
        <!-- Prioritně použij slot pokud existuje -->
        <slot 
          name="row" 
          :item="item"
          :format="formatCell"
        >
          <!-- Fallback na render funkci -->
          <template v-if="cellRenderer">
            {{ cellRenderer(item, formatCell) }}
          </template>
          <!-- Základní fallback -->
          <template v-else>
            <div class="grid-row">
              <div 
                v-for="(value, key) in item" 
                :key="key"
                class="grid-cell"
              >
                {{ formatCell(value, key) }}
              </div>
            </div>
          </template>
        </slot>
      </template>
    </div>

    <slot name="footer" />
  </div>
</template>

// Použití:
<script setup>
const data = [
  { 
    id: 1,
    name: 'Produkt 1',
    price: 1299.99,
    lastUpdated: new Date('2024-03-15'),
    status: 'active'
  },
  // ...
]

// Custom formátování pro specifické sloupce
const formatters = {
  price: (value) => `${value.toLocaleString()} Kč`,
  status: (value) => ({
    'active': '✅ Aktivní',
    'inactive': '❌ Neaktivní'
  }[value] || value)
}

// Komplexní transformace dat
const renderComplexRow = (item, format) => {
  const statusClass = item.status === 'active' ? 'text-green' : 'text-red'
  
  return `
    <div class="grid-row">
      <div class="font-bold">${item.name}</div>
      <div>${format(item.price, 'price')}</div>
      <div class="${statusClass}">${format(item.status, 'status')}</div>
      <div>${format(item.lastUpdated)}</div>
    </div>
  `
}
</script>

<template>
  <!-- Základní použití se slotem -->
  <DataGrid :items="data" :formatters="formatters">
    <template #row="{ item, format }">
      <div class="grid-row">
        <div>{{ item.name }}</div>
        <div>{{ format(item.price, 'price') }}</div>
        <div>{{ format(item.status, 'status') }}</div>
      </div>
    </template>
  </DataGrid>

  <!-- Použití s render funkcí pro specifické případy -->
  <DataGrid 
    :items="data"
    :formatters="formatters"
    :cell-renderer="renderComplexRow"
  />
</template>

example2.vue Raw #

// BaseList.vue
<script setup>
const props = defineProps({
  items: {
    type: Array,
    required: true
  },
  renderItem: {
    type: Function,
    required: true
  },
  filterFn: {
    type: Function,
    default: (item) => true
  },
  sortFn: {
    type: Function,
    default: (a, b) => 0
  }
})

const processedItems = computed(() => {
  return props.items
    .filter(props.filterFn)
    .sort(props.sortFn)
})
</script>

<template>
  <div class="base-list">
    <div v-for="item in processedItems" :key="item.id">
      <!-- Zde voláme předanou render funkci místo pevného templatu -->
      {{ renderItem(item) }}
    </div>
  </div>
</template>

// Použití v parentovi:
<template>
  <BaseList 
    :items="users"
    :render-item="(user) => `${user.name} (${user.role})`"
    :filter-fn="(user) => user.active"
    :sort-fn="(a, b) => a.name.localeCompare(b.name)"
  />