How to display a string value in template section in vue.js? - vue.js

I developed one page which is responsible for showing order success message and i am getting response from backend which contains orderId ,i am getting that response and i am able to bind in front end but i am getting my output as a json format in my UI page ,but what i need is to display only orderID value only (like a string).please help me to fix this issue...
i want to display orderID value only
OrderPlace.vue
<template>
<div class="order-place">
<div class="image-container">
<img src="../assets/success.png" alt="not found" />
</div>
<div class="title-container">
<p>Order placed Successfully</p>
</div>
<div class="message-section">
<p>Hurray!!!your order is confirmed and placed successfully contact us in below details
for further communication..</p>
</div>
<div class="order-id">
{{orderNumber}}
</div>
<div class="title-section">
<div class="email-us">
<p>Email-us</p>
</div>
<div class="contact-us">
<p>Contact-us</p>
</div>
<div class="address">
<p>Address</p>
</div>
</div>
<div class="email-sec">
<p>admin#bookstore.com</p>
</div>
<div class="contact-sec">
<p>+918163475881</p>
</div>
<div class="address-sec">
42, 14th Main, 15th Cross, Sector 4 ,opp to BDA complex, near Kumarakom restaurant, HSR Layout, Bangalore 560034
</div>
<div class="button">
<router-link to="/dashboard" class="btn">Continue Shopping</router-link>
</div>
</div>
</template>
<script>
import service from '../service/User';
// import { EventBus } from "./event-bus.js";
export default {
name: 'OrderPlace',
data(){
return{
successTitle:'Order placed Successfully',
adminEmailSection:'Email-us',
adminContactSection:'Contact-us',
adminAddressSection:'Address',
adminEmail:'admin#bookstore.com',
adminMobNum:'+918163475881',
orderNumber: ''
}
},
created() {
service.confirmMail().then(response =>
(this.orderNumber=JSON.stringify(response.data))
)
}
}
</script>

You're stringifying an Object of { message: string; orderId: number } which of course will result in that "string" of an Object being displayed when you use
<div class="order-id">
{{orderNumber}}
</div>
Like Boussadjra said just assign the id to the corresponding data field
service.confirmMail().then(response =>
(this.orderNumber=response.data.orderId)
)

Just assign the orderID to the orderNumber:
service.confirmMail().then(response =>
(this.orderNumber=response.data.orderID)
)

Related

How can I make my section hide only after the submit button is pressed. right now the section disappears after I press one letter

vue.js, how can I make my section hide only after the submit button is pressed. right now the section disappears after I press one letter. I want the V-if and V-else to activate only after the user has submitted their request. or if routing the results on to a different page would easier id like to go that route also.
<template>
<div class="home">
<section id="whiteClawVideo" class="videoWrapper d-block w-100">
<div class="video-container fluid">
<iframe width="100%" height="600" src="https://www.youtube.com/embed/JORN2hkXLyM?
autoplay=1&loop=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope;
picture-in-picture" allowfullscreen></iframe>
</div>
</section>
<form #submit.prevent="SearchMovies()" class="search-box">
<input type="text" placeholder="What are you looking for? " v-model="search" />
<input type="submit" value="Search">
</form>
<div class="movies-list" v-if="search !== ''" >
<div class="container">
<div class="row">
<div class="col-3" v-for="movie in movies" :key="movie.imdbID">
<router-link :to="'/movie/'+movie.imdbID" class="movie-link">
<img class="movieImg" height="100%" :src="movie.Poster" alt="Movie Poster" />
<div class="type">{{ movie.Type }}</div>
<div class="detail">
<p class="year">{{movie.Year}}</p>
<h3>{{ movie.Title }}</h3>
<p>{{movie.imdbID}}</p>
</div>
</router-link>
</div>
</div>
</div>
</div>
<div class="container" v-else>
<MovieSection />
<SecondMovieSection />
</div>
</div>
</template>
import { ref } from 'vue';
import env from '#/env.js';
import MovieSection from '#/components/MovieSection.vue';
import SecondMovieSection from '#/components/SecondMovieSection.vue'
export default {
components: {
MovieSection,
SecondMovieSection
},
setup () {
const search = ref("");
const movies = ref([]);
const SearchMovies = () => {
if (search.value !== "") {
fetch(`API_HERE`)
.then(response => response.json())
.then(data => {
console.log(data)
movies.value = data.Search;
})
}
}
return {
search,
movies,
SearchMovies
}
}
}
Well, it closes once you type a single character because search is a model - it updates on every keypress you do within input it's bound to. What you wanna do instead is hide form based on whether you have entries in your movies array or not, so try changing v-if="search !== ''" to v-if="!movies.length"

Bind class item in the loop

i want to bind my button only on the element that i added to the cart, it's working well when i'm not in a loop but in a loop anything happen. i'm not sure if it was the right way to add the index like that in order to bind only the item clicked, if i don't put the index every button on the loop are binded and that's not what i want in my case.
:loading="isLoading[index]"
here the vue :
<div class="container column is-9">
<div class="section">
<div class="columns is-multiline">
<div class="column is-3" v-for="(product, index) in computedProducts">
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src="" alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="content">
<div class="media-content">
<p class="title is-4">{{product.name}}</p>
<p class="subtitle is-6">Description</p>
<p>{{product.price}}</p>
</div>
</div>
<div class="content">
<b-button class="is-primary" #click="addToCart(product)" :loading="isLoading[index]"><i class="fas fa-shopping-cart"></i> Ajouter au panier</b-button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
here the data :
data () {
return {
products : [],
isLoading: false,
}
},
here my add to cart method where i change the state of isLoading :
addToCart(product) {
this.isLoading = true
axios.post('cart/add-to-cart/', {
data: product,
}).then(r => {
this.isLoading = false
}).catch(e => {
this.isLoading = false
});
}
You can change your isLoading to an array of booleans, and your addToCart method to also have an index argument.
Data:
return {
// ...
isLoading: []
}
Methods:
addToCart(product, index) {
// ...
}
And on your button, also include index:
#click="addToCart(product, index)"
By changing isLoading to an empty array, I don't think isLoading[index] = true will be reactive since index on isLoading doesn't exist yet. So you would use Vue.set in your addToCart(product, index) such as:
this.$set(this.isLoading, index, true)
This will ensure that changes being made to isLoading will be reactive.
Hope this works for you.
add on data productsLoading: []
on add to cart click, add loop index to productsLoading.
this.productsLoading.push(index)
after http request done, remove index from productsLoading.
this.productsLoading.splice(this.productoading.indexOf(index), 1)
and check button with :loading=productsLoading.includes(index)
You can create another component only for product card,
for better option as show below
Kindly follow this steps.
place the content of card in another vue component as shown below.
<!-- Product.vue -->
<template>
<div class="card">
<div class="card-image">
<figure class="image is-4by3">
<img src="" alt="Placeholder image">
</figure>
</div>
<div class="card-content">
<div class="content">
<div class="media-content">
<p class="title is-4">{{product.name}}</p>
<p class="subtitle is-6">Description</p>
<p>{{product.price}}</p>
</div>
</div>
<div class="content">
<b-button class="is-primary" #click="addToCart(product)" :loading="isLoading"><i class="fas fa-shopping-cart"></i> Ajouter au panier</b-button>
</div>
</div>
</div>
</templete>
<script>
export default {
name: "Product",
data() {
return {
isLoading: false
}
},
props: {
product: {
type: Object,
required: true
}
},
methods: {
addToCart(product) {
this.isLoading = true
axios.post('cart/add-to-cart/', {
data: product,
}).then(r => {
this.isLoading = false
}).catch(e => {
this.isLoading = false
});
}
}
}
</script>
Change your component content as shown below.
<template>
<div class="container column is-9">
<div class="section">
<div class="columns is-multiline">
<div class="column is-3" v-for="(product, index) in computedProducts">
<product :product="product" />
</div>
</div>
</div>
</div>
</templete>
<script>
import Product from 'path to above component'
export default {
components: {
Product
}
}
</script>
so in the above method you can reuse the component in other components as well.
Happy coding :-)

I want to show Filtered products in Vue Js based upon the selection made by user in 3 diffrent parameters from All products

This is step 1 which will appear & user will select one category from this
<div class="w-100 text-center step-div py-5">
<h3>step 1 </h3>
<p class="step-p"> for Men, Women or Unisex</p>
<div class="container">
<div id="categorytype" class="responsive">
<div v-for="(type,typeIndex) in types" class="filter-slider-div col-4 p-5" #click= "addfiltertype(typeIndex,type.typeslug)">
<img :src="type.typeImage" class="filter-img mx-auto">
<p>{{type.typename}}</p>
</div>
</div>
</div>
</div>
Out put will be something like Men,Women,Both,Kids etc & On click It is saving slug of this type. which I'll share below,
<h3>step 2 </h3>
<p class="step-p">Select your case size</p>
<div class="container">
<div id="categorydials" class="responsive">
<div v-for="(dial,dialIndex) in dials" class="filter-slider-div col-4 p-5" #click= "addfilterdial(dialIndex,dial.dialname)">
<img :src="dial.dialimage" class="filter-img mx-auto">
<p>{{dial.dialname}}mm</p>
</div>
</div>
</div>
In step 2 User will select Size it can be anything,
<h3>step 3 </h3>
<p class="step-p">Select your case colour</p>
<div class="container">
<div id="categorycolors" class="responsive">
<div v-for="(color,colorIndex) in colors" class="filter-slider-div p-5" #click= "addfiltercolor(colorIndex,color.colorslug)">
<img :src="color.colorimage" class="filter-img mx-auto">
<p>{{color.colorname}}</p>
</div>
</div>
</div>
In Step 3 User will select Colour
Now After this I am updating & saving the slug of these categoies in my js in method
Here is code how my Categories are coming from & saving the category slug in typeslugFilter
I used alert Js to check if it's working & saving correctly or not & It's Saving the exact slug,
var filters = new Vue ({
el: '#categorytype',
data:{
types: [
{
typeId: 1,
typename: 'Men',
typeImage: 'assets/images/filter1.png',
typeslug: 'men',
},
{
typeId: 2,
typename: 'Women',
typeImage: 'assets/images/filter2.png',
typeslug: 'women',
},
{
typeId: 3,
typename: 'Watches',
typeImage: 'assets/images/filter3.png',
typeslug: 'both',
}
] },
methods: {
addfiltertype (typeIndex,typeslug) {
this.typeslugFilter = typeslug;
// alert(this.typeslugFilter+ '+' + typeslug);
}
}
});
Consider similar code for other two categories with variable dialnameFilter & colorslugFilter,
Now I am trieng to fetch filtered products using below code it's not working for me as of now
I am getting my products from json file & they are working fine I am using typeslug & dialname as category type in single product details & using productslider as el: element .
<div id="productslider" class="container py-5">
<p>{{typeslugFilter}}</p>
<div v-for="(variant,variantIndex) in variants" v-if="typeslugFilter === typeslug && dialnameFilter === dialname">
<div class="watch-slider-div">
<img :src="variant.variantImage" class="w-100 py-3">
</div>
</div>
</div>
Please help me out in this If any tech geek an help will be appreciated

Invalid string length at repeat$1 (VueJS) [Resolved: continue is a reserved JavaScript word]

I'm having the Error in execution of function repeat$1 while compiling a very simple VueJS template. This error prevents the app from compiling.
Can't wrap my head against what's wrong whit the template.
Here's the code:
(I replaced parts of the template that consisted solely on text with the word "text".)
<template>
<div class="container">
<div class="row">
<div class="col-lg-10 mx-auto" v-if="showPrivacyDisclaimer">
<div class="card mt-4">
<div class="card-body">
<div class="card-title">
text
</div>
<p>
<b>text</b>
</p>
<p>
text.
</p>
<p>
text
</p>
<div class="text-sm">
<a #click="details = true" style="text-decoration: underline">
Leer más: ¿Qué datos recopilamos?
</a>
<p v-if="details">
text
</p>
<br>
<a #click="rights = true" style="text-decoration: underline">
Leer más: ¿Cómo ejercer tus derechos sobre estos datos?
</a>
<p v-if="rights">
text
</p>
</div>
</div>
<div class="card-footer">
<button type="button"
class="btn btn-primary"
#click="continue()">
Aceptar y continuar
</button>
</div>
</div>
<img :src="baseUrl + '/public/img/eks-logo.svg'"
class="mt-4" style="max-width: 10rem">
<p class="text-muted mt-4 text-sm">
text
<br>
more text
</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Home',
data() {
return {
baseUrl: process.env.VUE_APP_PHP_BASE_URL,
showPrivacyDisclaimer: false,
details: false,
rights: false,
}
},
mounted()
{
let hasPrivacyAccepted = window.localStorage.getItem('pda');
if (!hasPrivacyAccepted) {
this.showPrivacyDisclaimer = true;
} else {
this.continue();
}
},
methods: {
continue()
{
window.localStorage.setItem('pda', 1);
this.$router.replace({
path: '/encuesta/' + this.$route.query.e,
query: this.$route.query
})
}
}
}
</script>
If I completely remove everything between the <template> tags (except the first div that is required), the app starts compiling again.
I have tried progressively deleting parts of the template that use Vue directives (v-if, etc.). But this didn't made the app compile :(
Please help!
Update: I forgot to mention I've already tried deleting and re-installing node_modules
Update 2: I found the source of the bug. continue is a reserved JS word.
You can't use #click="continue()"
This is a reserved word for javascript.
You can see the full list here :
https://www.w3schools.com/js/js_reserved.asp
Update: I started refactoring the template in two views and a more descriptive error message pop'd-up.
The error was that I was using a JavaScript reserved word as a method name (continue is a reserved word).

Vue.js how to use radio buttons inside v-for loop

I'm trying to use radio buttons, so that users can choose one of the photos as their profile photo:
<ul v-for="p in myPhotos">
<li>
<div>
<div>
<div>
photo id: {{p.imgId}}
</div>
<input type="radio" v-model="profileImg" value="p.imgId"> Choose as profile image
</div>
<div><img v-bind:src="BASE_URL +'/uploads/' + userId + '/'+ p.imgId" /> </div>
</div>
</li>
</ul>
The values are otained like this:
created () {
axios.get(this.BASE_URL + '/profile/g/myphotos/', this.jwt)
.then( res => {
this.myPhotos = res.data.photos;
this.showUploadedPhoto = true;
this.profileImg = res.data.profileImg
})
.catch( error => {
console.log(error);
})
},
When an photo is chosen, the profileImg variable should be set to that photo's imgId.
The problem is how to let users to choose only one photo as profile image inside this v-for loop?
Update: a photo my myPhotos object that I'm iterate over:
By providing name you can treat it as one element
var app = new Vue({
el:"#app",
data:{
images:[{imgId:1},{imgId:2},{imgId:3}],
profileImg:2
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
<div v-for="image in images">
<input type="radio" v-model="profileImg" name="profileImg" :value="image.imgId"> Choose as profile image
</div>
You have selected : {{profileImg}}
</div>
</div>
How about setting name attribute for the input field
<ul v-for="p in myPhotos">
<li>
<div>
<div>
<div>
photo id: {{p.imgId}}
</div>
<input type="radio" name="user_profile_photo" v-model="profileImg" :value="p.imgId"> Choose as profile image
</div>
<div><img v-bind:src="BASE_URL +'/uploads/' + userId + '/'+ p.imgId" /> </div>
</div>
</li>
</ul>