Reputation: 1674
I am developing a custom UI component library using Svelte and each component has at least a CSS class which is the same name the component tag name. Also, I have a base component which all other components are using that. Here is the simplified codes:
Base.svelte
<script>
export let componentName
export let tag = 'div'
</script>
<svelte:element this={tag} class={componentName}>
<slot />
</svelte:element>
Foo.svelte
<script>
import Base from './Base.svelte'
</script>
<Base tag="b" componentName="Foo">
<slot />
</Base>
Bar.svelte
<script>
import Base from './Base.svelte'
</script>
<Base tag="h3" componentName="Bar">
<slot />
</Base>
App.svelte
<script>
import Foo from './Foo.svelte'
import Bar from './Bar.svelte'
</script>
<Foo>
<Bar>This is Bar 1</Bar>
<Bar>This is Bar 2</Bar>
</Foo>
<Foo>
Foo
</Foo>
In above code, I have to set the componentName
prop which actually should be a constant. Also, I should always update that in case I change the component's file name.
Is there anyway to get the current component tag name and set it in Base component?
Or, a function that returns the name similar to what we have for the component:
import { current_component } from 'svelte/internal';
Upvotes: 1
Views: 887
Reputation: 184526
You cannot get the tag name; it is not static and components can be rendered without using a tag at all via <svelte:component>
or by just using the constructor in code. There are ways to get the file name, which then could be transformed.
I would approach this via pre-processing. Svelte already provides a way to do this via its config, e.g.
// svelte.config.js
import { basename } from 'path';
/** @type {import('svelte/types/compiler/preprocess').PreprocessorGroup} */
const addComponentName = {
script: ({ content, filename }) => {
const componentName = basename(filename, '.svelte');
return {
code: `const __componentName = ${JSON.stringify(componentName)};\n`
+ content,
};
}
}
export default { preprocess: [addComponentName] };
This adds code that sets a constant __componentName
to the file name, which thus can be used in the rest of the code or the markup. You can use whatever name works for you; the underscores are there to prevent potential name collisions with the existing code.
(If you are using TypeScript you have to declare a global for this to prevent errors, as the declaration will be missing from the source files.)
Upvotes: 2