I have a problem with my slider on vue3:
SlideShow
<template>
<div class="slides-wrapper">
<button
class="btn btn-primary btn-action btn-lg slides-prev"
#click="changePhoto(-1)"
:disabled="prevBtn">
<i class="icon icon-arrow-left"></i>
</button>
<div class="slides">
<Slide
:url="activeUrl"
:text="infoSlides"/>
</div>
<button
class="btn btn-primary btn-action btn-lg slides-next"
#click="changePhoto(+1)"
:disabled="nextBtn">
<i class="icon icon-arrow-right"></i>
</button>
</div>
</template>
<script>
import { ref, computed } from 'vue';
import Slide from './Slide.vue';
import { loader } from '#/helpers/loader';
export default {
name: 'SlideShow',
components: {
Slide,
},
props: {
images: {
type: Array,
},
},
setup(props) {
const numberPhoto = ref(0);
const lenghtTablePhotos = ref(+props.images.length - 1);
const activeUrl = computed(() => props.images[numberPhoto.value].url);
const nextBtn = computed(() => numberPhoto.value === lenghtTablePhotos.value);
const prevBtn = computed(() => numberPhoto.value === 0);
const infoSlides = computed(() => `${numberPhoto.value + 1}/${lenghtTablePhotos.value + 1}`);
function changePhoto(param) {
const index = numberPhoto.value + param;
const slide = props.images[index];
if (slide !== undefined) {
loader(props.images[index].url)
.than((url) => console.log(url))
.catch(console.log('err'));
}
}
return {
numberPhoto,
activeUrl,
lenghtTablePhotos,
changePhoto,
nextBtn,
prevBtn,
infoSlides,
};
},
};
</script>
<style lang="scss" scoped>
.slides-wrapper {
width: 500px;
position: relative;
}
.slides-next,
.slides-prev {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.slides-prev {
left: 0;
}
.slides-next {
right: 0;
}
</style>
and my js file:
loader.js
export function loader(url) {
const img = document.createElement('img');
return new Promise((resolve, reject) => {
// eslint-disable-next-line no-unused-vars
img.onload = () => resolve(url);
img.onerror = () => reject(url);
img.src = url;
});
}
but it doesnt work, can someone help ?
enter image description here
you have to use reactive on your variable to use Composition API,
u can access
https://v3.vuejs.org/api/basic-reactivity.html#reactive
you have a typo at calling the .then function. You wrote than instead of then!
Related
I've got a React App, that scans products via a Scanner(using serialport.io + socket.io) and adds each scanned product into my frontend cart component.
Right now I got it working, but my solution creates a new row in my cart per product scanned as you can see here and I need it to display a new row only the first time a prod is scanned and then if the same product is detected it only updates the quantity and total per product and also the cart total, something like this...
From what I've searched the best way to do this would be by using react useContext and useReducer but I can't get it working.
This is my code on server side index.js:
io.on("connection", (socket) => {
console.log("Socket Connected");
const port = new SerialPort({
path: "COM6",
baudRate: 9600,
autoOpen: false,
});
socket.on("start_scanner", () => {
port.open(function (err) {
if (err) {
console.log("Error opening port: ", err.message);
}
else{
console.log("Scanner Connected");
}
});
port.on("open", function () {
setInterval(function () {
const portReader = port.read();
if (portReader != null) {
const sensorVal = Buffer.from(portReader).toString();
const soap = require("soap");
const url = "http://example.com?wsdl";
soap.createClient(url, function (err, client) {
client.GetProductById(
{
UserId: "1",
ProductId: sensorVal,
},
function (err, result) {
if (err) return console.log(err);
let productScanned = result.GetProductByIdResult;
socket.broadcast.emit("add_product_to_list", productScanned);
}
);
});
}
}, 700);
});
});
This is my Cart component code:
import { useState, useEffect } from "react";
import io from "socket.io-client";
import ProductRow from "./ProductRow";
import "./ProductsList.css";
const socket = io.connect("http://localhost:5000");
const ProductsList = (props) => {
const [scannedData, setScannedData] = useState([]);
useEffect(() => {
socket.on("add_product_to_list", (productScanned) => {
setScannedData((prevProducts) => [...prevProducts, productScanned]);
});
}, [socket]);
return (
<div className="w-9/12 h-full px-20 py-20 flex flex-col ">
<div className="w-full h-auto my-2 px-3 py-3 font-semibold grid grid-cols-3 bg-blue-600 rounded-xl">
<div className="w-[60%] text-left">Product</div>
<div className="w-[20%] text-left">Quant.</div>
<div className="w-[20%] text-left">Price</div>
</div>
<div
id="products-wrapper"
className="w-full h-[95%] flex flex-col overflow-x-hidden overflow-y-scroll"
>
{scannedData.map((productScanned) => (
<ProductRow data={productScanned} />
))}
</div>
<div className="w-full h-[15%] flex flex-row justify-end">
<div className="w-[20%] h-auto px-3 py-3 font-semibold flex flex-col justify-center bg-blue-600 rounded-xl ">
<div className="w-full text-left">
Total: {/* Total price amount */}{" "}
</div>
<div className="w-full text-left">
Qty: {0}
</div>
</div>
</div>
</div>
);
};
export default ProductsList;
This is my Cart Row component:
import "./ProductsList.css";
const ProductRow = ({ data }) => {
return (
<div
className="product-row w-full h-auto my-2 px-3 py-3 text-black text-center grid grid-cols-3 rounded-xl "
key={data._x003C_Id_x003E_k__BackingField}
>
<div className="w-[60%] text-left">
{data._x003C_Name_x003E_k__BackingField}
</div>
<div className="w-[20%] text-left">{1}</div>
<div className="w-[20%] text-left">
{parseFloat(data._x003C_Price_x003E_k__BackingField).toFixed(2)}€
</div>
</div>
);
};
export default ProductRow;
I've also got a cart-context.js and a CartProvider.js files which I was using to achieve my goal but can't get it to work.
/*cart-context.js*/
import React from "react";
const CartContext = React.createContext({
items: [],
totalAmount: 0,
addItem: (item) => {},
removeItem: (id) => {},
});
export default CartContext;
/*CartProvider.js*/
import { useContext, useReducer } from "react";
import CartContext from "./cart-context";
const defaultCartState = {
items: [],
totalAmount: 0,
};
const cartReducer = (state, action) => {
if (action.type === "ADD_ITEM") {
const updatedTotalAmount = state.totalAmount + action.item.price * action.item.amount;
const existingCartItemIndex = state.items.findIndex(
(item) => item.id === action.item.id
)
const existingCartItem = state.items[existingCartItemIndex];
let updatedItems;
if(existingCartItem){
const updatedItem = {
...existingCartItem,
amount: existingCartItem.amount + action.item.amount
}
updatedItems = [...state.items];
updatedItems[existingCartItemIndex] = updatedItem;
} else{
updatedItems = state.items.concat(action.item);
}
return {
items: updatedItems,
totalAmonut: updatedTotalAmount,
};
}
return defaultCartState;
};
const CartProvider = (props) => {
const [cartState, dispatchCartAction] = useReducer(
cartReducer,
defaultCartState
);
const addItemToCartHandler = (item) => {
dispatchCartAction({ type: "ADD_ITEM", item: item });
};
const removeItemFromCartHandler = (id) => {
dispatchCartAction({ type: "REMOVE_ITEM", id: id });
};
const cartContext = {
items: cartState.items,
totalAmonut: cartState.totalAmonut,
addItem: addItemToCartHandler,
removeItem: removeItemFromCartHandler,
};
return (
<CartContext.Provider value={cartContext}>
{props.children}
</CartContext.Provider>
);
};
export default CartProvider;
Could anyone help me out and help me understand my mistakes?
Thanks in advance.
I'm creating a function that is looking for users in database.
I've done the server-side code, but I don't know how to display the results in the html code. I know that I have to write some JavaScript code but I don't know how
I found something on Google, but it doesn't work.
This is my route.
router.get('/search', isAuth, feedController.getSearch);
This is my controller.
exports.getSearch = (req,res,next) => {
const search = req.query.searchField;
User.find({
firstname:{
$regex: new RegExp(search)
},
}, {
_id:0,
__v:0
}, function (err,data) {
res.json(data);
}
).limit(10);
}
This is my HTML
<li>
<div class="search-box">
<form action="/search" method="GET" class="form-inline my-0 my-lg-0">
<input type="text" aria-label="Search" class="form-control mr-sm-0" onkeyup="showResults(this.value)" placeholder="Mirror-Mirror Search">
<span class="hightlight"></span>
<span class="bar"></span>
</input>
<button type="submit" class="search-btn"><i class="fas fa-search"></i></button>
</form>
</div>
<div style="position: relative; width:100%; top:-1px;">
<div class="border" id="search-results"></div>
</div>
</li>
And this is what I found on Google
var showResults = debounce(function(arg) {
var value = arg.trim();
if(value == "" || value.length <=0)
{
$("#search-results").fadeOut();
return;
}
else {
$("#search-results").fadeIn();
}
var jgxh = $.get('/controllers/feed/getSearch?searchField=' + value, function(data) {
$("#search-results").html("");
})
.done(function(data){
if(data.length === 0) {
$("#search-results").append('<p class="lead text-center mt-2">No results</p>');
} else {
data.forEach(x => {
$("#search-results").append('<a href="#> <p class="m-2 lead>' +x.firstname+' '+x.lastname + '</p></a>')
});
}
})
.fail(function(err){
console.log(err);
})
},200)
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this;
args = arguments;
var later = function () {
timeout = null;
if(!immediate) func.apply(context,args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if(callNow) func.apply(context,args);
};
};
I expected to autodisplay the results, but It doesn't work. I want to search in my database either for 'firstname' or 'lastname', I hope you can help me, thank you!
I am able to fetch the data from the db and it is displaying on the inspect element also but it is not displaying on the browser i mean UI.
//storing the data into the posts
this.state = {
displayMenu: false,
posts: [ ]
};
//click function for the drop down and handling the axios.get
Click = event => {
event.preventDefault();
let currentComponent = this;
axios.get(`http://localhost:4000/api/AMS`)
.then(function (response) {
console.log(response);
currentComponent.setState({posts: response.data})
})
.catch(function (error) {
console.log(error);
});
}
//Render method
render() {
// var back = {backgroundSize : 'cover'};
var textStyle = {
position: 'absolute',
top: '50%',
left: '50%'
};
//From here the checking of data is happening, if the data is found inside the posts it will show it on the browser otherwise it will show no posts.
const { posts } = this.state;
const postList = posts.length ? (
posts.map(post => {
// console.log('hi');
return (
<div className="post card" key={post.ID}>
<div className="card-content">
</div>
</div>
)
})
) : ( <div className="center">No posts yet</div>)
//RETURN method
return (
<div>
{/* <Image
style={back} responsive
src={logo}>
</Image> */}
<div style={textStyle} className="dropdown" style = {{background:"red",width:"200px"}} >
<div className="button" onClick={this.showDropdownMenu}> Regions </div>
{ this.state.displayMenu ? (
<ul>
<li><a className="active" href="/AMS" onClick={this.Click}>AMS</a></li>
<li>EMEA</li>
<li>APJ</li>
</ul>
):(null)
}
</div>
//Here i am calling the postList variable
{postList}
{/* {this.state.posts}<br/>
{this.state.pictures} */}
</div>
);
}
}
Click = event => {
event.preventDefault();
let currentComponent = this;
axios.get(`http://localhost:4000/api/AMS`)
.then(function (response) {
console.log(response);
currentComponent.setState({posts: response.data})
})
.catch(function (error) {
console.log(error);
});
}
render() {
// var back = {backgroundSize : 'cover'};
var textStyle = {
position: 'absolute',
top: '50%',
left: '50%'
};
const { posts } = this.state;
const postList = posts.length ? (
posts.map(post => {
// console.log('hi');
return (
<div className="post card" key={post.ID}>
<div className="card-content">
</div>
</div>
)
})
) : ( <div className="center">No posts yet</div>)
The results that i am getting in the inspect element console is like below:
ID: 229, EMAIL: "anuraguk3#gmail.com", ROLE: "BASE", PASSWORD:"$2b$10$ShTWYAtF8M5JLhEm68JqTuMx7P8x6dtOIkNsGz4wE21LY92xGoDCO"
DOM is rendered before getting server response.So, you need to use async-await in this scenario. For your program:-
Click = async(event) => {
event.preventDefault();
let currentComponent = this;
await axios.get(`http://localhost:4000/api/AMS`)
.then(function (response) {
console.log(response);
currentComponent.setState({posts: response.data})
})
.catch(function (error) {
console.log(error);
});
}
I have a pagination system that allows me to go to the next page and previous page.
I want to be able to implement that if the user runs out of data to return on the page then they should be redirected back to the first page again.
Can someone help me do this? thanks
You can see below my .ts file and .html file.
import { Component } from '#angular/core';
import { WebService } from './web.service';
import { AuthService } from './auth.service';
#Component({
selector: 'hotels',
templateUrl: './hotels.component.html',
styleUrls: ['./hotels.component.css']
})
export class HotelsComponent {
constructor(private webService: WebService, private authService:
AuthService) {}
ngOnInit() {
if (sessionStorage.start) {
this.start = sessionStorage.start;
}
this.webService.getHotels(this.start);
}
nextPage() {
this.start = Number(this.start) + 5;
sessionStorage.start = Number(this.start);
this.webService.getHotels(this.start);
}
previousPage() {
if (this.start > 0) {
this.start = Number(this.start) - 5;
sessionStorage.start = Number(this.start);
this.webService.getHotels(this.start);
}
}
hotel_list;
start = 0;
}
HTML
<div class="container" style="margin-top:100px;">
<div class="row">
<div class="col-sm-12">
<div *ngFor="let hotel of webService.hotel_list | async">
<div class="card text-white bg-primary mb-3"
[routerLink]="['/hotels', hotel._id]" style="cursor: pointer">
<div class="card-header">
{{ hotel.Name }}
</div>
<div class="card-body">
This hotel is based in
{{ hotel.Location }}
</div>
<div class="card-footer">
{{ hotel.review_count }}
reviews available
</div>
</div>
</div>
</div> <!-- col -->
</div> <!-- row -->
<div class="row">
<div class="col-sm-6">
<button (click)="previousPage()">Previous</button>
</div>
<div class="col-sm-6 text-right">
<button (click)="nextPage()">Next</button>
</div>
</div>
</div> <!-- container -->
Web Service
import { Http, URLSearchParams } from '#angular/http';
import { Injectable } from '#angular/core';
import 'rxjs/add/operator/toPromise';
import { Subject } from 'rxjs/Rx';
#Injectable()
export class WebService {
hotelID;
private hotels_private_list = [];
private hotelsSubject = new Subject();
hotel_list = this.hotelsSubject.asObservable();
private hotel_private_list = [];
private hotelSubject = new Subject();
hotel = this.hotelSubject.asObservable();
private reviews_private_list = [];
private reviewsSubject = new Subject();
reviews = this.reviewsSubject.asObservable();
url: string = 'http://localhost:3000/api/hotels/';
hotelsArray = [];
constructor(private http: Http) {
}
getHotels(start) {
return this.http.get(
'http://localhost:3000/api/hotels?start=' + start)
.subscribe(response => {
this.hotels_private_list = response.json();
this.hotelsSubject.next(this.hotels_private_list);
})
}
getHotel(id: string) {
return this.http.get(
'http://localhost:3000/api/hotels/' + id)
.subscribe(response => {
this.hotel_private_list = [];
this.hotel_private_list.push(response.json());
this.hotelSubject.next(this.hotel_private_list);
this.hotelID = id;
})
}
getReviews(id) {
this.http.get(
'http://localhost:3000/api/hotels/' + id + '/reviews')
.subscribe(
response => {
this.reviews_private_list = response.json();
this.reviewsSubject.next(
this.reviews_private_list);
}
)
}
postReview(review) {
let urlSearchParams = new URLSearchParams();
urlSearchParams.append('username', review.name);
urlSearchParams.append('text', review.review);
urlSearchParams.append('stars', review.stars);
this.http.post(
"http://localhost:3000/api/hotels/" +
review.hotelID + "/reviews",
urlSearchParams)
.subscribe(
response => {
this.getReviews(review.hotelID);
}
)
}
}
I have changed a few things. no need to call API for every next/prev if already exists use that. no need to write async in HTML.
SERVICE
getHotels(start) {
return this.http.get('http://localhost:3000/api/hotels?start=' + start);
}
HTML
<div *ngFor="let hotel of pages[start]">
COMPONENT
pages = {};
ngOnInit() {this.getdata(this.start)}
getdata(start) {
if (pages[start]) return; //don't do anything
this.pages[start] = [];
this.webService.getHotels(start).subscribe(response => {
const result = response.json();
if(!result){ // data does not exist go to first page
this.start = 0;
}else{
pages[start] = result;
}
})
}
nextPage() {
this.start = this.start + 5;
sessionStorage.start = this.start;
getdata(this.start);
}
previousPage() {
if (this.start > 0) {
this.start = this.start - 5;
sessionStorage.start = this.start;
getdata(this.start);
}
}
I have no luck with adding spinner/progress bar to the page.
Tried many different libraries , without no success.
I need it to show on
//SHOW SPINNER
and then hide on
//HIDE SPINNER
line in the bellow code
Any help appreciated.
import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { connect } from 'react-redux';
import { deleteUser } from '../actions/Actions';
import { updateUser as APIUpdateUser, addUser as APIAddUser } from '../utils/APIUtils';
import language from '../language';
import scrollToElement from 'scroll-to-element';
import CarsSelect from './CarsSelect';
var _ = require('lodash');
function mapStateToProps(state) {
return {
};
}
class UserTableRow extends Component {
static propTypes = {
data: PropTypes.object.isRequired,
number: PropTypes.number.isRequired,
}
static contextTypes = {
store: React.PropTypes.object
}
constructor(props) {
console.log("Progress");
super(props);
this.state = {
edit: false,
data: props.data
};
this._handleChange = this._handleChange.bind(this);
this._handleCarChange = this._handleCarChange.bind(this);
this._startEdit = this._startEdit.bind(this);
this._cancelEdit = this._cancelEdit.bind(this);
this._handleSave = this._handleSave.bind(this);
this._handleShow = this._handleShow.bind(this);
}
componentDidMount() {
const {data} = this.props;
if (typeof data.new !== 'undefined' && data.new === true) {
this.setState({
edit: true
});
scrollToElement(this.refs.row, {
offset: 0,
ease: 'out-bounce',
duration: 1000
});
}
}
componentWillReceiveProps(nextProps) {
this.setState({
data: nextProps.data,
});
}
render() {
const {number} = this.props;
const {data} = this.state;
const lang = language[language.default];
var showClass = 'more';
var rowHidden = 'hidden';
if (this.state.more === true) {
showClass = 'less';
rowHidden = 'visible';
}
var editClass = '';
if (this.state.edit === true) {
editClass = 'table__row--edit';
}
return (
<div>
<div ref='row' className={'table__row table__row--outer ' + editClass}>
<div className='table__elements-wrapper'>
<div className='table__element'>{number}</div>
<div className='table__element'>
<span className='table__editable-data'>{data.email}</span>
<input onChange={this._handleChange.bind(this, 'email')} className='table__editable-hidden' ref='email' name='email' type='email' value={data.email} />
</div>
<div className='table__element'>
<span className='table__editable-data'>{data.firstName}</span>
<input onChange={this._handleChange.bind(this, 'firstName')} className='table__editable-hidden' ref='firstName' name='firstName' type='text' value={data.firstName} />
</div>
<div className='table__element'>
<span className='table__editable-data'>{data.lastName}</span>
<input onChange={this._handleChange.bind(this, 'lastName')} className='table__editable-hidden' ref='lastName' name='lastName' type='text' value={data.lastName} />
</div>
<div className='table__element'>
<span className='table__editable-data'>{data.phone}</span>
<input onChange={this._handleChange.bind(this, 'phone')} className='table__editable-hidden' ref='phone' name='phone' type='text' value={data.phone} />
</div>
<div className='table__element'>
<span className='table__editable-data'>{lang.userArr[data.type]}</span>
<select onChange={this._handleChange.bind(this, 'type')} className='table__editable-hidden' ref='type' name='type' type='text' value={data.type}>
<option value='0'>{lang.userArr[0]}</option>
<option value='1'>{lang.userArr[1]}</option>
<option value='2'>{lang.userArr[2]}</option>
</select>
</div>
<div className='table__element'>
<input className='table__editable-hidden' ref='password' name='password' type='password' />
</div>
<div className='table__element table__element--avatar'>
<img lightbox='lightbox' className='table__editable-data' src={data.image} alt=''/>
<input className='table__editable-hidden' type='file' ref='image' name='image' />
</div>
<div className='table__element'>
{(() => {
if (data.superAdmin !== true) {
return <div className='table__buttons'>
<div onClick={this._startEdit} className='table__button table__button--edit'></div>
<div onClick={this._cancelEdit} className='table__button table__button--cancel '></div>
<div onClick={this._handleSave} className='table__button table__button--ok'></div>
</div>;
} else {
return false;
}
})()}
</div>
<div className='table__element'><div onClick={this._handleShow} className={'table__show table__show--' + showClass}></div></div>
</div>
<div ref='hiddenRow' className={'table__row table__row--inner table__row--' + rowHidden}></div>
</div>
</div>
);
}
_handleShow() {
var more = this.state.more;
if (!more) {
ReactDOM.render(<CarsSelect handleCarChange={this._handleCarChange} user={this.state.data} />, this.refs.hiddenRow);
} else {
ReactDOM.unmountComponentAtNode(this.refs.hiddenRow);
}
this.setState({
more: !more
});
}
_handleCarChange(e) {
var {data} = this.state;
var values = [];
var userValues = [];
_.each(e, function(item) {
values.push({nameplate: item.label, _id: item.value});
userValues.push(item.value);
});
data.cars = values;
this.setState({
data: data
});
var user = {};
user._id = data._id;
user.cars = userValues;
APIUpdateUser(user);
}
_handleChange(type, event) {
var data = this.state.data;
data[type] = event.target.value;
this.setState({
data: data
});
}
_startEdit() {
this.setState({
edit: true
});
}
_cancelEdit() {
const {data} = this.props;
if (data.new === true) {
this.context.store.dispatch(deleteUser(data));
}
this.setState({
edit: false
});
}
_handleSave() {
//SHOW SPINNER
const {data} = this.props;
var user = {};
user._id = data._id;
user.email = this.refs.email.value;
user.firstName = this.refs.firstName.value;
user.lastName = this.refs.lastName.value;
user.phone = this.refs.phone.value;
user.type = this.refs.type.value;
if (this.refs.password.value) {
user.password = this.refs.password.value;
}
if (this.refs.image.files[0]) {
var reader = new window.FileReader();
reader.readAsDataURL(this.refs.image.files[0]);
reader.onloadend = function() {
user.image = reader.result;
console.log(user.image);
if (data.new === true) {
this.context.store.dispatch(deleteUser(data));
APIAddUser(user);
} else {
APIUpdateUser(user);
}
};
} else {
if (data.new === true) {
this.context.store.dispatch(deleteUser(data));
APIAddUser(user);
} else {
APIUpdateUser(user);
}
}
this.setState({
edit: false
});
//HIDE SPINNER
}
}
var getOptions = function(input, callback) {
setTimeout(function() {
callback(null, {
options: [
{value: 'one', label: 'One'},
{value: 'two', label: 'Two'}
],
// CAREFUL! Only set this to true when there are no more options,
// or more specific queries will not be sent to the server.
complete: true
});
}, 500);
};
export default connect(mapStateToProps)(UserTableRow);
Install
$ npm install react-spinkit --save
Usage
import Spinner from 'react-spinkit';
<Spinner spinnerName='double-bounce' />
see more here https://github.com/KyleAMathews/react-spinkit