VueJS Routing the same component not triggering OWL Carousel - javascript

Hello
I'm facing this problem with re-evaluating the images rendered by VueJS into a Carousel plugin (OwlCarousel) while loading the same component with different variables
the problem is when loading the page with images everything works well and the carousel can show the images, but when clicking on a link to go to the same component with other images, the carousel shows only an empty box.
Here is what I have so far:
<template>
<div>
<div id="owl-work">
<div class="item" v-for="image in project.images" :key="image.id">
<figure><img :src="'uploads/'+image.url" alt=""></figure>
</div>
</div>
<div class="similars" v-for="similar in similars">
<router-link :key="$route.fullPath" :to="{ name: 'project', params: { id: similar.id, project:similar }}" replace>
<h4>{{similar.title}}</h4>
</router-link>
</div>
</div>
</template>
<script>
export default {
props: ["id"],
computed: {
...mapGetters(['getProject', 'getSimilars']),
project() {
return this.getProject(this.id)
},
similars() {
return this.getSimilars(this.id)
}
}
}
$("#owl-work").owlCarousel();
</script>
and my routes look like:
[
{name: 'projects', path: '/projects', component: ProjectsScreen},
{name: 'project', path: '/project/:id', component: ProjectScreen, props: true},
]
So the question is how to load the "similar" project image into the carousel when clicking on the <router-link> which outputs the results in the same components.
PS: the other fields are changed, and when getting rid of the carousel it works, so its certain with the setup of the carousel itself with how VueJS deals with routing or something like that..

Move the owl initialization to a lifecycle hook, so it is executed again when the route changes:
<script>
export default {
props: ["id"],
computed: {
...mapGetters(['getProject', 'getSimilars']),
project() {
return this.getProject(this.id)
},
similars() {
return this.getSimilars(this.id)
}
},
mounted() {
$("#owl-work").owlCarousel();
}
}
// Removed from here
</script>
Or, better yet, remove the need for accessing from id and use a ref instead.
<template>
<div>
<div ref="owlwork">
<div class="item" v-for="image in project.images" :key="image.id">
<figure><img :src="'uploads/'+image.url" alt=""></figure>
</div>
</div>
<div class="similars" v-for="similar in similars">
<router-link :key="$route.fullPath" :to="{ name: 'project', params: { id: similar.id, project:similar }}" replace>
<h4>{{similar.title}}</h4>
</router-link>
</div>
</div>
</template>
<script>
export default {
props: ["id"],
computed: {
...mapGetters(['getProject', 'getSimilars']),
project() {
return this.getProject(this.id)
},
similars() {
return this.getSimilars(this.id)
}
},
mounted() {
$(this.$refs.owlwork).owlCarousel();
}
}
// Removed from here
</script>

Related

Reload vue-owl-carousel after dynamic data update

Initialized a vue-owl-carousel using dynamic data
<script>
import carousel from 'vue-owl-carousel'
export default {
components: { carousel },
}
<carousel :items="1">
<img v-for="(img, index) in images" :src="img" :key="index">
</carousel>
data: function() {
return {
images: [
"https://placeimg.com/200/200/any?1",
"https://placeimg.com/200/200/any?2",
"https://placeimg.com/200/200/any?3",
"https://placeimg.com/200/200/any?4"
]
};
}
Removed one of images from the images array
How to update the owl carousel with new images array?
This should work with normal reactivity so im guessing the way how the carousel library is built is just sloppy. My advice is to just build your own carousel. It is really not that and can be a good learning curve.
Nevertheless if you really want to use this library, you could wrap the carousel in a template with a v-if condition. Because when deleting a entry from the images array the carousel needs to be rerendered to show its changes. You can force this by deleting and adding the component to the DOM by toggling the v-if of the template tag. A hacky solution to a problem that shouldnt exist in the first place. But something like this would work:
<template>
<div id="app">
<template v-if="toggle">
<carousel :items="1">
<template v-for="(img, index) in images">
<img :src="img" :key="index" />
</template>
</carousel>
</template>
<button #click="deleteImage">DELETE A IMAGE</button>
</div>
</template>
<script>
import Carousel from "vue-owl-carousel";
export default {
name: "App",
components: { Carousel },
data() {
return {
images: [
"https://placeimg.com/200/200/any?1",
"https://placeimg.com/200/200/any?2",
"https://placeimg.com/200/200/any?3",
"https://placeimg.com/200/200/any?4",
],
toggle: true,
};
},
methods: {
deleteImage() {
this.toggle = false;
this.images.pop();
this.$nextTick(() => {
this.toggle = true;
});
},
},
};
</script>
Ive tested it and it works with the vue-owl-carousel library see sandbox

How to hide content when clicked checkbox from different components in vuejs?

//inputtwo.vue
<template>
<div><input type="checkbox" v-model="checked" />one</div>
</template>
<script>
export default {
name: "inputtwo",
components: {},
data() {
return {};
},
};
</script>
//maincontent.vue
<template>
<div>
<div class="container" id="app-container" v-if="!checked">
<p>Text is visible</p>
</div>
<common />
</div>
</template>
<script>
export default {
name: "maincontent",
components: {},
data() {
return {
checked: false,
};
},
methods: {
hidecont() {
this.checked = !this.checked;
},
},
};
</script>
//inputone.vue
<template>
<div><input type="checkbox" v-model="checked" />one</div>
</template>
<script>
export default {
name: "inputone",
components: {},
data() {
return {};
},
};
</script>
How to hide content of checkbox from different components in Vuejs
I have three components called inputone(contains checkbox with v-model),inputtwo (contains checkbox with v-model),maincontent.(having some content and logic), So when user click on checkboxes from either one checckbox(one,two). i schould hide the content.
Codesanfdbox link https://codesandbox.io/s/crimson-fog-wx9uo?file=/src/components/maincontent/maincontent.vue
reference code:- https://codepen.io/dhanunjayt/pen/mdBeVMK
You are actually not syncing the data between components. The main content checked never changes. You have to communicate data between parent and child components or this won't work. And try using reusable components like instead of creating inputone and inputtwo for same checkbox create a generic checkbox component and pass props to it. It is a good practice and keeps the codebase more manageable in the longer run.
App.vue
<template>
<div id="app">
<maincontent :showContent="showContent" />
<inputcheckbox text="one" v-model="checkedOne" />
<inputcheckbox text="two" v-model="checkedTwo" />
</div>
</template>
<script>
import maincontent from "./components/maincontent/maincontent.vue";
import inputcheckbox from "./components/a/inputcheckbox.vue";
export default {
name: "App",
components: {
maincontent,
inputcheckbox,
},
computed: {
showContent() {
return !(this.checkedOne || this.checkedTwo);
},
},
data() {
return {
checkedOne: false,
checkedTwo: false,
};
},
};
</script>
checkbox component:
<template>
<div>
<input
type="checkbox"
:checked="value"
#change="$emit('input', $event.target.checked)"
/>
{{ text }}
</div>
</template>
<script>
export default {
name: "inputcheckbox",
props: ["value", "text"],
};
</script>
Content:
<template>
<div class="container" id="app-container" v-if="showContent">
<p>Text is visible</p>
</div>
</template>
<script>
export default {
name: "maincontent",
props: ["showContent"]
}
</script>
https://codesandbox.io/embed/confident-buck-kith5?fontsize=14&hidenavigation=1&theme=dark
Hope this helps and you can learn about passing data between parent and child components in Vue documentation: https://v2.vuejs.org/v2/guide/components.html
Consider using Vuex to store and maintain the state of the checkbox. If you're not familiar with Vuex, it's a reactive datastore. The information in the datastore is accessible across your entire application.

Vue - how to append components?

I'm trying to create a button that, once is pushed, adds a child component to my component. My code works, except that the HTML is being parsed as a string, here is the parent component:
<template>
<div id="app">
<li v-for="item in items">
{{ item.component }}
</li>
</div>
</template>
<script>
export default {
props:{},
data(){
return {
items: []
}
},
mounted() {},
computed: {},
methods: {
addItem(){
this.items.push({component: '<testcomponent />'})
}
}
}
</script>
And the child component is very basic:
<template>
<div id="app">
<h1>Testing</h1>
</div>
</template>
So the problem with my code is that, every time i push the button, instead of loading every time a new instance of the child component, it will parse the HTML as a string: '<testcomponent />'. How can i fix this? Thanks in advance!
You can push the component name, and use <component :is="item.component"/> in the v-for as follows:
const testcomponent = Vue.component('testcomponent', {
template: '#testcomponent',
});
new Vue({
el:"#app",
components: { testcomponent },
data() { return { items: [] } },
methods: {
addItem() {
this.items.push({ component: 'testcomponent' });
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template id="testcomponent">
<div><h1>Testing</h1></div>
</template>
<div id="app">
<button #click="addItem">Add</button>
<li v-for="item in items">
<component :is="item.component"/>
</li>
</div>

How do I pass data to a component using Props in Vue2?

I have created a .Vue file to feature information on a cafe (Cafe Details Page). However, I would like to take parts of this details page and make it its own component, in order to manage any template updates more efficiently.
Therefore, I have created a Component (CafeHeader.vue) inside a components folder. I am trying to pass down the data from my array (Which is being used on my Cafe Details page) to this component using Props. However, I can't seem to get it to work.
The template for my Cafe Details Page is as below:
<template>
<div>
<div v-for="cafe in activeCafe">
<CafeHeader v-bind:cafes="cafes" />
<div class="content">
<p>{{ cafe.cafeDescription }}</p>
</div>
</div>
</div>
</template>
<script>
import CafeHeader from "./../../components/CafeHeader";
import cafes from "./../../data/cafes"; // THIS IS THE ARRAY
export default {
data() {
return {
cafes: cafes
};
},
components: {
CafeHeader,
},
computed: {
activeCafe: function() {
var activeCards = [];
var cafeTitle = 'Apollo Cafe';
this.cafes.forEach(function(cafe) {
if(cafe.cafeName == cafeTitle){
activeCards.push(cafe);
}
});
return activeCards;
}
}
};
</script>
Then, in a components folder I have a component called CafeHeader where I am wanting to use the data from the array which is previously imported to the Cafe Details page;
<template>
<div>
<div v-for="cafe in cafes">
<h1>Visit: {{cafe.cafeName}} </h1>
</div>
</div>
</template>
<script>
export default {
name: "test",
props: {
cafes: {
type: Array,
required: true
}
},
data() {
return {
isActive: false,
active: false
};
},
methods: {}
};
</script>
If in the CafeHeader component I have cafe in cafes, it does render data from the cafes.js However, it is every cafe in the list and I want just a single cafe.
<template>
<div>
<div v-for="cafe in cafes">
<h1>Visit: {{cafe.cafeName}} </h1>
</div>
</div>
</template>
The component also needed activeCafes on the v-for
<template>
<div>
<div v-for="cafe in activeCafes">
<h1>Visit: {{cafe.cafeName}} </h1>
</div>
</div>
</template>

Vue.js Data not Displaying in view i am trying to display todo list which just displaying blank

This is my App.vue where i have created the Data for todo list and trying to display all todo array data but nothing is showing i am stuck there and please help me to solve that problem
<template>
<div id="app">
<ToDo/>
</div>
</template>
<script>
import ToDo from './components/ToDo';
export default {
name: 'app',
components: {
ToDo
},
data ()
{
return {
todos: [
{
id: 1,
title: "TODO 1",
completed: false
},
{
id: 2,
title: "TODO 2",
completed: true
},
{
id: 3,
title:" TODO 3",
completed: false
}
]
}
}
}
</script>
This is my ToDo.vue from there i am trying to pass the todo.title to Display the title but not working
<template>
<div>
<div v-bind:key="todo.id" v-for="todo in todos" >
{{todo.title}}
</div>
</div>
</template>
<script>
export default {
name:"ToDo",
props: ["todos"]
}
</script>
You should be getting a warning in your console.
You are using a properties but not actually send it to the component.
Your template should be like this.
<template>
<div id="app">
<ToDo :todos="todos"/>
</div>
</template>
Since you're "todos" is an object you need to send it as Javascript which is the meaning of the : before the attribute.
Moreover you should definitely ensure that you are sending an Object to your component by specifying it in the definitions of your props.
props: {
todos: Object
}
you need to pass the todos into ToDo component from the app component like
<template>
<div id="app">
<ToDo :todos=todos/>
</div>
</template>

Categories

Resources