why is in Vuejs the toggle functionality not working - vue.js

m pulling the last strand of ny hair working onto toggle functionality using vuejs the console i dont find anything
my code seems to be
<template>
<div class="wrapper">
<nav class="nav flex-column sideBar" v-show='isOpen'>
<a class="nav-link active" href="#">Home</a>
<a class="nav-link" href="#">Contact</a>
</nav>
<div class="container-fluid">
<nav>
<div class="content">
<div class="navbar navbar-expand-lg">
<button type="button" class="btn btn-info" #click='toggleSideBar'>
<i class="fas fa-align-left"></i>
</button>
</div>
</div>
</nav>
</div>
</div>
</template>
<script>
export default{
data(){
isOpen=false;
},
method(){
toggleSideBar();
},
toggleSideBar(){
console.log("==========="+this.isOpen)
this.isOpen=!this.isOpen;
}
}
</script>
button on click the togglle fuctionality doesnt work out doent work out
any help much appreciated
this is the inspect html in browser
<button type="button" class="btn btn-info">
and not
<button type="button" class="btn btn-info" onclick='toggleSidebar()'>
the click function not added to it
m using sass
.wrapper {
display: flex;
align-items: stretch;
width:100%;
}
.sideBar{
border: 1px solid;
width: 30%;
height: 100vh;
margin-left: 0;
transition: all 0.5s;
background-color: #f9f9f7;
}
.container-fluid {
padding-right: 0px;
padding-left: 0px;
}
.navbar{
#extend .navbar;
background-color: #eae9e5;
}
.sidebar.active {
margin-left: -250px;
}

first, add return then change = to : and ; to , in your data()
data(){
return{
isOpen: false,
}
},
then put the toggleSideBar() inside your method like this:
methods:{
toggleSideBar(){
console.log("================"+this.isOpen)
this.isOpen=!this.isOpen;
}
}
FINAL OUTPUT
export default{
data(){
return{
isOpen: false,
}
},
methods:{
toggleSideBar(){
console.log("================"+this.isOpen)
this.isOpen=!this.isOpen;
},
}
}

<script>
export default{
data(){
isOpen: false; //Change this line to : instead of =
},
method(){
toggleSideBar: function(){
console.log("================"+this.isOpen)
this.isOpen=!this.isOpen;
}
},
}
</script>

Related

Dynamic columns how to seperate styles

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">

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 modal component passing data

I am stuck making a modal component for my app in VueJS. I want to be able to put it in its own component for reusability, be able to pass custom content and have multiple modals.
I made the component and it looks like this from the VueJS docs:
Modal.vue
<template>
<div ref="modal">
<script type="text/x-template" id="modal">
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
Header
</slot>
</div>
<div class="modal-body">
<slot name="body">
Body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
Footer
</slot>
<button class="btn btn-primary" #click="$emit('close')">
Button
</button>
</div>
</div>
</div>
</div>
</transition>
</script>
</div>
</template>
<script>
export default {
components: { },
props: ['header', 'footer', 'body', 'button'],
data: () => ({
showModal: false
}),
methods: {
open () {
console.log('Opening modal')
this.showModal = true
}
}
}
</script>
<style>
#modal {
/*color: #000;*/
}
.modal-mask {
position: fixed;
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: 300px;
margin: 0px auto;
/*padding: 20px 30px;*/
background-color: #25262D;
color: #FEFEFE;
border-radius: 3px;
box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
transition: all .3s ease;
font-size: 1.2em;
}
.modal-header {
border-radius: 3px;
background-color: #202128;
border: none;
}
.modal-header h3 {
margin-top: 0;
color: #42b983;
}
.modal-body {
margin: 20px 0;
/*background-color: #202128;*/
border: none;
}
.modal-footer {
text-align: center;
border: none;
}
.modal-footer .btn {
font-size: 1.0em;
}
/*
* 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);
}
</style>
I add a modal in my App.vue:
<button #click="openUpdatedModal()" type="button" class="btn btn-default" data-toggle="modal" data-target="#modal">
Launch Updated Modal
</button>
<modal ref="updatedModal" v-if="showModal" #close="showModal = false">
<!--
you can use custom content here to overwrite
default content
-->
<div slot="header">custom header</div>
</modal>
<script>
import Modal from './components/Modal'
export default {
components: { Modal },
data: () => ({
showModal: false
}),
methods: {
openUpdatedModal () {
this.$refs.updatedModal.open()
}
}
}
</script>
When I click the button I get the text in console "Opening modal" but nothing happens.
I can summon it and it works if I have ALL the code in App.vue
What am I missing?
I made it work by creating a ModalComponent.vue and removing the script tag as Phil suggested in the comments. Here's the code.
ModalComponent.vue:
<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>
</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>
</template>
<script>
export default{
}
</script>
Here's how I defined my component:
Vue.component('modal', ModalComponent);
Modal button in markup:
<button id="show-modal" #click="showModal = true">Show Modal</button>
And the modal component being called on the page:
<modal v-if="showModal" #close="showModal = false">
<!--
you can use custom content here to overwrite
default content
-->
<h3 slot="header">custom header</h3>
</modal>
It's worth noting that I had to declare the showModal property wherever I use my modal.

Can't use Slick-Slider with Dynamic data whwn pulling from external API

Trying to build a website with some sliders.for slider i used SLICK slider.Here is my code .
<template>
<div class="homePopularVenue">
<div class="container">
<h2 class="text-center sub-headwords">POPULAR VENUE</h2>
<!--slider start-->
<div class="home-slider-popular-venue">
<div>
<div class="well">
<span class="half-image-temp">
<img class="img-rsponsive" src=" http://placehold.it/250x150" alt="">
</span>
<span class="half-content-temp">
<h3 class="title">HELLOW</h3>
<h5 class="small">Welcome to Hellow World</h5>
BOOK NOW
</span>
</div>
</div>
</div>
<div class="text-center">
VIEW ALL
</div>
</div>
</div>
</template>
<script>
export default {
name: 'homePopularVenue',
data () {
return {
posts: []
}
},
mounted() {
this.create();
this.$http.get('https://newsapi.org/v1/sources?language=en')
.then(response => {
console.log(response.data);
this.posts = response.data.source;
})
},
methods:{
create (){
$('.home-slider-popular-venue').slick({
slidesToShow: 4,
slidesToScroll: 1,
infinite: true,
dots: true,
autoplay: true,
autoplaySpeed: 2000,
responsive: [
{
breakpoint: 1024,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
infinite: true,
dots: true
}
},
{
breakpoint: 600,
settings: {
slidesToShow: 2,
slidesToScroll: 2
}
},
{
breakpoint: 480,
settings: {
slidesToShow: 2,
slidesToScroll: 1
}
}
]
});
}
},
created: function(){
}
}
</script>
<style scoped>
.sub-headwords:after{
content:"";
width:200px;
background: #F99A13;
height: 4px;
display: block;
margin: auto;
margin-top: 15px;
margin-bottom: 30px;
}
.home-slider-popular-venue .well{
box-shadow: 2px 4px 8px 0 rgba(46,61,73,.2);
margin: 30px 10px;
transition: .2s ease-in-out;
}
.home-slider-popular-venue .well:hover{
box-shadow: 12px 15px 20px 0 rgba(46,61,73,.15);
}
.half-image-temp{
max-height: 250px;
}
.half-image-temp img{
width: 100%;
display: block;
margin: auto;
}
.half-content-temp{
}
</style>
Everything was good before i put the data dynamicaly in slider, after putting the data dynamically in slider its not working.
<template>
<div class="homePopularVenue">
<div class="container">
<h2 class="text-center sub-headwords">POPULAR VENUE</h2>
<!--slider start-->
<div class="home-slider-popular-venue">
<div v-for="post in posts">
<div class="well">
<span class="half-image-temp">
<img class="img-rsponsive" src=" http://placehold.it/250x150" alt="">
</span>
<span class="half-content-temp">
<h3 class="title">HELLOW</h3>
<h5 class="small">Welcome to Hellow World</h5>
<p> {{post.id}} </p>
BOOK NOW
</span>
</div>
</div>
</div>
<div class="text-center">
VIEW ALL
</div>
</div>
</div>
</template>
Also the same problem is happening with OWl.Carousel.