Dynamic columns how to seperate styles - vue.js

I am trying to create dynamic columns, whenever I have 2,3,4 columns then it's not a problem because these are cards with same styles. I want to be able to have 1 item per row with completely different css than the cards. What's the best way to achieve that?
This is what I've tried so far
<script setup>
import { ref } from 'vue'
const list = ref([
{ title: 'hello', content: 'world'},
{ title: 'hello', content: 'world'},
{ title: 'hello', content: 'world'},
{ title: 'hello', content: 'world'},
{ title: 'hello', content: 'world'},
])
const itemsPerRow = ref('25%')
function toggle(e) {
itemsPerRow.value = `${e.target.value}%`
}
</script>
<template>
<select #change="toggle($event)">
<option value="25">4</option>
<option value="33">3</option>
<option value="50">2</option>
<option value="100">1</option>
</select>
<div class="container">
<div class="items">
<div v-for="item in list" class="item">
{{ item.title }}
</div>
</div>
</div>
</template>
<style>
.items {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
}
.item {
flex-basis: v-bind(itemsPerRow);
border: 1px solid black;
box-sizing: border-box;
}
</style>

Working Example
This is just one of many ways you could conditionally render the data based on the number of columns.
Per Vue documentation, you could place the v-for on a template element. And inside use v-if and v-else to render different markup. In this example we check if itemsPerRow == '100%', which indicates that one column is being displayed, and apply different Bootstrap classes.
<template v-for="item in list">
<div v-if="itemsPerRow == '100%'" class="item card mb-2">
<img class="card-image-top" src="https://loremflickr.com/320/50/dog">
<div class="card-body">
<h5 class="card-title">{{item.title}}</h5>
{{item.content}}
</div>
</div>
<div v-else class="item alert alert-primary">
{{ item.title }}
</div>
</template>
Snippet
The snippet differs from the original code since it's an app rather than a component. Selecting 1 column from the dropdown will display a different layout from multiple columns.
const {
createApp
} = Vue
createApp({
methods: {},
watch: {
itemsPerRow: function(value) {
document.querySelector(":root").style
.setProperty("--itemsPerRow", value);
}
},
data() {
return {
itemsPerRow: "25%",
list: []
}
},
mounted() {
for (let i = 1; i <= 100; i++) {
this.list.push({
title: "Title " + i,
content: "The quick brown fox jumped over the lazy dog"
});
}
}
}).mount('#app')
:root {
--itemPerRow: 25%;
}
.container {
margin: 2rem;
}
.items {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
}
.item {
flex-basis: var(--itemsPerRow);
border: 1px solid black;
box-sizing: border-box;
padding: 0.25rem;
}
<div id="app">
<div class="container">
<select v-model="itemsPerRow" class="form-control mb-2">
<option value="25%">4 columns</option>
<option value="33%">3 columns</option>
<option value="50%">2 columns</option>
<option value="100%">1 column</option>
</select>
<div class="items">
<template v-for="item in list">
<div v-if="itemsPerRow == '100%'" class="item card mb-2">
<img class="card-image-top" src="https://loremflickr.com/320/50/dog">
<div class="card-body">
<h5 class="card-title">{{item.title}}</h5>
{{item.content}}
</div>
</div>
<div v-else class="item alert alert-primary">
{{ item.title }}
</div>
</template>
</div>
</div>
</div>
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/css/bootstrap.min.css" rel="stylesheet">

Related

couldn't passing the data from axios to data return variable in vuejs

I have an issue in my vue template down below. I fetched data from axios but it couldn't store the data on this.sub_brand variable. console.log(this.sub_brand) is only working for inside axios. here is the full code -
<template>
<div>
<div class="row" >
<div class="col-md-4 pt-5 pl-5">
<div class="product">
<div class="product__images">
<img
src="http://127.0.0.1:8000/images/gsm.jpg"
alt="google pixel 6"
class="product__main-image"
id="main-image"
/>
<div class="product__slider-wrap">
<div class="product__slider">
<img
src="http://127.0.0.1:8000/images/gsm.jpg"
alt="google pixel 6"
class="product__image product__image--active"
/>
<img
src="http://127.0.0.1:8000/images/gsm.jpg"
alt="google pixel 6"
class="product__image"
/>
<img
src="http://127.0.0.1:8000/images/gsm.jpg"
alt="google pixel 6"
class="product__image"
/>
<img
src="http://127.0.0.1:8000/images/gsm.jpg"
alt="google pixel 6"
class="product__image"
/>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-5 pt-5 pr-5">
<h4>{{sub_brand}}</h4>
<!-- <input type="text" class="form-control" name="" id="" v-model="sub_brand"> -->
<h5>Star</h5>
<div class="bg-light mt-4" style="padding: 10px 0px">
<h2 class="pl-4 pt-3">RM869.00</h2>
</div>
<div class="mt-4">
<h3>Variation</h3>
</div>
<div class="bg-light mt-4" style="padding: 10px 0px">
<h5 class="pl-4">Quantity: </h5>
<input type="number" class="form-control pl-4" placeholder="0" style="width: 12%; margin-left: 4%" min="0">
</div>
<div class="row mt-5">
<button class="btn btn-secondary ml-3">Add to Cart</button>
<button class="btn btn-primary ml-3">Buy Now</button>
</div>
<hr class="mt-5">
</div>
<div class="col-md-3 bg-light">
<div class="pl-5">
<h3><strong>Samsung</strong></h3>
</div>
<div class="pl-5 custom_pan">
Chat
Video Chat
View
</div>
<hr>
<div class="pl-5 mt-4 pr-4">
<strong>Shipping Details</strong>
<p style="color: #D1D3D4">2A, Changkat Duta Kiara, Mont Kiara, 50480 Kuala Lumpur, Willayah Persekutuan Kuala Lumpur</p>
<strong>From: China Logistic, Shankal</strong>
<br><br>
<strong>To: Kuala Lumpur, Willayah Persekutuan</strong>
<br><br>
<strong>Shipping Fee: RM8.00</strong>
</div>
<hr>
<div class="pl-5 mt-5">
<h5>Authentic</h5>
<br>
<h5>15 Days Return</h5>
<br>
<h5>Free Shipping</h5>
</div>
<br><br>
</div>
</div>
<div class="row bg-light">
<div class="card">
<div class="card-header">
<h4>Product Description</h4>
</div>
<div class="card-body">
Samsung
</div>
</div>
</div>
<div class="row bg-light">
<div class="card">
<div class="card-header">
<h4>Review</h4>
</div>
<div class="card-body">
Samsung
</div>
</div>
</div>
<div class="row bg-light">
<div class="card">
<div class="card-header">
<h4>You may also like other product from same merchant</h4>
</div>
<div class="card-body">
Samsung
</div>
</div>
</div>
<div class="row bg-light">
<br><br>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
mounted() {
// console.log('Component mounted.');
this.fetchProduct();
},
data() {
return{
single_product: [],
sub_brand: "",
product_id: 6,
}
},
methods: {
fetchProduct(){
axios.get('https://admin.globalshopping-mall.site/api/single_sub_brand_detail/'+ this.product_id)
.then(res => {
this.single_product = res.data.data[0];
this.sub_brand = res.data.data[0].GUID;
}).catch(err => {console.log(err);});
},
},
}
</script>
<style>
.card{
margin-top: 2%;
margin-left: 4%;
background-color: white;
width: 71%;
/* height: 30%; */
}
.card-header{
background-color: white
}
.product {
width: 100%;
height: 68%;
}
.product__images {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.product__main-image {
max-width: 500px;
max-height: 600px;
object-fit: cover;
cursor: pointer;
border: 1px solid #070707;
}
.product__slider-wrap {
max-width: 500px;
min-height: 100px;
display: flex;
align-items: center;
}
.product__slider {
width: 98%;
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
padding-left: 2%;
}
.product__image {
max-width: 180px;
max-height: 100px;
object-fit: cover;
cursor: pointer;
opacity: 0.5;
margin: 0.25rem;
border: 1px solid #070707;
}
.product__image:first-child {
margin-left: 0;
}
.product__image:last-child {
margin-right: 0;
}
.product__image:hover {
opacity: 1;
}
.product__image--active {
opacity: 1;
}
.product__slider::-webkit-scrollbar {
height: 10px;
}
.product__slider::-webkit-scrollbar-thumb {
background-color: #D1AD33;
border-radius: 50px;
}
</style>
Look, the problem is, your context this. works inside axios with context of axios
If you want to use context this. of vue component, you have to get data from axios outside.
You have to use async/await for you vue method fetchProduct
Something like that
methods: {
async fetchProduct() {
let result = await axios.get("https://admin.globalshopping-mall.site/api/single_sub_brand_detail/" +this.product_id)
.then((res) => {
return res.data.data[0];
})
.catch((err) => {console.log(err);});
this.single_product = result;
this.sub_brand = result.GUID;
},
},
or
You can save your context this to the variable before axios
and use this variable inside the axios function
Something like this
methods: {
fetchProduct() {
let _this = this;
axios.get("https://admin.globalshopping-mall.site/api/single_sub_brand_detail/" + this.product_id)
.then((res) => {
_this.single_product = res.data.data[0];
_this.sub_brand = res.data.data[0].GUID;
})
.catch((err) => {console.log(err);});
console.log(this);
},
},
Root cause : As axios API calls works asynchronously, But other code will execute synchronously. Hence, While trying to logging this.sub_brand it will work synchronously and will invoke before the axios call (response time might vary).
Solution : If you want to access the API response immediately after a call. You have to use async/await which make promises easier to write.
async makes a function return a Promise
await makes a function wait for a Promise
Live Demo :
methods: {
async fetchProduct(){
const res = await axios.get('https://admin.globalshopping-mall.site/api/single_sub_brand_detail/'+ this.product_id)
.then(res => {
return res.data.data[0];
}).catch(err => {console.log(err);});
}
this.single_product = res;
this.sub_brand = res.GUID;
}

I'm trying to convert from pure html code to Vuejs but it's not working

This is the logic algorithm I'm converting and it's not working.
Popup.vue
<script>
import '../../assets/style.css'
export default {
data(){
return{
ceos: [{name_ceo:"Mr. A",
position_ceo:"CEO-GOSTREAM",
content:"Lorem."},
{name_ceo:"Mr. B",
position_ceo:"CTO-GOSTREAM",
content:"Lorem2."},
{name_ceo:"Mr. C",
position_ceo:"CGO-GOSTREAM",
content:"Lorem3."},
]
}
},
methods:{
modalCeo(i){
var modal = this.$refs.modal;
modal[0].style.display="flex";
ceos.forEach(element => {
name_ceo1.innerHTML=ceos[i].name_ceo;
position.innerHTML=ceos[i].position_ceo;
content.innerHTML=ceos[i].content;
});
},
closemodal(){
var modal = this.$refs.modal;
modal[0].style.display="none";
}
}
}
</script>
<style>
</style>
My theme:
<template>
<div class="ceo">
<div ref="modal" class="ceo-popup">
<div class="modal-content-ceo">
<div class="btn-close-popup">
<img src="../../assets/close.svg" id="btn-close-modal" type="button" #click="closemodal()">
</div>
<div class="content-main" v-for="(detail, index) in ceos" :key="index">
<h3 id="name"></h3>
<h5 id="position"></h5>
<h6 id="intro-ceo"></h6>
</div>
<img class="buiding-popup" src="../../assets/Group 226.png" alt="">
</div>
</div>
<div class="title">
<h5>Đội ngũ GoStream</h5>
<h2>Co-Founders</h2>
</div>
<div class="avatar-buiding">
<img class="buiding" src="../../assets/building-0122.png" alt="">
<div class="avatar ">
<img src="../../assets/Profile1.png" #click="modalCeo(0)">
<img src="../../assets//Profile2.png" alt="" #click="modalCeo(1)">
<img src="../../assets/Profile3.png" alt="" #click="modalCeo(2)">
</div>
</div>
</div>
</template>
I want when I click it, a pop up will appear showing the values ​​I have given.
Can you guys give me a solution to this problem?
<div class="avatar" v-for="(item, index) in images" :key="index" >
<img :src="item.url" #click="modalCeo(index)">
</div>
Script:
images:[
{url: '../../assets/Profile1.png'},
{url: '../../assets/Profile2.png'},
{url: '../../assets/Profile3.png'},
]
Update on the code I worked on but it still can't render the image.
You can simply achieve it by using Vue Modal component.
Demo :
new Vue({
el: '#app',
data: {
showModal: false,
selectedCeo: [],
ceos: [
{name_ceo:"Mr. A",
position_ceo:"CEO-GOSTREAM",
content:"Lorem."},
{name_ceo:"Mr. B",
position_ceo:"CTO-GOSTREAM",
content:"Lorem2."},
{name_ceo:"Mr. C",
position_ceo:"CGO-GOSTREAM",
content:"Lorem3."}
]
},
methods: {
modalCeo(index) {
this.showModal = true;
this.selectedCeo = this.ceos[index];
}
}
});
.modal-vue .overlay {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
}
.modal-vue .modal {
position: relative;
width: 300px;
z-index: 9999;
margin: 0 auto;
padding: 20px 30px;
background-color: #fff;
}
.modal-vue .close{
position: absolute;
top: 10px;
right: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<!-- app -->
<div id="app" class="modal-vue">
<!-- button show -->
<button v-for="(item, index) in ceos" :key="index" #click="modalCeo(index)">{{ item.name_ceo }}</button>
<!-- overlay -->
<div class="overlay" v-if="showModal" #click="showModal = false"></div>
<!-- modal -->
<div class="modal" v-if="showModal">
<button class="close" #click="showModal = false">x</button>
<p>Name : {{ selectedCeo.name_ceo }}</p>
<p>Position : {{ selectedCeo.position_ceo }}</p>
<p>Content : {{ selectedCeo.content }}</p>
</div>
</div>
Note : I updated code snippet as per your comment. Instead of the profile pictures I used buttons just for the demo.

Easy way to apply masonry to vue grid items?

Is there an easy way to apply masonry to grid items in Vue? I've been searching through tutorials and questions here, but I haven't been able to successfully apply Masonry to my app. I'm looking for a way to use Masonry to automatically place and size the images:
<template>
<div class="row" v-if="othersImages">
<div class="col" v-if="errors">
<div class="alert alert-danger"><p>{{ errors }}</p></div>
</div>
<div id="others-images" class="grid">
<div class="grid-item" v-for="image in othersImages" :key="image.id">
<h5>{{ image.name }}</h5>
<picture v-bind="'image' + image.id">
<img v-bind:src="image.image.path" v-bind:alt="image.description"/>
</picture>
</div>
<div class="clearfix"></div>
</div>
</div>
</template>
<script>
export default {
name: 'othersImages',
created() {
this.fetchImages();
},
data() {
return {
apiRequest: new this.$request(),
othersImages: [],
errors: '',
};
},
methods: {
fetchImages() {
const endpoint = 'images';
this.apiRequest.get(endpoint)
.then((response) => {
this.othersImages = response;
this.errors = '';
})
.catch((errors) => {
this.errors = errors;
});
},
},
};
</script>
I believe, the easiest way to handle that is applying one plugin based on npm package: https://www.npmjs.com/package/vue-masonry. That's the simple library with good supporting and small size.
<template>
<div data-masonry='{"percentPosition": true }' class="row">
<div class="full col-lg-4 half"></div>
<div class="half col-lg-4"></div>
<div class="full col-lg-4"></div>
<div class="full col-lg-4"></div>
<div class="half col-lg-4"></div>
<div class="full col-lg-4"></div>
<div class="full col-lg-4"></div>
<div class="half col-lg-4"></div>
<div class="full col-lg-4"></div>
<div class="full col-lg-4"></div>
</div>
</template>
<script>
export default {}
</script>
<style>
.row {
width: 80vw;
height: 600px;
background-color: green;
margin: auto;
}
.full {
height: 150px;
background-color: grey;
border: 1px solid black;
}
.half {
height: 75px;
background-color: grey;
border: 1px solid black;
}
</style>
You should add bootstrap and masonry cdn's to your projects, then simply adding
data-masonry='{"percentPosition": true }'
line to your row, masonry works automatically.
Check out this link for more info.

VueJS: How to add a boolean prop to existing template

I am looking to extend a vue-toggle component I found to add a boolean value. I am trying to add ability to hide/show an element based on the boolean prop.
Here is my html code:
<div class="container" id="app">
<div class="row">
<div class="col-xs-3 col-sm-4 col-md-5 col-lg-6">
<img src="https://images-na.ssl-images-amazon.com/images/I/81UxhkSlBjL._UX466_.jpg" alt="" class="img-responsive" />
</div>
<div class="col-xs-9 col-sm-8 col-md-7 col-lg-6 options">
<fieldset class="form-group">
<legend class="sr-only">Style</legend>
<div class="form-group">
<vue-toggle :values="styles" :boolean="showVNeck" :selected.sync="style" default="crew"></vue-toggle>
</div>
</fieldset>
<div><span v-if="showVNeck">V Neck</span><span v-else>Crew Neck</span> Selected</div>
</div>
</div>
</div>
<template id="vue-toggle">
<div class="btn-group">
<button type="button"
v-for="(val, key) in values"
#click="changeSelectVal(key, boolean)"
:class="['btn', { 'btn-primary': selected === key, 'btn-default': selected !== key }]"
>{{ val }}</button>
</div>
</template>
Here is my javascript:
var Toggle = Vue.extend({
template: '#vue-toggle',
props: ['values','selected','boolean','default'],
mounted: function () {
this.selected = this.default;
},
methods: {
changeSelectVal: function(val, boolean) {
this.selected = val;
this.boolean = !this.boolean;
}
}
});
Vue.component('vue-toggle', Toggle);
new Vue({
el: '#app',
data: {
style: '',
showVNeck: false,
styles: {
'crew': 'Crew Neck',
'vneck': 'V-Neck',
}
}
});
Here is a codepen to share:
https://codepen.io/mujaji/pen/YzXVqaL
I think I am just overlooking something and looking for assistance.
Cheers!
The .sync modifier requires that your child emits events of the type update:myPropName instead of directly mutating the prop - look at the documentation:
var Toggle = Vue.extend({
template: '#vue-toggle',
props: ['values','selected','boolean','default'],
mounted: function () {
this.$emit('update:selected',this.default);
},
methods: {
changeSelectVal: function(val, boolean) {
this.$emit('update:selected',val);
this.$emit('update:boolean',!this.boolean);
}
}
});
Vue.component('vue-toggle', Toggle);
new Vue({
el: '#app',
data: {
style: '',
showVNeck: false,
styles: {
'crew': 'Crew Neck',
'vneck': 'V-Neck',
},
},
methods:
{
updateVNeck(newValue)
{
this.showVNeck = newValue;
}
}
});
body {
background-color: #5c4084;
padding: 50px;
}
.container {
background-color: #fff;
padding-top: 40px;
padding-bottom: 80px;
border-radius: 8px;
}
.heading
h1 {
color: #fff;
font-size: 4rem;
font-weight: 900;
margin: 0 0 5px 0;
background: -webkit-linear-gradient(#fff, #999);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-align: center;
}
.heading h4 {
color: #5c3d86;
font-size: 24px;
font-weight: 400;
text-align: center;
margin: 0 0 35px 0;
}
.options {
padding-top: 80px;
}
.btn{
outline: none !important;
}
.btn.btn-primary {
background-color: #5c4084;
border-color: #5c4084;
outline: none;
}
.btn.btn-primary:hover {
background-color: #5c4084;
border-color: #5c4084;
}
.btn.btn-primary:active, .btn.btn-primary:focus {
background-color: #5c4084;
border-color: #5c4084;
}
.btn.btn-default:hover {
background-color: #5c4084;
border-color: #5c4084;
color: #fff;
}
.btn.btn-default:active, .btn.btn-default:focus {
background-color: #5c4084;
border-color: #5c4084;
color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
<div class="container" id="app">
<div class="row">
<div class="col-xs-3 col-sm-4 col-md-5 col-lg-6">
<img src="https://images-na.ssl-images-amazon.com/images/I/81UxhkSlBjL._UX466_.jpg" alt="" class="img-responsive" />
</div>
<div class="col-xs-9 col-sm-8 col-md-7 col-lg-6 options">
<fieldset class="form-group">
<legend class="sr-only">Style</legend>
<div class="form-group">
<vue-toggle :values="styles" :boolean.sync="showVNeck" :selected.sync="style" default="crew"></vue-toggle>
</div>
</fieldset>
<div><span v-if="showVNeck">V Neck</span><span v-else>Crew Neck</span> Selected</div>
</div>
</div>
</div>
<template id="vue-toggle">
<div class="btn-group">
<button type="button"
v-for="(val, key) in values"
#click="changeSelectVal(key, boolean)"
:class="['btn', { 'btn-primary': selected === key, 'btn-default': selected !== key }]"
>{{ val }}</button>
</div>
</template>

Vue 2 select2 custom template for label

I know I can change the template for the option slot, but can we do the same for the label slot? Like for option:
<v-select inputId="originsId" :options="origins" label="city" placeholder="Search...">
<template slot="option" slot-scope="origin">
<div class="flex">
<div class="col">
<span>{{ origin.city }}</span>
</div>
<div class="col">
<span>{{ origin.country }}</span>
</div>
</div>
</template>
</v-select>
Is there some way I can style the label when the option is selected? Now it only shows the label="city" value. I need something like:
<v-select inputId="originsId" :options="origins" label="city" placeholder="Search...">
<template slot="label" slot-scope="origin">
<div class="flex">
<div class="col">
<span>Selected city: {{ origin.city }}</span>
</div>
<div class="col">
<span>Selected country: {{ origin.country }}</span>
</div>
</div>
</template>
<template slot="option" slot-scope="origin">
<div class="flex">
<div class="col">
<span>{{ origin.city }}</span>
</div>
<div class="col">
<span>{{ origin.country }}</span>
</div>
</div>
</template>
</v-select>
Basically I need some custom styling and additional info other then label="city" when the option is selected.
As Vue-select Github: L324 and Vue-select Github: L539, uses <slot name="selected-option"> will be one solution.
Updated: from Vue-select Github you will see there is one parent slot = selected-option-container, but I found it hasn't been deployed to the dist. In future, you should be able to use this slot to custom the whole container and the selected options.
Like below demo:
Vue.component('v-select', VueSelect.VueSelect)
new Vue({
el: '#app',
data: {
options: [
{
title: 'Read the Docs',
icon: 'fa-book',
url: 'https://codeclimate.com/github/sagalbot/vue-select'
},
{
title: 'View on GitHub',
icon: 'fa-github',
url: 'https://codeclimate.com/github/sagalbot/vue-select'
},
{
title: 'View on NPM',
icon: 'fa-database',
url: 'https://codeclimate.com/github/sagalbot/vue-select'
},
{
title: 'View Codepen Examples',
icon: 'fa-pencil',
url: 'https://codeclimate.com/github/sagalbot/vue-select'
}
]
}
})
body {
font-family: "Source Sans Pro", "Helvetica Neue", Arial, sans-serif;
}
h1,.muted {
color: #2c3e5099;
}
h1 {
font-size: 26px;
font-weight: 600;
text-rendering: optimizelegibility;
-moz-osx-font-smoothing: grayscale;
-moz-text-size-adjust: none;
}
#app {
max-width: 30em;
margin: 1em auto;
}
#app .dropdown li {
border-bottom: 1px solid rgba(112, 128, 144, 0.1)
}
#app .dropdown li:last-child {
border-bottom: none;
}
#app .dropdown li a {
padding: 10px 20px;
display: flex;
width: 100%;
align-items: center;
font-size: 1.25em;
}
#app .dropdown li a .fa {
padding-right: 0.5em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<script src="https://unpkg.com/vue-select#latest"></script>
<div id="app">
<h1>Vue Select - Custom Option Templating</h1>
<v-select :options="options" label="title">
<template slot="selected-option" slot-scope="option">
<div class="flex">
<div class="col">
<span class="fa" :class="option.icon"></span>
<span>Selected item: {{ option.title }}</span>
</div>
</div>
</template>
<template slot="option" slot-scope="option">
<span class="fa" :class="option.icon"></span>
{{ option.title }}
</template>
</v-select>
</div>