I am learning Vue.js hence new to it. I am having difficulty to check whether my class is bonded dynamically. I am trying to add effect: when I hover over a card it should go up a little bit and change its color. Besides, not just css but also custom events are also not working.
Here is my card component:
Vue.component('card', {
props: ['def'],
template: `
<div class="card" :class="'type-' + def.type" #click="play">
<div class="title">{{ def.title }}</div>
<img class="separator" src="svg/card-separator.svg" />
<div class="description">
<div v-html="def.description"></div>
</div>
<div class="note" v-if="def.note">
<div v-html="def.note"></div>
</div>
</div>
`,
methods: {
play() {
this.$emit('play')
this.$emit('test_event_with_args', 'str_arg', 777)
}
},
mounted() {
this.$on("play", ()=> {
console.log("custom event play ni tutdim ready hook ni ichida")
})
this.$on('test_event_with_args', (str, num) => {
console.log(`Test_Event: str=${str}, num=${num}`);
})
}
});
Here is an excerpt from my css file:
.card:hover{
top: -5px
}
.card.type-attack{
background:#9b1b1b
}
.card.type-special{
background:#751b9b
}
.card.type-support{
background:#1b6e9b
}
Related
with html
<div id="app">
<gallery v-bind:links="['link1.jpg', 'link2.jpg']" />
</div>
and component definition:
Vue.component('gallery', {
template: `
<div v-if="!isReady">
not ready
</div>
<div v-else>
<image-grp v-for="src in links">
<img v-bind:src="src">
</image-grp>
</div>
`,
data() {
return {
links: [],
isReady: false
}
},
mounted() {
this.links = this.$el.getAttribute('links').split(',')
this.isReady = true
console.log(this.links);
}
});
I've managed to produce this html:
<div links="link1.jpg,link2.jpg">
<div class="image">
<img src="">
</div>
<div class="image">
<img src="">
</div>
</div>
The images are not showing up because of the empty src. The src should be filled in during the loop on src in links. The array links must be filled properly, cause the html shows the same number of image-grp elements as are in the links array.
I have tried a variety of ways to populate/bind/mustache the src into the dynamic <img src=""> elements. Any guidance would be appreciated.
I don't see any problems with your code. It works.
But you should better make links to props, like this:
props: ['links']
Then, the other commented out lines are not needed.
Playground
Vue.component('gallery', {
props: ['links'],
template: `
<div v-if="!isReady">
not ready
</div>
<div v-else>
<image-grp v-for="src in links">
<img v-bind:src="src">
</image-grp>
</div>
`,
data() {
return {
//links: [],
isReady: false
}
},
mounted() {
//this.links = this.$el.getAttribute('links').split(',');
this.isReady = true;
}
});
const app = new Vue({
el: '#app'
})
img {
width: 100px;
height: 100px;
margin: 4px;
}
<div id="app">
<gallery v-bind:links="['https://i.stack.imgur.com/NxnaT.jpg?s=256&g=1', 'https://www.gravatar.com/avatar/50309120892edf29dcb2188bdabe3b08?s=256&d=identicon&r=PG']"></gallery>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#^2.0.0/dist/vue.min.js"></script>
I'm a bit new to knockout. I'm trying to get a custom component to dynamically load another custom component. I have a variable called location_board that contains html and that html has a custom component in it. . When I use the data-bind="html: location_board" it put the line for the in the dom but it doesn't run the custom component to fill out that node. Note: If I add the npc-widget directly to the template it works. It just doesn't work when it is added though the html binding. From my research I think this means I need to applyBindings on it? I'm not sure how to go about that in this situation though.
Any help is apricated.
Here is my full code for the custom component.
import {Database} from './database.js'
let database = new Database();
import {ResourceManager} from "./resource-manager.js";
let resourceManager = new ResourceManager();
let locationRegister = {
fog_forest: {
name: "The Ghostly Woodland",
image: "url('img/foggy_forest.jpeg')",
description: `
Place holder
`,
location_board: `
<npc-widget id="john-npc" params="id: 1, tree: 'shopkeep', speed: 50"></npc-widget>
<div>In</div>
`
}
};
ko.components.register('location-widget', {
viewModel: function (params) {
let self = this;
self.function = function () {
console.log("Functions!")
}
for(let k in locationRegister[params.id]) {
console.log(k)
this[k] = locationRegister[params.id][k];
}
console.log(this.name)
//return { controlsDescendantBindings: true };
},
template:
`
<div class="row">
<div class="col-lg-12">
<h2 id="title" class="tm-welcome-text" data-bind="html: name"></h2>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div data-bind="style: { 'background-image': image}" class="location-picture mx-auto d-block">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="location-description mx-auto d-block" data-bind="html: description"></div>
</div>
</div>
</div>
<hr>
<div class="row">
<div class="col-lg-12">
<div id="location_board" data-bind="html: location_board">
</div>
</div>
</div>
`
});
In my project I use medium-zoom with pagination. On first page it works well but on second, third, fourth... I have to click several times for close image...on second page...two times, on third 3 times...
it seems to be a problem with maybe any index number?
Here is my code:
<template>
<div>
<div v-if="loading" class="text-center">
<i class="fas fa-spinner fa-pulse fa-5x"></i>
</div>
<div v-else>
<div v-for="(item, imageIndex) in pageOfItems" :key="item.id" class="m-3">
<div class="row mt-3">
<div class="col-lg-9 my-auto" v-html="item.mytext"></div>
<div class="col-lg-3 my-auto text-center">
<article class="container">
<img
class="img-thumbnail"
:src="'http://localhost:4000/api/galeria/' + item.galeriaId + '_f.jpg'"
/>
</article>
</div>
</div>
<hr class="hr1" />
</div>
</div>
<div class="pb-0 pt-3 text-center">
<jw-pagination :items="info" :page-size="10" #changePage="onChangePage"></jw-pagination>
</div>
</div>
</template>
<script>
import mediumZoom from 'medium-zoom'
import axios from 'axios'
export default {
data() {
return {
info: [],
customLabels,
pageOfItems: [],
loading: true,
}
},
mounted() {
axios
.get('http://localhost:4000/api/fetch_galeria.php/')
.then((response) => (this.info = response.data))
.finally(() => (this.loading = false))
},
updated() {
mediumZoom('article img', {
background: 'transparent',
})
},
methods: {
onChangePage(pageOfItems) {
// update page of items
this.pageOfItems = pageOfItems
},
},
}
</script>
You will pretty much need to detach the event listeners here. Because it should be a lot of them added everytime due to the updated hook.
A naive implementation would be to add mediumZoom on the mounted hook. And when you do have a new changePage event, to detach it from all the images, then to apply it to the new ones with the same mediumZoom call.
Below is a way to see which event listeners (and probably how many) you have linked to a specific VueJS component. Select it in the Vue devtools and then, you will have access to the element's properties via $vm0.
I need to make the modal visible on click, I work through components, new Vue constructs do not work
I've never worked with Vue, now I'm asking for help
Error:
64:4 error 'showModal:' is defined but never used no-unused-labels
<template>
<modalPhoto v-if="showModal == 'true'"></modalPhoto>
<div class="block-inputs">
<div class="input-header">
<h3>Photos</h3>
</div>
<div class="photos">
<div class="photo-block">
<img src="../assets/photo.jpg" class="photo modal-img" v-on:click="viewPhoto('true')">
</div>
</div>
</div>
<div class="save-changes">
<div style="margin: 0 auto;">
<button class="button-add button-save">Save</button>
</div>
</div>
<script>
import modalPhoto from './modal/modalPhoto.vue';
export default {
name: 'Photos',
data() {
showModal: false
},
methods: {
viewPhoto() {
this.showModal = true;
}
},
components: {
modalPhoto,
}
}
So I have a list of data brought in using vue resource from an api. I'm trying to integrate this list with bootstrap accordion.
So:
I have set this :
data: {
taller: false
}
and
<div class="panel panel-default"
v-repeat="faq: faqs | filterBy searchText"
v-transition="staggered"
stagger="200"
v-on="click: toggleHeight"
v-class="active: taller">
So on click i'll call toggleHeight and pass through the faq instance :
toggleHeight: function(faq) {
this.taller = true;
}
This function sets to taller to true however it sets it to true for all faq items, not just the one i've passed to toggle height.
How can I only return taller: true for clicked faq item?
Thanks
<div id="demo">
<div class="input-group">
<input class="form-control" v-model="searchText">
</div>
<script id="item-template" type="x-template">
<div
class="stag"
v-on="click: toggleHeight()"
v-class="active: taller"
>
<h3>{{ item.question }}</h3>
<h4>{{ item.answer }}</h4>
</div>
</script>
<question
v-repeat="item: items | filterBy searchText"
v-transition="staggered"
stagger="200">
</question>
</div>
</div>
and the js:
Vue.component('question', {
template: document.querySelector('#item-template'),
data: function() {
return {
taller: false
}
},
methods: {
toggleHeight: function() {
this.taller = ! this.taller
}
}
});
new Vue({
el: '#demo',
ready: function() {
this.fetchItems();
},
methods: {
fetchItems: function() {
this.$http.get('/dev/frequently-asked-questions/api/index', function(items) {
this.$set('items', items);
});
}
}
});
Had to make use of components to target each item more directly.
First of all, you only have one variable taller. Not one per faq. So you'd have to change it a bit to something like this:
new Vue({
el: '#faq-list',
data: {
faqs: [{id:'foo',taller:false},{id:'bar',taller:true}]
},
methods: {
toggleHeight: function (faq, ev) {
faq.taller = false;
ev.target.classList.add('active');
}
}
});
And your HTML to something like this:
<div id="faq-list">
<div class="panel panel-default"
v-repeat="faq: faqs"
v-on="click: toggleHeight (faq, $event)"
v-class="active: taller">
{{ faq.id }}</div>
</div>
And for fun, I added CSS to see things working:
.active {
color: red;
}
Here's the JSfiddle, for your reference and to mess around with it. Click on one of the items in the list and it turns red.