Vue.js 37 🟢 Dynamic Slot Names
A slot name is usually a fixed string. The <slot name="header" /> in the child matches the <template #header> in the parent, and the name is the same in both places. But the name is not always known at the time the template is written. A table component renders the columns from the data, and the parent wants to provide the custom cell for the specific column. A layout component renders the regions from the configuration, and the parent wants to fill the region by the runtime name. A form renders the fields from the schema, and the parent wants to control the rendering of each field. The dynamic slot names solve the problem: the name is the JavaScript expression, and the parent targets the slot with the #[dynamicName] syntax.
The dynamic name is the expression in the brackets. The <template #[slotName]> is the parent’s usage, and the slotName is the parent’s data. The <slot :name="dynamicName" /> is the child’s usage, and the dynamicName is the child’s data. The two must evaluate to the same string for the slot to match. The expression is evaluated in the scope where it appears: the parent’s expression in the parent’s scope, and the child’s expression in the child’s scope. The two scopes are separate, and the string is the contract between them.
The dynamic name has the several rules. The v-slot directive with the dynamic argument is the v-slot:[expression], and the shorthand is the #[expression]. The expression must be the valid JavaScript, and the result must be the string. The directive argument is the dynamic, which is the Vue feature that allows the directive arguments to be the expressions. The v-bind:[attr] and the v-on:[event] are the other dynamic arguments, and the v-slot:[name] is the same mechanism for the slots.
This chapter covers three areas. First, why the dynamic slot names exist — the runtime-name problem and the data-driven rendering. Second, the syntax — the #[expression] in the parent, the :name="expression" in the child, and the scope of the expression. Third, the patterns and the pitfalls — the table columns, the form fields, the layout regions, the v-for with the dynamic names, and the reactivity of the names. The chapter ends with a complete example session, a quick reference, best practices, common pitfalls, real-world examples, and diagrams showing the dynamic slot flow.
Key point: A dynamic slot name is the slot name that is the JavaScript expression, not the fixed string. The parent uses the #[expression] syntax, and the child uses the :name="expression" syntax. The expression is evaluated in the scope where it appears, and the result must be the string. The dynamic name composes with the scoped slot props and the v-for, and it enables the data-driven rendering where the component and the parent agree on the names at the runtime.
Why the dynamic slot names exist
The runtime-name problem. The slot names are the fixed strings in the template. The <template #header> is the header slot, and the <template #footer> is the footer slot. But the component sometimes needs the slots that are not known until the runtime. The table component renders the columns from the columns prop, and the column names are the runtime data. The parent wants to provide the custom cell for the column named status, and the name is the data. The dynamic name lets the parent write the #[column.key] and the child write the :name="column.key", and the two match at the runtime.
The data-driven problem. The component renders the list from the data, and the parent wants to customize each item. The list component renders the ten items, and the parent wants the different rendering for the different types. The dynamic name lets the parent target the slot by the item type: the #[item-${item.type}] and the :name="item-${item.type}". The child and the parent agree on the naming convention, and the parent provides the different rendering for each type.
The configuration problem. The layout component renders the regions from the configuration, and the parent fills the region by the configured name. The regions are the data — the regions: ['header', 'main', 'sidebar', 'footer'] — and the parent wants to fill each region. The dynamic name lets the parent iterate the regions and provide the content for each.
The convention problem. The dynamic name is the string, and the component and the parent must agree on the convention. The slot-${type} is the convention, and the both sides use the same template literal. The convention is the contract, and the documentation is the requirement.
The expression-scope problem. The expression is evaluated in the scope where it appears. The parent’s expression is in the parent’s scope, and the child’s expression is in the child’s scope. The #[slotName] uses the parent’s slotName, and the :name="dynamicName" uses the child’s dynamicName. The two are the separate variables, and the string is the common value.
The trade-off. The dynamic name adds the indirection: the name is not the literal, and the reader must trace the expression. The wrong expression is the silent undefined slot, and the debugging is the harder. The trade-off is between the flexibility of the runtime names and the explicitness of the static names.
a. The dynamic slot name syntax
The parent uses the #[expression] syntax:
<template>
<MyComponent>
<template #[slotName]>
<p>Dynamic content</p>
</template>
</MyComponent>
</template>
<script setup>
import { ref } from 'vue';
const slotName = ref('header');
</script>
The #[slotName] targets the slot named by the slotName value. When the slotName is the 'header', the content fills the header slot. When the slotName is the 'footer', the content fills the footer slot.
The v-slot long form is the same:
<template v-slot:[slotName]>
<p>Dynamic content</p>
</template>
The child uses the :name binding:
<template>
<div>
<slot :name="dynamicName" />
</div>
</template>
<script setup>
import { computed } from 'vue';
const props = defineProps({ type: String });
const dynamicName = computed(() => `slot-${props.type}`);
</script>
The :name is the dynamic, and the slot name is the slot-${type} value. The parent must use the same expression:
<template>
<MyComponent :type="'error'">
<template #[`slot-${'error'}`]>
<p>Error content</p>
</template>
</MyComponent>
</template>
The parent’s #[slot-${‘error’}] and the child’s :name="slot-${type}" evaluate to the same slot-error, and the slot matches.
The v-for with the dynamic names. The parent can iterate the names and provide the content for each:
<template>
<MyComponent>
<template
v-for="name in slotNames"
#[name]
:key="name"
>
<p>{{ name }} content</p>
</template>
</MyComponent>
</template>
<script setup>
const slotNames = ['header', 'main', 'footer'];
</script>
The v-for iterates the names, and the #[name] targets the slot for each. The :key is the requirement for the list rendering.
The scoped dynamic slot. The dynamic name composes with the scoped props:
<template>
<DataTable :rows="rows" :columns="columns">
<template
v-for="col in columns"
#[`cell-${col.key}`]="{ row, value }"
:key="col.key"
>
<span>{{ value }}</span>
</template>
</DataTable>
</template>
The #[cell-${col.key}] targets the slot named cell-status, the cell-name, and the others. The child renders the slot with the matching name:
<template>
<td v-for="col in columns" :key="col.key">
<slot :name="`cell-${col.key}`" :row="row" :value="row[col.key]">
{{ row[col.key] }}
</slot>
</td>
</template>
The :name="cell-${col.key}" matches the parent’s #[cell-${col.key}].
b. The patterns
The table columns. The table component renders the columns, and the parent provides the custom cell for the specific column.
<!-- DataTable.vue -->
<script setup>
defineProps({ rows: Array, columns: Array });
</script>
<template>
<table>
<tbody>
<tr v-for="row in rows" :key="row.id">
<td v-for="col in columns" :key="col.key">
<slot
:name="`cell-${col.key}`"
:row="row"
:value="row[col.key]"
:column="col"
>
{{ row[col.key] }}
</slot>
</td>
</tr>
</tbody>
</table>
</template>
The parent fills the specific columns:
<template>
<DataTable :rows="rows" :columns="columns">
<template #[`cell-status`]="{ value }">
<StatusBadge :status="value" />
</template>
<template #[`cell-actions`]="{ row }">
<button @click="edit(row)">Edit</button>
<button @click="remove(row)">Delete</button>
</template>
</DataTable>
</template>
The cell-status and the cell-actions slots are the specific columns, and the other columns use the fallback.
The form fields. The form component renders the fields from the schema, and the parent provides the custom field rendering.
<!-- DynamicForm.vue -->
<script setup>
defineProps({ fields: Array });
</script>
<template>
<form>
<div v-for="field in fields" :key="field.name">
<label>{{ field.label }}</label>
<slot :name="`field-${field.name}`" :field="field">
<input
:type="field.type"
:name="field.name"
v-model="field.value"
/>
</slot>
</div>
</form>
</template>
The parent fills the specific fields:
<template>
<DynamicForm :fields="fields">
<template #[`field-email`]="{ field }">
<input type="email" :name="field.name" v-model="field.value" />
<span v-if="field.error">{{ field.error }}</span>
</template>
</DynamicForm>
</template>
The layout regions. The layout component renders the regions, and the parent fills each.
<!-- Layout.vue -->
<script setup>
defineProps({ regions: Array });
</script>
<template>
<div class="layout">
<slot
v-for="region in regions"
:key="region"
:name="`region-${region}`"
/>
</div>
</template>
The parent fills the regions:
<template>
<Layout :regions="['header', 'main', 'footer']">
<template #[`region-header`]>
<Nav />
</template>
<template #[`region-main`]>
<Article />
</template>
<template #[`region-footer`]>
<Footer />
</template>
</Layout>
</template>
The notification types. The component renders the notification, and the parent provides the different rendering for the different types.
<!-- Notification.vue -->
<script setup>
defineProps({ type: String, message: String });
</script>
<template>
<div :class="`notification-${type}`">
<slot :name="`notification-${type}`" :message="message">
{{ message }}
</slot>
</div>
</template>
The parent fills the specific types:
<template>
<Notification type="error" message="Something went wrong">
<template #[`notification-error`]="{ message }">
<strong>Error:</strong> {{ message }}
</template>
</Notification>
</template>
c. The pitfalls
The expression-scope pitfall. The parent’s expression and the child’s expression are evaluated in the separate scopes.
<!-- ❌ The wrong -->
<!-- The child -->
<script setup>
const type = 'error';
</script>
<slot :name="type" />
<!-- The parent -->
<template>
<Child>
<template #[type]>...</template> <!-- the parent's type, not the child's -->
</Child>
</template>
The type in the parent is the parent’s variable, and the type in the child is the child’s. They do not share, and the strings must match.
The reactivity pitfall. The dynamic name is reactive, and the slot content can change when the name changes.
<script setup>
const currentTab = ref('tab1');
</script>
<template>
<Tabs>
<template #[currentTab]>
<TabContent :tab="currentTab" />
</template>
</Tabs>
</template>
The currentTab is the reactive, and the slot content changes when the currentTab changes.
The v-for with the dynamic names. The v-for with the dynamic slot name needs the :key:
<template
v-for="name in names"
#[name]
:key="name"
>
The :key is the requirement, and the missing :key causes the warning.
The empty name pitfall. The dynamic name that evaluates to the empty string is the warning.
<!-- ❌ The empty name -->
<template #['']>
<p>Content</p>
</template>
The slot name must be the non-empty string, and the empty name is the invalid.
The wrong type pitfall. The dynamic name must be the string.
<!-- ❌ The wrong type -->
<script setup>
const slotName = ref(123);
</script>
<template>
<Child>
<template #[slotName]>...</template>
</Child>
</template>
The number is the coerced to the string '123', and the slot name is the '123'. The better is the explicit string.
Complete Example Session
<!-- ============================================
PART 1: THE BASIC DYNAMIC NAME
============================================ -->
<!-- MyComponent.vue -->
<template>
<div>
<slot name="header" />
<slot name="main" />
<slot name="footer" />
</div>
</template>
<!-- The parent -->
<script setup>
import { ref } from 'vue';
const slotName = ref('header');
</script>
<template>
<MyComponent>
<template #[slotName]>
<p>Dynamic content</p>
</template>
</MyComponent>
</template>
<!-- ============================================
PART 2: THE CHILD'S DYNAMIC NAME
============================================ -->
<!-- DynamicSlot.vue -->
<script setup>
defineProps({ type: String });
</script>
<template>
<div>
<slot :name="`slot-${type}`" />
</div>
</template>
<!-- The parent -->
<template>
<DynamicSlot type="error">
<template #[`slot-error`]>
<p>Error content</p>
</template>
</DynamicSlot>
</template>
<!-- ============================================
PART 3: THE v-for WITH THE DYNAMIC NAMES
============================================ -->
<template>
<MyComponent>
<template
v-for="name in ['header', 'main', 'footer']"
#[name]
:key="name"
>
<p>{{ name }} content</p>
</template>
</MyComponent>
</template>
<!-- ============================================
PART 4: THE SCOPED DYNAMIC SLOT
============================================ -->
<template>
<DataTable :rows="rows" :columns="columns">
<template
v-for="col in columns"
#[`cell-${col.key}`]="{ row, value }"
:key="col.key"
>
<span>{{ value }}</span>
</template>
</DataTable>
</template>
<!-- ============================================
PART 5: THE TABLE COLUMNS
============================================ -->
<!-- DataTable.vue -->
<script setup>
defineProps({ rows: Array, columns: Array });
</script>
<template>
<table>
<tbody>
<tr v-for="row in rows" :key="row.id">
<td v-for="col in columns" :key="col.key">
<slot
:name="`cell-${col.key}`"
:row="row"
:value="row[col.key]"
:column="col"
>
{{ row[col.key] }}
</slot>
</td>
</tr>
</tbody>
</table>
</template>
<!-- ============================================
PART 6: THE FORM FIELDS
============================================ -->
<!-- DynamicForm.vue -->
<script setup>
defineProps({ fields: Array });
</script>
<template>
<form>
<div v-for="field in fields" :key="field.name">
<label>{{ field.label }}</label>
<slot :name="`field-${field.name}`" :field="field">
<input :type="field.type" v-model="field.value" />
</slot>
</div>
</form>
</template>
<!-- ============================================
PART 7: THE LAYOUT REGIONS
============================================ -->
<!-- Layout.vue -->
<script setup>
defineProps({ regions: Array });
</script>
<template>
<div class="layout">
<slot
v-for="region in regions"
:key="region"
:name="`region-${region}`"
/>
</div>
</template>
<!-- ============================================
PART 8: THE REACTIVITY
============================================ -->
<script setup>
import { ref, computed } from 'vue';
const currentTab = ref('tab1');
const slotName = computed(() => `tab-${currentTab.value}`);
</script>
<template>
<Tabs>
<template #[slotName]>
<TabContent :tab="currentTab" />
</template>
</Tabs>
</template>
<!-- ============================================
PART 9: THE EXPRESSION SCOPE PITFALL
============================================ -->
<!-- ❌ The wrong -->
<!-- The parent's type and the child's type are separate. -->
<Child>
<template #[type]>...</template>
</Child>
<!-- ✅ The correct -->
<!-- Both sides use the same string. -->
<Child :type="type">
<template #[`slot-${type}`]>...</template>
</Child>
<!-- ============================================
PART 10: THE COMPLETE EXAMPLE
============================================ -->
<!-- DataTable.vue -->
<script setup>
defineProps({
rows: { type: Array, required: true },
columns: { type: Array, required: true },
});
</script>
<template>
<table class="data-table">
<thead>
<tr>
<th v-for="col in columns" :key="col.key">
<slot :name="`header-${col.key}`" :column="col">
{{ col.label }}
</slot>
</th>
</tr>
</thead>
<tbody>
<tr v-for="row in rows" :key="row.id">
<td v-for="col in columns" :key="col.key">
<slot
:name="`cell-${col.key}`"
:row="row"
:column="col"
:value="row[col.key]"
>
{{ row[col.key] }}
</slot>
</td>
</tr>
</tbody>
</table>
</template>
<!-- The parent -->
<script setup>
import { ref } from 'vue';
const rows = ref([
{ id: 1, name: 'Alice', status: 'active' },
{ id: 2, name: 'Bob', status: 'inactive' },
]);
const columns = ref([
{ key: 'name', label: 'Name' },
{ key: 'status', label: 'Status' },
{ key: 'actions', label: 'Actions' },
]);
</script>
<template>
<DataTable :rows="rows" :columns="columns">
<template #[`header-status`]="{ column }">
<strong>{{ column.label }}</strong>
</template>
<template #[`cell-status`]="{ value }">
<StatusBadge :status="value" />
</template>
<template #[`cell-actions`]="{ row }">
<button @click="edit(row)">Edit</button>
<button @click="remove(row)">Delete</button>
</template>
</DataTable>
</template>
The ten parts show the basic dynamic name, the child’s dynamic name, the v-for with the dynamic names, the scoped dynamic slot, the table columns, the form fields, the layout regions, the reactivity, the expression scope pitfall, and the complete example.
Quick Reference
The Syntax
| The side | The syntax |
|---|---|
| The parent | #[expression] |
| The parent (the long form) | v-slot:[expression] |
| The child | :name="expression" |
| The child (the static) | name="literal" |
The Expression
| The expression | The result |
|---|---|
#[slotName] | The slotName value |
#[slot-${type}] | The template literal |
#[name] in the v-for | The loop variable |
#[currentTab] | The reactive value |
The Common Patterns
| The pattern | The child | The parent |
|---|---|---|
| The table | :name="cell-${col.key}" | #[cell-${col.key}] |
| The form | :name="field-${field.name}" | #[field-${field.name}] |
| The layout | :name="region-${region}" | #[region-${region}] |
| The notification | :name="notification-${type}" | #[notification-${type}] |
The v-for Requirements
| The requirement | The why |
|---|---|
The :key | The list rendering |
The #[name] | The dynamic name |
The v-for | The iteration |
The Pitfalls
| The pitfall | The fix |
|---|---|
| The expression scope | Use the same string on both sides |
| The empty name | Use the non-empty string |
| The wrong type | Use the string |
The missing :key | Add the :key |
Best Practices
✅ Do This:
<!-- Use the #[expression] in the parent -->
<template #[slotName]>...</template> // ✅
<!-- Use the :name="expression" in the child -->
<slot :name="`slot-${type}`" /> // ✅
<!-- Use the v-for with the :key -->
<template v-for="name in names" #[name] :key="name">...</template> // ✅
<!-- Use the template literal for the convention -->
#[`cell-${col.key}`] // ✅
<!-- Use the computed for the reactive name -->
const slotName = computed(() => `tab-${currentTab.value}`); // ✅
<!-- Use the same string on both sides -->
<!-- The child: :name="`cell-${col.key}`" -->
<!-- The parent: #[`cell-${col.key}`] --> // ✅
❌ Don’t Do This:
<!-- Don't use the child's variable in the parent's expression -->
<template #[childType]>...</template> // the parent's scope // ❌
<!-- Don't use the empty string -->
<template #['']>...</template> // the invalid // ❌
<!-- Don't forget the :key in the v-for -->
<template v-for="name in names" #[name]>...</template> // the missing key // ❌
<!-- Don't use the number as the name -->
const slotName = ref(123); // the coerced to '123' // ❌
<!-- Don't mix the convention -->
<!-- The child: :name="`cell-${col.key}`" -->
<!-- The parent: #[col.key] // the missing prefix --> // ❌
<!-- Don't use the dynamic name when the static works -->
<template #[`header`]>...</template> // the use #header // ✅
Common Pitfalls
| The pitfall | The why | The fix |
|---|---|---|
| The slot is not filled | The name mismatch | Check the string on both sides |
| The undefined slot | The wrong expression | Check the scope |
| The empty name | The empty string | Use the non-empty |
The missing :key | The v-for | Add the :key |
| The reactivity lost | The wrong binding | Use the computed |
| The child’s variable in the parent | The scope | Use the parent’s variable |
Real-World Examples
1. The Basic Dynamic
<template #[slotName]>...</template>
2. The Child’s Dynamic
<slot :name="`slot-${type}`" />
3. The Table Cell
<template #[`cell-${col.key}`]="{ value }">{{ value }}</template>
4. The Form Field
<template #[`field-${field.name}`]="{ field }">...</template>
5. The Layout Region
<template #[`region-${region}`]>...</template>
6. The v-for
<template v-for="name in names" #[name] :key="name">...</template>
7. The Reactive Name
const slotName = computed(() => `tab-${currentTab.value}`);
8. The Scoped Dynamic
<template #[`cell-${col.key}`]="{ row, value }">...</template>
9. The Convention
<!-- Both sides use the same template literal -->
10. The Complete
<DataTable :rows="rows" :columns="columns">
<template #[`cell-status`]="{ value }">
<StatusBadge :status="value" />
</template>
</DataTable>
Visual
The Dynamic Slot Flow
┌──────────────────────────────────────────────────────────────┐
│ THE DYNAMIC SLOT FLOW │
│ │
│ The child: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ <td v-for="col in columns"> │ │
│ │ <slot :name="`cell-${col.key}`" :value="..." /> │ │
│ │ </td> │ │
│ │ │ │
│ │ The child renders the slot named cell-name, │ │
│ │ cell-status, cell-actions, ... │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ │ the dynamic names │
│ ▼ │
│ The parent: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ <DataTable> │ │
│ │ <template #[`cell-status`]="{ value }"> │ │
│ │ <StatusBadge :status="value" /> │ │
│ │ </template> │ │
│ │ </DataTable> │ │
│ │ │ │
│ │ The parent fills the cell-status slot. │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
The Expression Scope
┌──────────────────────────────────────────────────────────────┐
│ THE EXPRESSION SCOPE │
│ │
│ The child's scope: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ <script setup> │ │
│ │ const type = 'error'; │ │
│ │ </script> │ │
│ │ │ │
│ │ <slot :name="`slot-${type}`" /> │ │
│ │ → the 'slot-error' │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ The parent's scope: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ <script setup> │ │
│ │ const type = 'error'; // the PARENT's variable │ │
│ │ </script> │ │
│ │ │ │
│ │ <Child> │ │
│ │ <template #[`slot-${type}`]>...</template> │ │
│ │ → the 'slot-error' │ │
│ │ </Child> │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ The two variables are the separate. The strings must │
│ match, but the variables do not. │
│ │
└──────────────────────────────────────────────────────────────┘
The v-for with the Dynamic Names
┌──────────────────────────────────────────────────────────────┐
│ THE v-for WITH THE DYNAMIC NAMES │
│ │
│ <template> │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ <MyComponent> │ │
│ │ <template │ │
│ │ v-for="name in ['header', 'main', 'footer']" │ │
│ │ #[name] │ │
│ │ :key="name" │ │
│ │ > │ │
│ │ <p>{{ name }} content</p> │ │
│ │ </template> │ │
│ │ </MyComponent> │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ The v-for iterates the names, and the #[name] targets │
│ the slot for each. The :key is the requirement. │
│ │
└──────────────────────────────────────────────────────────────┘
The Table Columns
┌──────────────────────────────────────────────────────────────┐
│ THE TABLE COLUMNS │
│ │
│ The child: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ <td v-for="col in columns"> │ │
│ │ <slot :name="`cell-${col.key}`" :value="..."> │ │
│ │ {{ row[col.key] }} ← the fallback │ │
│ │ </slot> │ │
│ │ </td> │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ The parent: │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ <template #[`cell-status`]="{ value }"> │ │
│ │ <StatusBadge :status="value" /> │ │
│ │ </template> │ │
│ │ │ │
│ │ <template #[`cell-actions`]="{ row }"> │ │
│ │ <button @click="edit(row)">Edit</button> │ │
│ │ </template> │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ The parent fills the specific columns, and the others │
│ use the fallback. │
│ │
└──────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| The dynamic name | The slot name that is the expression |
| The parent | #[expression] |
| The parent (the long) | v-slot:[expression] |
| The child | :name="expression" |
| The scope | The expression in the local scope |
| The string | The contract between the two |
The v-for | The :key is the requirement |
| The reactive | The computed for the changing names |
Key takeaways:
- A dynamic slot name is the slot name that is the JavaScript expression, not the fixed string. The parent uses the
#[expression]syntax, and the child uses the:name="expression"syntax. The two must evaluate to the same string. - The expression is evaluated in the scope where it appears. The parent’s expression is in the parent’s scope, and the child’s expression is in the child’s scope. The variables are the separate, and the string is the contract.
- The dynamic name composes with the scoped slot props. The
#[cell-${col.key}]="{ value }"combines the dynamic name and the scoped props. - The
v-forwith the dynamic names needs the:key. Thev-for="name in names" #[name] :key="name"iterates the names and targets the slot for each. - The dynamic name is reactive. The
computedprovides the changing name, and the slot content updates when the name changes. - The convention is the contract. The child and the parent must agree on the naming convention. The
slot-${type}is the convention, and the both sides use the same template literal. - The static names are the simpler. The dynamic name is for the runtime names, and the static is for the known. The static is the explicit and the debuggable.
- The result is the data-driven rendering. The component and the parent agree on the names at the runtime, and the parent provides the rendering for the specific data. The dynamic name is the foundation of the table columns, the form fields, and the layout regions.
Remember: A dynamic slot name is the slot name that is the expression. The parent uses the #[expression], and the child uses the :name="expression". The string is the contract, and the convention is the agreement. The result is the data-driven rendering, which is the foundation of the reusable table, the dynamic form, and the flexible layout.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!