I want to extend component and override its html template only, but left all logic and styles. Unfortunately I see that all styles defined in parent component was not inherited. Is there the way to use styles of the component that was extended?
P.S. This is comoponent defined in node_modules, so I can edit source code.
If you want to bleed styles down to a component. You would put this on your target component.
#Component({
encapsulation: ViewEncapsulation.None
})
Related
This question already has an answer here:
How do I create a Vue 3 custom element, including child component styles?
(1 answer)
Closed 11 months ago.
I am using Vue 3 to create some Web Components. I would like to use Single File Components and be able to nest them and deploy, but the styling is missing on the child component.
I have simplified what I am trying to do with the following example.
MDivElement.ce.vue - a div that wraps MButton
<template>
<div id="mdiv">
MDiv
<MButtonElement>MButton</MButtonElement>
</div>
</template>
<script>
import MButtonElement from "./MButtonElement.ce.vue";
export default {
components: {
MButtonElement,
},
};
</script>
<style scoped>
#mdiv {
color: blue;
}
</style>
MButtonElement.ce.vue - a simple Button
<template>
<button id="mbutton">MButton</button>
</template>
<script>
export default {};
</script>
<style scoped>
#mbutton {
color: red;
}
</style>
Example
My problem is that all the style is gone from the button when using <m-div></m-div>
Can SFC be nested (with styles) and used as Web Components?
I will compile using Vite and distribute.
Thanks!
As of April 2022 and Vue 3.2 there is open bug #4662 about this behavior, as in the question How do I create a Vue 3 custom element, including child component styles?. One of the workarounds suggested in the bug is to make sure you are consuming the custom element by name in your template rather than using Vue and import to compose your components in custom elements.
You may need to update your SFC build plugin version so that it properly understands your .ce.vue extensions as custom elements that treat their styles differently. See the SFC as Custom Element docs:
defineCustomElement also works with Vue Single-File Components (SFCs). However, with the default tooling setup, the <style> inside the SFCs will still be extracted and merged into a single CSS file during production build. When using an SFC as a custom element, it is often desirable to inject the <style> tags into the custom element's shadow root instead.
The official SFC toolings support importing SFCs in "custom element mode" (requires #vitejs/plugin-vue#^1.4.0 or vue-loader#^16.5.0). An SFC loaded in custom element mode inlines its <style> tags as strings of CSS and exposes them under the component's styles option. This will be picked up by defineCustomElement and injected into the element's shadow root when instantiated.
Finally, as another potential workaround, you can to put the <style> within the element itself in order to accommodate the Shadow DOM technique that powers Web Components, or otherwise include the styles in the defineCustomElement Vue call specific to Custom Elements.
As in the MDN web components documentation:
You can affect the nodes in the shadow DOM in exactly the same way as non-shadow nodes — for example appending children or setting attributes, styling individual nodes using element.style.foo, or adding style to the entire shadow DOM tree inside a <style> element. The difference is that none of the code inside a shadow DOM can affect anything outside it, allowing for handy encapsulation.
In contrast, Vue SFC scoping rolls up the styles into the element itself, but applies the styles to the whole document with an arbitrary data element (data-v-f3f3eg9 in the docs). Those styles are applied outside of the shadow dom, and consequently your styles set in SFC <style> tags aren't inherited inside of it.
I'm using Vue3 with the composition API. In a form-component I put ref's on each field (child-component).
For some reason the ref's of the custom components are different from ref's for Quasar components.
When I console.log a ref to a custom component I get this in DevTools:
Proxy {__v_skip: true}
(without any properties in Target)
while a ref to a Quasar components gives this :
Proxy {…}
(with all properties of the component in Target)
For this reason I can't use the ref to access properties or methods of these child components.
I have no idea what __v_skip even means.
My custom components are defined with script setup, could that be a reason?
Any idea how to fix this?
UPDATE
If I use defineExpose in the child components for the properties and methods I want to access from outside with a ref, it does work. Not really handy though, since these components have lots of props.
Seem likes currently you cannot access the custom component by ref, if your component is written by Composition API (<script setup>). But you can try the way I mention underneath.
In the Vue 3 doc, there are some lines mentioned this behavior:
An exception here is that components using <script setup> are private
by default: a parent component referencing a child component using
<script setup> won't be able to access anything unless the child
component chooses to expose a public interface using the defineExpose
macro
Read more here: Vue 3 - Ref on Component
That means if you want to access anything from the custom component, your component has to expose that information. I think it's because in Vue 3 you don't need to have root component anymore, so if you define a ref, Vue does not know what the component you want to ref to.
But...
You can try to use yourRef.value.$el, maybe it will help.
Example:
// Parent.vue
<template>
<Child ref="childRef">
</template>
<script setup lang="ts">
// Import things...
const childRef = ref<InstanceType<typeof Child> | null>(null);
onMounted(() => {
console.log(childRef.value.$el);
});
</script>
I'm trying to develop some components that will be used by our content editors in Storyblok and there's a use case where we would like to define layout properties (using Tailwind's classes) through props that will be coming from Storyblok components.
As an example,
I am passing the width prop through storyblok giving a value of w-1/2 which is a Tailwind class. As you see on the right the class is applied just fine to the element but there's no actual impact on the page. I have tried the same with many other classes (either for background or border colors or for text styling etc, tried to use Tailwind classes as props coming from Storyblok but didn't work).
My only guess is that Nuxt is a server side application and the CSS gets compiled on build time, therefore any new class binding to the DOM will not reflect the actual CSS that they represent. Is this right? If yes, is there a way to make this happen and work?
The code for the widthSetter component is as simple as that
<template>
{{blok.width}}
<div v-editable="blok" :class="[ blok.width ]">
<component
v-for="value in blok.blocks"
:key="value._uid"
:is="value.component"
:blok="value"
/>
</div>
</template>
<script lang="ts" setup>
const props = defineProps({
blok: {
type: Object,
required: true,
},
})
</script>
You need to add Complete Class Names.
As there is no w-1/2 in your code, TW won't generate the class.
You can workaround the issue by adding the class to safelist.
Doc: https://tailwindcss.com/docs/content-configuration#safelisting-classes
module.exports = {
safelist: ['w-1/2'],
//...
}
Then w-1/2 utility will be generated regardless if it shows up in your code or not.
I have a single-file vue3 component.
Its template looks like this.
<template>
<div ref="elements"></div>
</template>
I have scoped styles in the same file:
<style scoped>
.el {
color: red;
}
</style>
Now I want to add element in the script.
<script>
export default {
name: "App",
mounted() {
const div = this.$refs.elements;
const el = document.createElement("div");
el.setAttribute("class", "el");
el.innerText = "Hello World!";
div.appendChild(el);
},
};
</script>
The result shows that the element is not styled according to the class in the scoped styles.
Is there a way to apply styling to the elements added through script, while keeping styles in the scope?
After some research this seems to be an answer.
Vue scoped styling is the internal Vue feature. So, there should be a way to distinguish same class names on different components. Vue does it by adding a special id to each class name. You can find it by inspecting elements in the browser (e.g. data-v-a2c3afe).
When building a component, Vue processes its template and properly tracks only nodes you have declared for rendering there. It does not know anything it might get from somewhere. It actually makes sense and pushes you to write everything you expect to see in the template, so that it does not happen that you suddenly see something wrong in the DOM (especially if you are taking someone's code).
I have rewritten code, so that I still have scoped styles, but with no elements appending from the script and the code now allows to clearly see what is being rendered. This is probably the property of any framework - it makes you to stick to some patterns, so that everyone in the team/community knows what behavior to expect and writes more consistent code.
I am new to react native, The component looks very messy it has views, controller and styles everything in one file.
I want to organise these things in a separate file, like Write views (UI design) in separate files and styles in a separate file and want to import into components( How we do it in Angular projects)
Like this
UPDATE
#Component({
selector: 'app-outcome-ratio-popup',
templateUrl: './outcome-ratio-popup.component.html',
styleUrls: ['./outcome-ratio-popup.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class OutcomeRatioPopupComponent implements OnInit {
//i write logics here
}
in outcome-ratio-popup.component.html
<div>hello world <div> //i write view design code here
outcome-ratio-popup.component.scss
ul{
li{
margin-top: 10px; //i Write styles here
}
}
This is what i am currently following for my projects.
in root directory you can have folder 'app' which will have following structure
Edited
Suppose you have component name Header
Header
Index.js ( you can right component app logic here)
Style.js ( style for your component )
View.js ( view for your component )
I personally will not recommend above layout.
You can use following
Heder
Index.js ( you can right component app logic & view here)
Style.js ( style for your component )
Mostly in react-native we don’t kept view and logic in separate file because component file will contain very little amount of logic. And if your component is very huge you can try to break down component into small component. That will declutter your components.
if you can take look at this project and you will understand what i am trying to say