trigger slide in swiper.js from extern via vuejs - vuejs3

I tried to address a method from an external button that is in swiper.js 8.1.0. goes to the next slide.
I created a refSwiper with the compositon API, no idea I don't see any function that I can call there, even with #onSwiper I get a reference to Swiper, but it doesn't move.
<swiper class="swiper-container" ref="swiperRef"
:pagination="{clickable: true,type: 'fraction' }"
:navigation="{ nextEl: '.arrow', }"
:modules="modules"
:centeredSlides="true"
:loop="false"
:simulate-touch="true"
:allow-touch-move="true"
:allow-slide-next="true"
:allow-slide-prev="true"
:watch-slides-progress="true"
#swiper="onSwiper"
#slideChange="onSlideChange"
:breakpoints="{
'1200': {
slidesPerView: 3,
spaceBetween: 770,
},
}"
>
<swiper-slide v-for="item, index in array" :key="index" >
<div class="kachel" #click="go(index)" ></div>
</swiper-slide>
</swiper>
<div class="arrows" >
<img src="../assets/svgs/rechtslinks.svg" alt="" #click="onSwipeNext()" >
</div>
ok, but how can i call the right function in my swiperRef
const onSwipeNext = () => {
console.log(swiperRef);
swiperRef.value.nextSlide();
}

Related

VUE3.JS - Modal in a loop

I have a GET request in my home.vue component.
This query allows me to get an array of objects.
To display all the objects, I do a v-for loop and everything works fine.
<div class="commentaires" v-for="(com, index) of coms" :key="index">
My concern is that I want to display an image by clicking on it (coms[index].imageUrl), in a modal (popup).
The modal is displayed fine but not with the correct image, i.e. the modal displays the last image obtained in the loop, which is not correct.
Here is the full code of my home.vue component
<template>
<div class="container">
<div class="commentaires" v-for="(com, index) of coms" :key="index">
<modale :imageUrl="com.imageUrl_$this.index" :revele="revele" :toggleModale="toggleModale"></modale>
<img class="photo" :src=""" alt="image du commentaire" #click="toggleModale">
</div>
</div>
</template>
<script>
//import axios from "axios";
import axios from "axios";
import Modale from "./Modale";
export default {
name: 'HoMe',
data() {
return {
coms: [],
revele: false
}
},
components: {
modale: Modale
},
methods: {
toggleModale: function () {
this.revele = !this.revele;
},
</script>
Here is my modale.vue component
<template>
<div class="bloc-modale" v-if="revele">
<div class="overlay" #click="toggleModale"></div>
<div class="modale card">
<div v-on:click="toggleModale" class="btn-modale btn btn-danger">X</div>
<img :src=""" alt="image du commentaire" id="modal">
</div>
</div>
</template>
<script>
export default {
name: "Modale",
props: ["revele", "toggleModale", "imageUrl"],
};
</script>
I've been working on it for 1 week but I can't, so thank you very much for your help...
in your v-for loop you're binding the same revele and toggleModale to every modal. When there is only one revele then any time it's true, all modals will be displayed. It's therefore likely you're actually opening all modals and simply seeing the last one in the stack. You should modify coms so that each item has it's own revele, e.g.:
coms = [
{
imageUrl: 'asdf',
revele: false
},
{
imageUrl: 'zxcv',
revele: false
},
{
imageUrl: 'ghjk',
revele: false
}
];
then inside your v-for:
<modale
:image-url="com.imageUrl"
:revele="com.revele"
#toggle-modale="com.revele = false"
></modale>
<img class="photo" :src=""" alt="image du commentaire" #click="com.revele = true">
passing the same function as a prop to each modal to control the value of revele is also a bad idea. Anytime a prop value needs to be modified in a child component, the child should emit an event telling the parent to modify the value. Notice in my code snippet above I replaced the prop with an event handler that turns the revele value specific to that modal to false. Inside each modal you should fire that event:
modale.vue
<div class="btn-modale btn btn-danger" #click="$emit('toggle-modale')">
X
</div>
This way you don't need any function at all to control the display of the modals.

VueJs calling :key in method

im new to Vue and trying myself in Vue3 and Vuetify.
Similar to this Post im trying to :key or ref a vue-signature-pad in a for loop.
I initialize an empty Array and push a new element, which adds a new signature.
<template>
<div>
<v-container>
<div class="row" v-for="(input, index) in inputs">
<v-container>
<VueSignaturePad
id="signature"
width="100%"
height="300px"
ref="signaturePad"
/>
</v-container>
<div class="buttons">
<button #click="undo">Undo</button>
<button #click="save">Save</button>
</div>
</div>
<v-row justify="center">
<v-btn #click="addRow"
class="ma-2"
color="blue-grey"
icon="mdi-plus-circle-outline"
></v-btn>
</v-row>
</v-container>
</div>
</template>
<script>
export default {
data: () => ({
inputs: [],
}),
methods: {
addRow() {
this.inputs.push({
name: ''
})
},
undo() {
this.$refs.signaturePad.undoSignature();
},
save() {
const { isEmpty, data } = this.$refs.signaturePad.saveSignature();
alert("Open DevTools see the save data.");
console.log(isEmpty);
console.log(data);
}
}
}
</script>
<style scope>
</style>
In the Post i already mentioned, i tried the Solution from Mathieu Janio.
So if i understand everything right, ref is not working and i have to use :key on the div itself.
So i tried his Solution
<template>
<div
class="row"
v-for="(applicants, index) in applicant_details"
:key="index"
>
<div class="col-sm-4">
<div class="form-group">
<p>Signature for {{ applicants.first_name }}</p>
</div>
</div>
<div class="col-sm-4">
<div class="form-group">
<VueSignaturePad ref="" />
<button type="button" #click="undo" class="btn btn-warning">
Undo
</button>
</div>
</div>
</div>
</template>
<script setup>
const applicant_details = [
{ first_name: 'john', signature: '' },
];
const undo = () => {
//will undo the signature
};
const save_signature = () => {
//Save the signature
};
</script>
But now im stuck at calling the right "undo"
The signatepad github example uses ref: at the single signaturepad, which is ok.
but not working at the forloop
How do i call now the right function in "undo" for the solution above?
I tried using "this.$.vnode.key" but this gives me an error.
"Uncaught TypeError: Cannot read properties of undefined (reading '$')".
I figured my first way out.
Heres what i have done.
The Signaturepad got an index on the ref.
<VueSignaturePad
:id="'signaturePad' + index"
width="100%"
height="300px"
:ref="'signaturePad' + index"
:options="options"
/>
The "undo" button is giving it "ref" with
<button #click="undo(`signaturePad${index}`)">Undo</button>
And the undo function itself has the first item in its ref array
undo(ref) {
this.$refs[ref][0].undoSignature();
}
Maybe someone has some more efficient way. Feel free :)

How in Vue.js could I load images once the route loads without displaying them yet?

I am trying to add a transition of 2 png into an png in the background, and be able to switch between different scenarios ( like living-room, dining-room etc). Once I click the element that select which area of the house I am choosing, the images gets fetched but because it takes some time to load, the transition doesn't happen and they just appear on top of the image on the background without transition smoothly from the side. I need a way to load the all the images once the route gets rendered, or maybe if you could give me another solution for the problem I'm happy to hear it.
This is the template
<template>
<div>
<div v-for="item in painting" :key="item.id" class="showroom">
<div class="setting">
<h1>{{ item.name }}</h1>
<h3>Choose a room:</h3>
<div v-for=" (room, idx) in rooms" :key="idx" id="roomSelection">
<img id="roomSelector" :src="room.roomview" #click="showRoom(room)">
<p>{{ room.name }}</p>
<br>
</div>
<p>Choose a wall color: <span id="colorPicker" :style="{backgroundColor: color}"><input type="color" id="base" v-model="color"></span></p>
<router-link to="/painting"><i class="fas fa-arrow-left"></i></router-link>
</div>
<div class="display">
<div :style="{backgroundColor: color}" class="wall">
<img :src="item.img">
</div>
<div class="forniture">
<transition name="slideIn">
<div v-for=" room in roomToShow" :key="room" class="setForniture">
<img class="left" :id="room.space1" :src="room.forniture1">
<img class="left" :id="room.space2" :src="room.forniture2">
</div>
</transition>
</div>
</div>
</div>
</div>
</template>
This is the script
<script>
import { mapGetters } from 'vuex'
import sofa from '../assets/sofa.png'
import lamp from '../assets/lamp.png'
import table from '../assets/table.png'
import cabinet from '../assets/cabinet.png'
import chair from '../assets/chair.png'
import sidetable from '../assets/sidetable.png'
import livingroom from '../assets/livingroom.png'
import diningroom from '../assets/diningroom.png'
import lounge from '../assets/lounge.png'
export default {
data(){
return{
color: '#243E36',
rooms: [
{ name: "lounge", space1: 'lounge1', space2: 'lounge2', forniture1: chair, forniture2:sidetable, roomview: lounge},
{ name: "livingroom" , space1: 'livingroom1', space2: 'livingroom2', forniture1:sofa, forniture2:lamp, roomview: livingroom },
{ name: "diningroom" , space1: 'diningroom1', space2: 'diningroom2', forniture1: table, forniture2: cabinet, roomview: diningroom }
],
roomToShow: [],
}
},
computed: {
...mapGetters([
'showPainting',
'forSale',
'painting'
]),
},
methods: {
showRoom(room) {
setTimeout( () => {
this.roomToShow.shift();
this.roomToShow.push(room);
}, 100)
}
}
</script>
The easiest way to solve this issue is to just hide the images with CSS but nevertheless load all from the beginning (render the elements). You can do that by dynamically adding a class to the currently visible image with :class="".
A more complex solution, which gives you also a callback for when the images are loaded, is to create a new Image() for all images and react to onload/onerror. Like this, you can load all the images in the beginning with JS abd without changing the HTML. Here is an example for this use case: How to create a JavaScript callback for knowing when an image is loaded?

How to use search in react js and get the result in particular div?

while searching, the results should appear as a div like below :
i use jquery to search in table,how to get the result like above.
my component code is:
<div id="modaldash" style={{ display: (searching ? 'block' : 'none') }}>
<p className="font-weight-medium" id="name"> <img id="logo" className="logo" src={jessica} alt="pam-logo" /> Jessica James </p>
<button id="Addlist" onClick={this.onSubmitdata} className="btn info">{this.state.shown ? "Addded" : "Add to list"}</button>
<p id="mailid">jessicajames#gmail.com </p>
<p id= "address">Mountain view,Ave</p>
</div>
its just a static content for css. how to use search and get results like above.
export default function App() {
// considering the data object to search on name
const [searchedData, setSearchedData] = useState([]);
const users = [
{
name: "abc1",
emailid: "abc1#gmail.com",
address: "23rd main, 2nd street"
},
{
name: "adb2",
emailid: "abc2#gmail.com",
address: "23rd main, 2nd street"
},
{
name: "adc3",
emailid: "abc3#gmail.com",
address: "23rd main, 2nd street"
}
];
const handleSearch = event => {
const data = users.filter(
user => user.name.indexOf(event.target.value) !== -1
);
setSearchedData(data);
};
const showSearchedData = () => {
return searchedData.map(user => (
<div key={user.emailid}>
<p className="font-weight-medium" id="name">
{" "}
<img id="logo" className="logo" src="" alt="pam-logo" />
{user.name}
</p>
<button id="Addlist"> Added/ add to list</button>
<p id="mailid">{user.emailid} </p>
<p id="address">{user.address}</p>
</div>
));
};
return (
<div className="App">
<input type="text" onChange={handleSearch} />
<div id="modaldash">{searchedData.length > 0 && showSearchedData()}</div>
</div>
);
}
You can add CSS to make a look and feel like shown in image attached.
Check the working example here https://codesandbox.io/s/falling-sun-r3rim

Display User Data with React/Meteor Application

I have been trying various methods to display data from a Meteor fetch within a React template. I don't fully understand why this is so hard to do.
When I use getMeteorData within the template it doesn't display the data when using {this.data.user._id}
getMeteorData() {
return {
user: Meteor.user()
};
},
This is the same story when using componentDidMount.
I have followed the react & meteor tutorial on the meteor website and they use props. This however feels a lot of work for simply pulling and fetching data.
This is an example of an attempt
export var MenuLoggedIn = React.createClass({
displayName: 'MenuLoggedIn',
mixins: [
Router.State, Router.Navigation
],
getMeteorData() {
return {
user: Meteor.user()
};
},
getInitialState(){
return {
avatarImagePreview: null,
avatarImage: null
};
},
render: function() {
return (
<div className="container">
<div className="menu-structure col-md-12">
{this.data.user._id}
<div className="left-menu pull-left">
<img className="logo" src="/img/logo.png"/>
<h1 className="eventburger-title">eventburger</h1>
</div>
<div className="right-menu">
<div className="search-bar">
<i className="fa fa-search"></i>
<input type="text" name="Search" placeholder="Harpist, Photographer, Caterer..."/>
</div>
{this.data
? <img src="/img/avatar.png"/>
: <img src="/img/placeholder-person.jpg"/>}
<span>{this.data}
Feeney</span>
<a href="/app/inbox">
<i className="fa fa-envelope"></i>
</a>
<a className="head-spacing" href="#" onClick={this.logout}>LOG OUT</a>
</div>
</div>
</div>
);
},
logout: function(e) {
e.preventDefault();
Meteor.logout();
window.location.href = "/login"; //Need to be moved to History
}
});
You need to use the ReactMeteorData mixin to make getMeteorData() work.
mixins: [
Router.State, Router.Navigation, ReactMeteorData
],
https://atmospherejs.com/meteor/react-meteor-data

Resources