How to change component css with props with Nuxt Js Vue js - css

I'm new to Nuxt and Vue, thanks for being indulgent ;).
I have a "Subtitle" component that I use in another "Main" component (names are for the example).
How can I change the css of the "subtitle" component from the "Main" component ?
Here "Subtitle" component :
<template>
<div>
<h1 :class="data">{{ title }}</h1>
</div>
</template>
<script>
export default {
name: 'subtitle',
props: {
title: String,
}
}
</script>
And here my "Main" component :
<template>
<div class="container">
<Subtitle :title="title""></Subtitle>
</div>
</template>
I searched with the props etc.... But now I've been on it for a while and I'm blocking.
Thanks for your help!

You can do it using the combination of props and computed
Subtitle Component
<template>
<div>
<h1 :style="getStyle">{{ title }}</h1>
</div>
</template>
<script>
export default {
name: 'subtitle',
props: {
stylings: Object,
},
computed: {
getStyle() {
return this.stylings;
}
}
}
</script>
Main Component
<template>
<div class="container">
<Subtitle :stylings="customStyle"></Subtitle>
</div>
</template>
export default {
name: 'subtitle',
data() {
return {
customStyle: {
'font-weight': 'Bold',
}
}
}

Related

how to add Vue props value to background-image

I'm new in VueJS and I get confused to change background image from Vue props value.
I've created simple table from 'vue3-easy-data-table'.
BaseTable.vue:
<template>
<EasyDataTable>
...
</EasyDataTable>
</template>
<script setup lang="ts">
changeImg: {
type: String,
}
})
</script>
<style>
.vue3-easy-data-table__message {
background-image: url("`${v-bind("changeImg")}`");
/* background-image: var(--image-url); */
/* background-image: url('#/assets/img/noDataMultiplierOnCity.svg'); */
}
</style>
View.vue:
<template>
<BaseTable
:changeImg= "image"
/>
</template>
<script lang="ts" setup>
const image : string = "'#/assets/img/noDataMultiplierOnCity.svg'"
</script>
I've tried solution from this link https://stackoverflow.com/questions/42872002/in-vue-js-component-how-to-use-props-in-css but no gain.
Already tried as in the comments in the code, in this case I can just style the component in style tag cause the class is from 'vue3-easy-data-table' (maybe have another way to apply style to it?)
I want to make the background image from BaseTable so it can be reused in other file.
I hope I understood you right and this example will help you
template:
<div :style="styleExample" />
script:
let styleExample = { 'width': props.examplePro }
One way to solve this is to use an inline reactive style. For example you could give your script a method that convers the prop into a style, one that holds the image and any other defining features:
<template>
<EasyDataTable :style="backgroundStyles(image)">
...
</EasyDataTable>
</template>
<script setup>
changeImg: {
type: String,
}
})
const backgroundStyles = (img) => {
return {
'background-image': `url(${img})`,
'background-size': 'cover'
}
}
</script>
code:
App.vue
<script setup>
import { ref } from 'vue'
import BaseTable from './BaseTable.vue'
import BaseTable2 from './BaseTable2.vue'
const msg = ref('Hello World!')
const imageUrl = ref("https://cdn.mos.cms.futurecdn.net/SWx64q2g3wax53Xz5H4QjS-970-80.jpg.webp");
</script>
<template>
<h1>{{ msg }}</h1>
<input v-model="msg">
<BaseTable :image="imageUrl"/>
<hr>
<BaseTable2 :image="imageUrl"/>
</template>
BaseTable.vue
<template>
<div class="bkgrnd" :style="backgroundStyles(image)">
<h2>
Base Table
</h2>
<ul v-for="index in 8" :key="index">
<li>Index: {{ index }}</li>
</ul>
</div>
</template>
<script setup>
const props = defineProps(['image'])
const backgroundStyles = (img) => {
return {
'background-image': `url(${img})`,
'background-size': 'cover'
}
}
</script>
<style scoped>
.bkgrnd {
color: white;
font-style: bold;
}
</style>
Solution using the prop in the CSS
Another way to do this can be to avoid inline styles and instead display the background image in the <style> CSS code. To do this, I would use a computed property to create a URL from the prop, something like:
const computedUrl = computed(() => {
return `url(${props.image})`;
});
Code example,
BaseTable2.vue
<template>
<div class="bkgrnd">
<h2>
Base Table 2
</h2>
<ul v-for="index in 8" :key="index">
<li>Index: {{ index }}</li>
</ul>
</div>
</template>
<script setup>
import { computed } from 'vue';
const props = defineProps(['image'])
const computedUrl = computed(() => {
return `url(${props.image})`;
});
</script>
<style scoped>
.bkgrnd {
color: white;
font-style: bold;
background-image: v-bind(computedUrl);
}
</style>
Both examples can be found at the Vue SFC Playground

Children Component HTML not visible in VueJS

I have create Home Component which is imported into App.vue
App.vue
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<home></home>
</template>
<script>
import home from "./components/home.vue";
export default {
name: "App",
components: {
home
},
};
</script>
And header component is imported into Home.vue
Home.vue
<template>
<header></header>
</template>
<script>
import header from "./header.vue";
export default {
name: "home",
components: {
header: header,
},
};
</script>
Header.vue
<template>
<div class="new-component">
<h1>A New Component</h1>
<p>This is a text inside the NewComponent.</p>
</div>
</template>
<script>
export default {
name: 'header',
}
</script>
When I check in browser I don't see HTML of header.vue
Use multi word names. Your component is conflicting with HTML's default header tag.
VueHeader.vue
<template>
<div class="new-component">
<h1>A New Component</h1>
<p>This is a text inside the NewComponent.</p>
</div>
</template>
<script>
export default {
name: "vue-header",
};
</script>
Home.vue
<template>
<vue-header></vue-header>
</template>
<script>
import VueHeader from "./VueHeader.vue";
export default {
name: "home",
components: {
VueHeader,
},
};
</script>
You can find more information about this and other minor issues in here Vue style guide

same component with different background-color

I've created a component and use it multiple times on one of my vue pages.
Now I wanna change the background-color for each use of this component.
This is my component:
<template>
<div class="project-card" :style="{backgroundColor: color}">
<h2>{{ title }}</h2>
<p>{{ description }}</p>
</div>
</template>
<script>
export default {
name: 'ProjectCard',
props: {
title: String,
description: String
},
data: function() {
return {
color: "#000"
}
}
}
</script>
and this is my vue page, where I use the component:
<template>
<div class="projects">
<ProjectCard
title="Projekt 01"
description="Lorem Ipsum"
/>
<ProjectCard
title="Projekt 02"
description="Lorem Ipsum"
/>
</template>
<script>
import ProjectCard from '#/components/ProjectCard.vue'
export default {
name: 'projects',
components: {
ProjectCard
}
}
</script>
Is it now possible to change the color data of the project-card component on my projects page, like I changed the text props?
Thanks for your help!
Pass color also as a prop:
<ProjectCard
title="Projekt 02"
description="Lorem Ipsum"
color= "#000F"
/>
<ProjectCard
title="Projekt 02"
description="Lorem Ipsum"
color= "#00FF00"
/>
and in script:
<script>
export default {
name: 'ProjectCard',
props: {
title: String,
description: String,
color:String
},
data: function() {
return {
color: "#000"
}
}
}
</script>

In vue.js component, how to use props in css?

I'm new to vue.js. Here is my problem:
In a *.vue file like this:
<template>
<div id="a">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color']
}
</script>
<style scoped>
#a {
background-color: ?
}
<style>
How can I use the props color in background-color: (where is a ? now).
Thanks.
You actually can!
You should define the CSS variables in a Computed Property, then call the computed property as a style attribute to the element that will require the CSS variable, and finally you may use the variable within the tags at the bottom of your document.
new Vue({
el: '#app',
data: function() {
return {
baseFontSize: 1,
bgHoverColor: "#00cc00",
hoverContent: "Hovering!"
}
},
computed: {
cssProps() {
return {
'--hover-font-size': (this.baseFontSize * 2) + "em",
'--bg-hover-color': this.bgHoverColor,
'--hover-content': JSON.stringify(this.hoverContent)
}
}
}
})
div {
margin: 1em;
}
div.test:hover {
background-color: var(--bg-hover-color);
font-size: var(--hover-font-size);
}
div.test:hover::after {
margin-left: 1em;
content: var(--hover-content);
}
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app" :style="cssProps">
<div>Hover text: <input type="text" v-model="hoverContent"></div>
<div>Hover color: <input type="color" v-model="bgHoverColor"></div>
<div class="test">Hover over me</div>
</div>
Or have a look here: https://codepen.io/richardtallent/pen/yvpERW/
And here: https://github.com/vuejs/vue/issues/7346
You don't. You use a computed property and there you use the prop to return the style of the div, like this:
<template>
<div id="a" :style="style" #mouseover="mouseOver()">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color'],
computed: {
style () {
return 'background-color: ' + this.hovering ? this.color: 'red';
}
},
data () {
return {
hovering: false
}
},
methods: {
mouseOver () {
this.hovering = !this.hovering
}
}
}
</script>
<style scoped>
<style>
As we are in 2020 now, I suggest using this trick with a css function called var
<template>
<div id="a" :style="cssVars"></div>
</template>
<script>
export default {
props: ['color'],
computed: {
cssVars () {
return{
/* variables you want to pass to css */
'--color': this.color,
}
}
}
<script>
<style scoped>
#a{
background-color: var(--color);
}
</style>
This method is very useful because it allows you to update the passed values through css later on (for example when you apply hover event).
credit
I know we're talking vue 2 here, but in case anyone from vue 3 lands in this question (like I did), vue 3 introduced a much cleaner way to do this:
<template>
<div id="a">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color']
}
</script>
<style scoped>
#a {
background-color: v-bind(color);
}
<style>
What Vue actually does behind the scenes is the same "introducing css variables through component's style process", but it sure looks much better on the eyes now.
Documentation source: https://v3.vuejs.org/api/sfc-style.html#state-driven-dynamic-css
Why not just use :style prop in this way:
<template>
<div :style="{ backgroundColor: color }">
</template>
<script>
export default {
props: {
color: {
type: String,
default: ''
}
}
}
</script>
Make sure you define css properties in camelCase style.
If you need css that can't be applied by a style attribute like pseudo classes or media queries, what I do is the following:
Create a globally available style component when initializing Vue (you need it as otherwise you run into linting issues). It creates a style tag that simply renders the content in the slot:
I would only use this if you really need both dynamic values in your css and css features that can't be applied to a style attribute.
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
Vue.component('v-style', {
render: function(createElement) {
return createElement('style', this.$slots.default)
}
})
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
Then use it at the top of your template like this and you get the full JavaScript scope of your component and the full css syntax combined:
<template>
<v-style>
#media screen and (max-width: 820px) {
.gwi-text-media-{{ this.id }} {
background-image: url({{ mobileThumb }});
}
}
</v-style>
</template>
It seems a bit hacky to me, but it does it's job and I would rather go like this in some cases than having to add additional JS for mouse-over or resize events that have a big potential to slow down your application performance.
Vue 3 added new way of binding styles, so now you can easily bind your props to css properties.
Read source:
https://learnvue.co/2021/05/how-to-use-vue-css-variables-reactive-styles-rfc/
<template>
<div>
<div class="text">hello</div>
</div>
</template>
<script>
export default {
data() {
return {
color: 'red',
}
}
}
</script>
<style>
.text {
color: v-bind(color);
}
</style>
You could utilise the CSS var(--foo-bar) function. It is also useful if you are trying to pass an asset that has its own dynamic path, like Shopify does.
This method also works for styling the :before and :after elements as they refer back to the style applied on the owner element.
Using the original post example for passing a colour:
<template>
<div
id="a"
:style="{ '--colour': color }">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color']
}
</script>
<style scoped>
#a {
background-color: var(--colour);
}
</style>
Using the original post example for passing an URL:
<template>
<div
id="a"
:style="{ '--image-url': 'url(' + image + ')' }">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['image']
}
</script>
<style scoped>
#a {
background-url: var(--image-url);
}
</style>
Source

Meteor Dynamic Template not working

The line {{> Template.dynamic template=content }} makes my page not load. It actually crashes my browser sometimes. I had it working for a while but something happened and now it does not work anymore.
{{> Template.dynamic template='navBar' }} works so my packages should be ok.
Meteor: 1.4
Packages: kadira:flow-router, kadira:blaze-layout
imports/ui/layouts/mainLayout.html:
<template name="mainLayout">
<header>
<div class="container">
{{> navBar }}
</div>
</header>
<body>
<div class="container">
{{> Template.dynamic template=content }} <!-- not working -->
</div>
</body>
<footer>
<div class="container">
<h3>Footer</h3>
</div>
</footer>
</template>
imports/ui/layouts/mainLayout.js:
import { Template } from 'meteor/templating';
import './mainLayout.html';
import '../components/navBar.html';
import '../pages/settings.html';
imports/startup/client/routes.js:
import { FlowRouter } from 'meteor/kadira:flow-router';
import { BlazeLayout } from 'meteor/kadira:blaze-layout';
import '../../ui/layouts/mainLayout.js';
import '../../ui/pages/settings.js';
FlowRouter.route('/', {
action() {
BlazeLayout.render('mainLayout', { content: 'mainLayout' });
},
});
FlowRouter.route('/settings', {
action() {
BlazeLayout.render('mainLayout', { content: 'settings' });
},
});
imports/ui/pages/settings.html:
<template name="settings">
<div class="container">
<h1>This is the settings page</h1>
</div>
</template>
This route:
FlowRouter.route('/', {
action() {
BlazeLayout.render('mainLayout', { content: 'mainLayout' });
},
});
is not going to work because you are inserting the mainLayout component into itself - the nested content helper is the issue. Instead, you should be rendering a different component into content:
BlazeLayout.render('mainLayout', { content: 'home' }); // or whatever component should be at "/"

Resources