VueJs - reuse component and pass through background-image - css

Im trying to reuse a component i VueJs. This is the first time Im using Vue.
I have a couple of components in app.vue. And one of them I want to use two times with the only differens between them is the text and the background-image.
I can't wrap my head around how Im gonna make that work. Any Ideas???
App.vue
<!-- first contact banner -->
<lrContactBanner bannerText="The text to the first component"></lrContactBanner>
<!-- second contact banner -->
<lrContactBanner bannerText="text text" backgroundImage="contact.jpeg"></lrContactBanner>
ContactBanner.vue
<div class="banner parallax overlay" :style="{ 'background-image': backgroundImage }">
<div class="container section">
<div class="columns">
<div class="column">
<h3> {{ bannerText }} </h3>
</div>
</div>
</div>
</div>
<script>
export default {
name: 'lrContactBanner',
props: ['bannerText', 'backgroundImage']
}
</script>
<style>
.parallax {
/* background-image: url("../img/lrImage.jpg"); */
height: 250px;
/* Create the parallax scrolling effect */
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
position: relative;
}
</style>

You need to use bound props with v-bind:bannerText or short-hand :bannerText to pass the values to the Banner component. You also need to use quoted single quotes to pass a string to the component since it's looking for an object by default. Here's a working example.
<lrContactBanner :bannerText="'text text'" :backgroundImage="'contact.jpeg'"></lrContactBanner>
For the background-image I would actually use a computed property like
<template>
<div class="banner parallax overlay" :style="style">
<h3>{{ bannerText }} </h3>
</div>
</template>
<script>
export default {
props: ['bannerText', 'backgroundImage', 'color'],
computed: {
style() {
return 'background-image: url(' + this.backgroundImage + ')';
}
}
}
</script>

Related

How can I change some of the cards to next line, that are inside an wrapper when screen limit is reached?

i want to display several elements in cards , coming from my routing system, in a similar way that i am creating my sidebar (that is working properly). i got all titles and icons, and the linking is working perfectly .
This is what i am doing: Since some of my elements, i am getting from my routing system have children (for example, i have spots for "agenda" , "sessao" and "packs e modulos", and the last element, has two elements inside of it "packs" and "modulos") when i am checking my route file, for elements, it wraps each parent, making a wrapper for «agenda», other wrapper for «sessao», and a wrapper with the two children inside it: "packs" e " modulos" (i don't want it's parent to display.
Everything is working as i want except one thing, that is what i am struggling. I display all my cards (wrapped) horizontally, and when a wrapper doensn't fit on the screen it goes to the next line. With the wrappers with only one element works perfectly, however with the wrappers with children, is where i am struggling, since if the wrapper doensn't fit the screen, the entire wrapper changes it's line, and i only want that the child that doesn't fit the line, changes to the next line
For example, if only Agenda, Sessao and Pack fits one line, i want that only Modulo changes to the next line, instead, both Pack and Modulo are chaning.
Here is my code
<template>
<div v-if="!item.hidden&&item.children" class="menu-wrapper">
<template v-if="!item.hidden&&item.children && hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren) && !item.alwaysShow">
<app-link :to="resolvePath(onlyOneChild.path)">
<!-- single -->
<el-card :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest} ">
<!-- <item v-if="onlyOneChild.meta" :title="onlyOneChild.meta.title" /> -->
<!-- <item v-if="onlyOneChild.meta" :icon="onlyOneChild.meta.icon||item.meta.icon" :title="onlyOneChild.meta.title" :collapse="collapse" /> -->
<!-- <span>{{ onlyOneChild.meta.title }}</span> -->
<div class="contentCard">
<div class="icon">
<i :class="onlyOneChild.meta.icon" />
</div>
<span class="title">
{{ generateTitle(onlyOneChild.meta.title) }}
</span>
</div>
</el-card>
</app-link>
</template>
<!-- group -->
<template v-else class="childCard" v-for="child in visibleChildren" :index="resolvePath(item.path)">
<app-link :to="resolvePath(child.path)">
<el-card class="contentClass" :index="resolvePath(child.path)">
<div class="contentCard">
<div class="icon">
<i :class="child.meta.icon" />
</div>
<span class="title">
{{ generateTitle(child.meta.title) }}
</span>
</div>
</el-card>
</app-link>
</template>
</div>
</template>
Here is my css styling
<style lang="css" scoped>
.el-menu--inline span{
font-size: 0.9em;
}
.el-menu-item svg{
margin-right: 11px;
}
.el-menu-item-group__title {
display: none;
}
.is-active .menu-dot{
background: #cca13c;
}
.menu-dot {
width: 21px;
background: #304156;
height: 10px;
border-radius: 20px;
margin-right: 10px;
}
.contentClass{
margin-right:20px;
}
.childCard{
flex-grow:1;
}
.contentCard{
display:grid;
}
.icon{
text-align: center;
font-size: 50px;
}
.title{
text-align: center;
font-size: 10px;
}
.el-card{
margin-right: 20px;
margin-top: 10px;
min-height: 145px;
min-width: 250px;
flex-grow:1;
}
.menu-wrapper{
flex-wrap: wrap;
display: flex;
min-height: fit-content;
}
</style>
Thank You
Edit: since it may be confusing what i said above, to try to be more simple, i have several wrappers with cards inside it, in one line. If i had one card per wrapper, my code would work properly , however, some of my wrappers have 2 or more cards inside, and when it reaches the limit of the screen (especially if is a small screen), the entire wrapper goes to the next line, instead, i only want the card that doensn't have space to fit in the same line, inside that wrapper, to change to the next line.
Solved my problem by doing an workaround (and i post what i did so it may help anyone who had similar problem as me), and simply ungroup my children. I was using a routes method, that simply was retunirng my $store.state.permission.routes, and doing all the magic on my template. I changed my approach and did all the magic on the routes method, and then simpply passing an object array with my ungrouped components, like this:
routes() {
this.rotas = this.$store.state.permission.routes;
console.log(this.$store.state.permission.routes)
var k=0;
for(let i in this.rotas){
if( !this.rotas[i].hidden&&this.rotas[i].children){
if(this.hasOneShowingChild(this.rotas[i].children,this.rotas[i]) && (!this.onlyOneChild.children||this.onlyOneChild.noShowingChildren) && !this.rotas[i].alwaysShow){
this.result[k]= this.rotas[i];
this.result[k].meta=this.rotas[i].children[0].meta;
k++;
}
else{
var childrens = this.rotas[i].children.filter(item => !item.hidden);
for(let child in childrens){
this.result[k]= childrens[child];
k++;
}
}
}
}
return this.result;
},
and my template now
<template>
<div class="menu-wrapper">
<app-link :to="resolvePath(item.path)">
<!-- single -->
<el-card :index="resolvePath(item.path)" :class="{'submenu-title-noDropdown':!isNest} ">
<!-- <item v-if="onlyOneChild.meta" :title="onlyOneChild.meta.title" /> -->
<!-- <item v-if="onlyOneChild.meta" :icon="onlyOneChild.meta.icon||item.meta.icon" :title="onlyOneChild.meta.title" :collapse="collapse" /> -->
<!-- <span>{{ onlyOneChild.meta.title }}</span> -->
<div class="contentCard">
<div class="icon">
<i :class="item.meta.icon" />
</div>
<span class="title">
{{ generateTitle(item.meta.title) }}
</span>
</div>
</el-card>
</app-link>
</div>
</template>

Vue transitioned element not showing after transition is complete

I'm trying to animate an element to full browser height when the user clicks on the top bar. The animation works, but once the (enter) animation is finished the container jumps back to zero height, while it's supposed to stay until the user clicks the close button.
How do I make the container stay 100vh when the animation is finished?
I tried adding height: 100vh; on the element, but by doing that the transition animation stopped working. (by removing the height, the animation works but the element disappears)
Not sure if it matters, but I changed v-if into v-show and also added a key on the container, but that didn't seem to make a difference.
Here's a link to my code. And to view the animation.
<!-- AboutMeComponent.vue -->
<template>
<div>
<div v-show="!extended" class="small-container" #click="extended = !extended">
<h4>
CLICK ME
</h4>
</div>
<ExtendTransition>
<div v-show="extended" key="1" class="main-container">
<div class="icon-container">
<a v-show="extended" href="#" #click="extended = !extended">
<font-awesome-icon icon="times"/>
</a>
</div>
</div>
</ExtendTransition>
</div>
</template>
<!-- ExtendTransition.vue -->
<template>
<transition appear name="extend" mode="out-in">
<slot></slot>
</transition>
</template>
<style lang="scss">
.extend-enter-active,
.extend-leave-active {
transition: 3s;
}
.extend-enter-to,
.extend-leave {
height: 100vh;
}
.extend-leave-to {
height: calc(20px + 1vw);
}
.extend-enter {
height: calc(40px + 3vw);
}
</style>
A transition only is applied while the transition is playing. Once the transition finished, all transition classes are removed. This means that your element must have the CSS you want it to have after the transition is finished. You can then use the transition classes to set the initial state and define the transition to get to that point, and from that point to the initial state.
The easiest way to solve this problem is by making ExtendTransition.vue the only component that worries about the transition, and using a wrapper that wraps the thing you want to extend.
<template>
<transition appear name="extend" mode="out-in">
<div class="extend-transition-wrapper" v-show="extended">
<slot></slot>
</div>
</transition>
</template>
<script>
export default {
props: {
extended: {
type: Boolean,
default: false
}
}
};
</script>
The only thing you then have to do is to set the default state of your wrapper:
.extend-transition-wrapper {
height: 100vh;
will-change: height;
position: relative;
}
In your ABoutMeComponent.vue you then use a prop to show and hide the content:
<ExtendTransition :extended="extended">
<div class="main-container">
<div class="icon-container">
<a v-show="extended" href="#" #click="extended = !extended">
<font-awesome-icon icon="times"/>
</a>
</div>
</div>
</ExtendTransition>
And finally you set .main-container to always have a height of 100%. Since we set the wrapper to have position: relative, this will force the main container to become the height of that element.

Applying .scss-styles to vuetify custom tags

There I have a PageHeader.vue file in my project which includes a stylesheet from an external PageHeader.scss-file:
<template>
<header>
<v-toolbar
app
flat
style="height: 300px;">
</v-toolbar>
<div id="logo"></div>
</header>
</template>
<script>
import './../assets/css/PageHeader.scss'
export default {
name: 'PageHeader'
}
</script>
If I do so everything goes well, but if I try to remove this line:
style="height: 300px;"
and instead use the style in my .scss-file like this:
v-toolbar {
height: 300px;
}
then my style from .scss-file does not apply. But if I prepend
v-toolbar
with the point symbol (treating it like a class but not like a tag name) it works good:
.v-toolbar {
height: 300px;
}
But I do have the v-toolbar TAG in my markup inside the .vue-file, NOT A DIV with "v-loobar" classname. Is there any way to work with vuetify custom tags the same way as with regular HTML tags?
The v-toolbar component renders to
<nav class="v-toolbar" ...></nav>
So you could style the nav element with something like nav.v-toolbar {...}.

How to override the color defined in css?

I have this style class it's create red rectange in the view:
.tag-template .left-panel {
width: 24px;
height: 24px;
background: red;
vertical-align: middle;
}
Here how I use the class in view template:
<script type="text/ng-template" id="tag-template">
<div class="tag-template">
<div class="left-panel">
</div>
<div class="right-panel">
<span>{{$getDisplayText()}}</span>
<a class="remove-button" ng-click="$removeTag()">✖</a>
</div>
</div>
</script>
At some point I want to override the color defined in css .tag-template .left-panel and change color to be green.
Any idea how can I change the color defined in css in the view using ng-style for examle?
you can use ng-style to change color like myStyle can be your expression
<div class="left-panel" ng-style="myStyle"></div>
or
<div class="left-panel" ng-style="{color:'green'}"></div>
My I suggest you keep logic in your markup and styles in your CSS, it will make code easier to read and maintenance well structured.
Note, no space between .left-panel.left-panel-color
CSS
.tag-template .left-panel.left-panel-color {
color: green;
}
HTML
<div class="left-panel left-panel-color">
</div>
If you want to override by pure css method:
old code:
<div class="left-panel">
new code:
<div class="left-panel" style="color:green";>

How do you make an icon change from grey to full colour on hover?

I have a grey facebook icon and a full colour facebook icon. I would like to have them on my website so that when the mouse cursor is placed over the grey icon it becomes the full colour one. How do I achieve this?
Use CSS sprites and shift position based on CSS class for element and element:hover.
Old question, new answer with an old link:
http://webdesignerwall.com/tutorials/html5-grayscale-image-hover shows a solution with jQuery, which doesn't need 2 images (so it saves time and resorces if you want to do a larger gallery)
you need to have 2 versions from the Icon, one grey and another colored, and on hover, switch:
icon
{
background-image: greyIconURL
}
icon:hover
{
background-image: coloredIconURL
}
another way and better is #Kon solution
It can be done through the filter in css.
example
/* needed code */
.employee:hover img {
filter: none;
-webkit-filter: grayscale(0);
-webkit-transform: scale(1.01);
}
.employee img {
filter: gray;
-webkit-filter: grayscale(1);
transition: all .8s ease-in-out;
width: 100%; }
/* style col -- no need */
.row {
display:flex;
}
.col-md-3{
padding:5px;
width:25%;
}
<div class="row ourTeam">
<div class="col-md-3 col-12 q-pa-md employee">
<img src="https://placeimg.com/640/480/any">
<h6>Name</h6>
<span>CEO</span>
</div>
<div class="col-md-3 col-12 q-pa-md employee">
<img src="https://placeimg.com/640/480/any">
<h6>Name</h6>
<span>CEO</span>
</div>
<div class="col-md-3 col-12 q-pa-md employee">
<img src="https://placeimg.com/640/480/any">
<h6>Name</h6>
<span>CEO</span>
</div>
<div class="col-md-3 col-12 q-pa-md employee">
<img src="https://placeimg.com/640/480/any">
<h6>Name</h6>
<span>CEO</span>
</div>
</div>
that easy!
<img src="grey.png" onmouseover="this.src='blue.png'" onmouseout="this.src='greay.png'" />
EDIT use this instead of you wish to be following rules but increasing complexities and KBs
HTML
<img id="yourImage" />
JS
document.getElementsByTagNames('body')[0].addEventListener('load', function() {
document.getElementById('yourImage').addEventListener('mouseover', function() {
document.getElementById('yourImage').src = 'color.jpg'
}, false);
document.getElementById('yourImage').addEventListener('mouseout', function() {
document.getElementById('yourImage').src = 'grey.jpg'
}, false);
}, false);
PS this uses javascript as opposed to your css tag simply because it is a good practice to use image tag wherever possible because browsers will image as an image as opposed to a div tag where they will treat it as a content block (which is not good!).

Resources