VueJs Multiselect - only one option showing - vue.js

I'm using VueJS Multiselect and when I make a selection from the drop-down menu the other options disappear. How can I choose multiple options?
Also, how do I remove the [] (square brackets) from displaying at the You selected: {{ value }}?
<template>
<div class="container">
<div class="row">
<div class="col-12 col-lg-10 container">
<div>
<Multiselect
v-model="value"
:options="posts"
mode="tags"
:multiple="true"
label="title"
/>
</div>
<p>You selected: {{ value }}</p>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
import Multiselect from "#vueform/multiselect";
export default {
components: {
Multiselect,
},
data: function () {
return {
posts: [],
id: [],
value: [],
};
},
created() {
this.getPosts();
},
methods: {
getPosts() {
axios
.get("https://jsonplaceholder.typicode.com/posts")
.then((response) => {
// eslint-disable-next-line
console.log(response);
this.posts = response.data;
})
.catch((error) => {
// eslint-disable-next-line
console.log(error);
});
},
},
};
</script>
<style src="#vueform/multiselect/themes/default.css"></style>

Try this way :
new Vue({
components: {
Multiselect: window.VueMultiselect.default
},
data: {
value: {
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
},
posts: [
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
},
{
"userId": 1,
"id": 3,
"title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
"body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
},
{
"userId": 1,
"id": 4,
"title": "eum et est occaecati",
"body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
}]
},
methods: {
customLabel (option) {
return option.title
}
}
}).$mount('#app')
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vue-multiselect#2.0.3/dist/vue-multiselect.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect#2.0.2/dist/vue-multiselect.min.css"/>
<div id="app">
<template>
<multiselect
v-model="value"
:options="posts"
:multiple="true"
track-by="id"
:custom-label="customLabel"
>
</multiselect>
<pre>{{ value }}</pre>
</template>
</div>

Related

Vitest: Wrapper doesn't show "teleported" HTML

imagine we have two components, Modal.vue which is lets say a component that is used to display modal content (uses slots to take in JSX), and Component.vue which is the one with content we wish to test with vitest/jest:
//Modal.vue
<template>
<div>
<slot name="header" />
<slot />
<slot name="footer" />
</div>
</template>
//component.vue
<template>
<Modal>
<template #header>
<h1>Hello world</h1>
</template>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<template #footer>
<button>Great</button>
</template>
</Modal>
</template>
The problem is that I cannot reach the wrapper HTML within my test, as it will console log something similar to this:
// snipet from the test file
...
it('should mount Component.vue', () => {
console.log(wrapper.html())
expect(wrapper).toBeTruthy()
})
...
The console.log in the test will result to this:
<div>
<!---->
<!--teleport start-->
<!--teleport end-->
<!---->
</div>
Question is: How can I access the wrapper HTML that is define in 'Component.vue'??

Vue Property or method "isCompleted" is not defined on the instance but referenced during render

I'm trying to add a button that changes color when clicked and changes isCompleted between true and false, what am I doing wrong? I have tried to change 'checkCompleted' to 'checkCompleted(task)' but it still gives the same error
(extra text so stackoverflow allows me post the question, they keep saying too much code and not enough text)
<template>
<div class="container tasks">
<div class="card" v-for="(task, index) in tasks" :key="index">
<div class="card-content">
<div class="card-title">
<h4>{{ task.title }}</h4>
</div>
<p>{{ task.description }}</p>
<button
class="btn-small green"
#click="checkCompleted"
v-if="!isCompleted"
>
Completed
</button>
<div class="btn- red" v-else>Incomplete</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Home",
data() {
return {
tasks: [
{
title: "Read Books",
description:
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Alias accusamus iste asperiores excepturi tempore unde.",
isCompleted: false,
},
{
title: "Wash Plates",
description:
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Alias accusamus iste asperiores excepturi tempore unde.",
isCompleted: false,
},
{
title: "Play Fifa",
description:
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Alias accusamus iste asperiores excepturi tempore unde.",
isCompleted: false,
},
{
title: "Go Gym",
description:
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Alias accusamus iste asperiores excepturi tempore unde.",
isCompleted: false,
},
],
};
},
methods: {
checkCompleted() {
this.isCompleted = this.isCompleted ? true : false;
},
},
};
</script>
You're looping and want to reference the isCompleted from each task so
v-if="!isCompleted"
should be
v-if="!task.isCompleted"

What is overriding a media query?

I am practicing with css-grid and media queries. When I add the media query for max-width 768px nothing happens when I shrink the screen to that size and I still see the 4 columns instead of the 2 I am trying to apply.
I am using Visual Studio Code and the live server. I already tried opening the html directly in Finder (I am using mac os), i have refreshed the page and still have the same issue.
Something is overriding that media query when I have a screen size under 768px and when I inspect the file I see these messages below. How can I solve this or what am I doing wrong here?
Very thankful for any help!
body {
background: green;
}
.grid {
display: grid;
grid-template-columns: repeat(4, auto);
grid-gap: 1rem;
}
#media (max-width: 768px) {
.grid {
display: grid;
grid-template-columns: repeat (2, auto);
}
}
<body>
<div class="grid">
<div class="item">
<h3>Heading 1</h3>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quidem debitis nesciunt eum accusamus corrupti voluptates officiis. Molestiae deleniti pariatur ipsum rerum facilis dicta fugiat quibusdam, nulla quo suscipit, consectetur ratione.</p>
</div>
<div class="item">
<h3>Heading 2</h3>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quidem debitis nesciunt eum accusamus corrupti voluptates officiis. Molestiae deleniti pariatur ipsum rerum facilis dicta fugiat quibusdam, nulla quo suscipit, consectetur ratione.</p>
</div>
<div class="item">
<h3>Heading 3</h3>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quidem debitis nesciunt eum accusamus corrupti voluptates officiis. Molestiae deleniti pariatur ipsum rerum facilis dicta fugiat quibusdam, nulla quo suscipit, consectetur ratione.</p>
</div>
<div class="item">
<h3>Heading X</h3>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quidem debitis nesciunt eum accusamus corrupti voluptates officiis. Molestiae deleniti pariatur ipsum rerum facilis dicta fugiat quibusdam, nulla quo suscipit, consectetur ratione.</p>
</div>
</div>
</body>
There is a space between the word repeat and the opening bracket. Remove that and all should be OK.
The yellow warning triangle shows that something was wrong with that line.

Smooth transition of v-if/else height in Vue.js

I have a component that loads data and then displays it. The user can modify the module which triggers new data to load. While data is loading a loading state is shown. I would like to smoothly transition between these states using animate.css. I have it roughly working, but there is still some jumpiness to it. How can you get the height of the element to smoothly scale on changing state?
JS:
new Vue({
el: '#demo',
data: {
show: true
},
methods: {
loadData() {
this.show = !this.show
setTimeout(() => {
this.show = !this.show
}, 1000);
}
}
})
HTML:
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.2/animate.min.css">
<div id="demo" style="border:1px solid #ddd">
<button v-on:click="loadData()">
Toggle
</button>
<transition
appear-active-class="animated fadeIn"
enter-active-class="animated fadeIn"
leave-active-class="animated fadeOutDown faster"
mode="out-in"
>
<p v-if="!show" key="loading" style="border:1px solid #ddd">Loading</p>
<p v-if="show" key="data" style="border:1px solid #ddd">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In urna metus, pulvinar a dapibus nec, mattis eu nunc. Sed sed lorem id quam tincidunt accumsan. Nam pharetra, nunc facilisis malesuada tincidunt, nulla mi molestie neque, quis dictum dolor dolor a mi. Suspendisse sed est mollis risus vehicula viverra ac in nunc. Duis cursus mauris vitae sapien tincidunt, sit amet sodales dui mattis. Aliquam dui magna, sagittis at tristique et, consequat at sapien. Quisque ac bibendum urna, et aliquet orci. Ut vitae ipsum id odio consectetur eleifend a nec dui. Suspendisse nulla quam, suscipit in pretium id, dignissim sit amet tortor. Aliquam aliquam, leo et tincidunt venenatis, neque purus cursus elit, ac commodo quam leo at ligula.
</p>
</transition>
</div>
https://jsfiddle.net/2ud5s1ne/11/
Shameless plug, I created vue-smooth-reflow for this exact use case.
Here's a demo: https://jsfiddle.net/guanzo/snyvoxec/1/
new Vue({
el: '#demo',
mixins: [SmoothReflow],
data: {
show: true
},
mounted(){
this.$smoothReflow()
},
methods: {
loadData() {
this.show = !this.show
setTimeout(() => {
this.show = !this.show
}, 1000);
}
}
})

Reloading page is flashing content on slot in vue component

Is there any way to avoid this flicker on page refresh, it's a modal component which takes HTML as slot, but when I refresh the page it flashes. My app is not using a router so it's not complete SPA.
see the gif.
Here is the code.
.body {
padding: 2em;
text-align: center;
display: table-cell;
vertical-align: middle;
}
.modal-mask {
position: absolute;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
display: table;
transition: opacity .3s ease;
}
.modal-wrapper {
display: table-cell;
vertical-align: middle;
}
.modal-container {
width: 70%;
margin: 1em auto;
padding: 20px 30px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
transition: all .3s ease;
font-family: Helvetica, Arial, sans-serif;
}
.modal-header h3 {
margin-top: 0;
color: #42b983;
}
.modal-body {
margin: 20px 0;
}
.modal-default-button {
float: right;
}
/*
* The following styles are auto-applied to elements with
* transition="modal" when their visibility is toggled
* by Vue.js.
*
* You can easily play with the modal transition by editing
* these styles.
*/
.modal-enter {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
.modal-enter .modal-container,
.modal-leave-active .modal-container {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}
<!-- template for the modal component -->
<script type="text/x-template" id="modal-template">
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
<button class="modal-default-button" #click="$emit('close')">Close</button>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" #click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</script>
<!-- app -->
<div id="app">
<button id="show-modal" #click="showModal = true">Show Modal</button>
<!-- use the modal component, pass in the prop -->
<modal v-if="showModal" #close="showModal = false">
<!--
you can use custom content here to overwrite
default content
-->
<div slot="body">
<div class="modal-body">
<h4>Text in a modal</h4>
<p>Duis mollis, est non commodo luctus, nisi erat porttitor ligula.</p>
<h4>Popover in a modal</h4>
<p>This button should trigger a popover on click.</p>
<h4>Tooltips in a modal</h4>
<p>This link and that link should have tooltips on hover.</p>
<hr>
<h4>Overflowing text to show scroll behavior</h4>
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
<p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
</div>
</div>
<h3 slot="header">custom header</h3>
</modal>
</div>
<script src="https://unpkg.com/vue#latest/dist/vue.js"></script>
<script>
// register modal component
Vue.component('modal', {
template: '#modal-template'
})
// start app
new Vue({
el: '#app',
data: {
showModal: false
}
})
</script>
Most usually this is due to the fact that your vue.js requires to load until it is able to do what you want.
You basically load html content which is by default visible.
After the html you load vue and vue will hide your content due to your v-if or v-show statements. The most simple way to ensure something like this is not happening is to use the v-cloak directive plus a little bit of css.
Place it at a very high level as given in this example
<div id="app"><!-- vue mounted at this div -->
<div v-cloak>
<!-- your actual code / content -->
</div>
</div>
And the css
[v-cloak] { display: none; }
The v-cloak property will be removed as soon as vue is done with loading. Therefore everything is hidden until vue is done with loading. This should ensure your content is not flashing.