Vue.js list rendering just when IDE updates - javascript

I created a page to show all events that I created, the problem is that when entering the page, no event is shown, only the add events button. And as soon as I hit enter in the IDE and add an empty line anywhere in the code, the list magically appears. Can anyone explain to me the reason for this?
I'm using Quasar and Firebase, I'll let my HTML and Javascript code here if anyone has any idea why this is happening
HTML
<template>
<q-page class="flex flex-center bg-primary column">
<q-btn
to="/adicionar-evento"
color="grey-9"
padding="16px 50px"
class="q-mt-lg"
>
<q-icon left size="2.5em" name="add_circle" />
Adicionar um novo evento
</q-btn>
<div v-for="evento in eventos" :key="evento.id" class="partidaDiv row">
<div class="column colunaPartida">
<h1 class="dataHorario">{{ evento.data.slice(0, 5) }}</h1>
<h1 class="dataHorario">{{ evento.horaInicio }}</h1>
</div>
<div class="column colunaPartida2">
<h1 class="dataHorario">{{ evento.quadra.label }}</h1>
<h1 class="textoLocal">{{ evento.quadra.value }}</h1>
<h1 class="textoLocal">Cachoeirinha, Rio Grande do Sul</h1>
</div>
<div class="column colunaPartida3">
<q-icon name="person" color="white" size="2rem" />
<h1 class="dataHorario">
{{ evento.numeroVagasPreenchidas }}/{{ evento.numeroVagasJogadores }}
</h1>
</div>
</div>
<q-item>
<h1></h1>
</q-item>
</q-page>
</template>
Javascript
<script>
import db from "src/boot/firebase";
import {
collection,
getDocs,
orderBy,
query,
addDoc,
onSnapshot,
deleteDoc,
doc,
getDoc,
updateDoc,
} from "firebase/firestore";
export default {
setup() {
return {
name: "IndexPage",
eventos: [],
};
},
async mounted() {
const ordersRef = collection(db, "eventos");
const q = query(ordersRef, orderBy("data"));
const unsubscribe = onSnapshot(q, (snapshot) => {
snapshot.docChanges().forEach((change) => {
let eventoChange = change.doc.data();
eventoChange.id = change.doc.id;
if (change.type === "added") {
this.eventos.unshift(eventoChange);
}
});
});
},
};
</script>

Figured out, I was using setup() instead of data().

Related

Vuejs emit not working form child to parent

I'm working on this app and the idea is to show details of the cars in a sidebar on click. There are several issues like the sidebar is showing four times and I resolve it somehow but I don't know why is it showing four times. now I don't getting any response on emit call help me out please, I try $parent.$emit, $root.$emit but not seems working!!!
<template>
<div class="home">
<!-- warehouse details -->
<div
v-for="(detail, detailindex) in details"
:key="detailindex"
class="container mt-5 mb-5"
>
<h1>
{{ detail.name }}
<span class="location">{{ detail.cars.location }}</span>
</h1>
<!-- vehicle details -->
<SingleGarage :detail="detail"> </SingleGarage>
</div>
<b-sidebar
id="my-sidebar"
title="Sidebar with backdrop"
backdrop-variant="dark"
ref="mySidebar"
backdrop
shadow
#emitData="testingEmit()"
>
<div class="px-3 py-2">
<h1>{{currentCar}}</h1>
</div>
</b-sidebar>
</div>
</template>
<script>
// # is an alias to /src
import axios from "axios";
import SingleGarage from "../components/SingleGarage";
export default {
components: { SingleGarage },
name: "Home",
data: () => ({
details: String,
currentCar: 'String',
}),
methods:{
testingEmit(data){
this.currentCar = data
console.log('data from emit',data)
}
},
mounted() {
axios
.get("https://api.jsonbin.io/b/5ebe673947a2266b1478d892")
.then((response) => {
var results;
response.data.forEach((element) => {
element.cars.vehicles.sort((a, b) => {
a = new Date(a.date_added);
b = new Date(b.date_added);
results = a > b ? -1 : a < b ? 1 : 0;
return results * -1;
});
});
this.details = response.data;
});
},
};
</script>
<template>
<div class="vGrid mt-4">
<div
class="gridItem border vehicle singleCar"
v-for="(vehicle, vehicleIndex) in detail.cars.vehicles"
:class="'griditem' + vehicleIndex"
:key="vehicle._id"
>
<SingleCar
:vehicle="vehicle"
#click.native="testingTef(vehicleIndex)"
></SingleCar>
</div>
</div>
</template>
<script>
import SingleCar from "#/components/SingleCar";
export default {
name: "SingleGarage",
components: { SingleCar },
props: ["detail"],
data: () => ({
dummyImg: require("#/assets/img/dummycar.png"),
currentCar : 1
}),
methods: {
testingTef(vehicleIndex) {
this.$parent.$emit('emitData',this.detail.cars.vehicles[vehicleIndex].make)
this.$root.$emit('bv::toggle::collapse', 'my-sidebar')
console.log(this.detail.cars.vehicles[vehicleIndex].make)
console.log(this.detail.cars.vehicles[vehicleIndex].date_added)
this.currentCar = this.detail.cars.vehicles[vehicleIndex].make;
},
},
};
</script>
<template>
<div class="singleCar">
<!-- conditionally show image -->
<img
class="carImg"
:src="vehicle.img"
v-if="vehicle.img"
alt="No Preview"
/>
<img class="carImg" :src="dummyImg" v-else alt="No Preview" />
<div class="p-3">
<h3 class="make">{{ vehicle.make }}</h3>
<div class="modelDetails">
<div class="model d-flex ">
<p class="bold">Model:</p>
<p class="price ml-auto ">{{ vehicle.model }}</p>
</div>
<div class="price d-flex ">
<p class="bold">Price:</p>
<p class="price ml-auto ">€{{ vehicle.price }}</p>
</div>
</div>
<p class="dateAdded ml-auto ">{{ vehicle.date_added }}</p>
</div>
</div>
</template>
<script>
export default {
name: "SingleCar",
props: ["vehicle"],
data: () => ({
dummyImg: require("#/assets/img/dummycar.png"),
}),
methods:{
working(){
console.log('working');
console.log(this.vehicle.make)
}
}
};
</script>
Thanks for your help.
So a few things you can try to fix this
in your Home.vue you can change
#emitData="testingEmit()"
to
#emitData="testingEmit"
// or
#emitData="testingEmit($event)"
You are telling to the function testingEmit that is not params to parse. So you need to take out the () and Vue will parse everything that comes from the $event or you cant say put the $event as a param in your testingEmit (second option).
For your SingleGarage.vue you can take the $parent.$emit and replace it with
this.$emit('emitData',this.detail.cars.vehicles[vehicleIndex].make)

Vue firebase query: how to show the next results using infinite loading?

I am creating the food order system. I am building the order history page and try to achieve the infinite loading.
I want to show the next five results each time when I press the "next" button.
The each five results must be returned in descending order. The column name is created_at.
The issue now is, if I press the next button once, I can see the sixth to tenth results.
But if I press the button again, I see the sixth to tenth results.
And the same thing is happening again and again, each time I press the next button.
I think I need to use the for loop in my method. But I could not see how to solve this issue.
I am using firebase query in my methods.
My code:
<template>
<div>
<NavbarMobile />
<CartSmartphone class="mb-5" />
<b-container class="history-mobile">
<b-row class="mb-2 orders">
<span class="ml-2 orders">Your orders</span>
</b-row>
<div class="user-section d-flex " v-for="(item, index) in history" :key="index">
<div v-if="item.status == 'processing'" class="card-area">
<div class=" mb-3" v-for="(sample, index) in item.sample" :key="index">
<router-link :to="{name:'OrderSmartphone',params:{id: item.code}}">
<b-card :img-src="sample" img-alt="Card image" img-left class="mb-3">
<b-card-text class="text">
<!-- Some quick example text to build on the card and make up the bulk of the card's content. -->
<ul class="list-unstyled">
<b-row tag="li">
<span class="shop">{{ item.business }}</span>
</b-row>
<div cols="12" class="d-flex my-3">
<span class="date">{{ item.day }}/{{ item.month }}/{{ item.year}}</span>
<span class="status">{{ item.status }}</span>
</div>
<b-row class="my-3">
<span class="price">{{ item.sale }}</span>
</b-row>
</ul>
</b-card-text>
</b-card>
</router-link>
</div>
</div>
<div v-else class="card-area">
<div class="card-area mb-3" v-for="(sample, index) in item.sample" :key="index">
<b-card :img-src="sample" img-alt="Card image" img-left class="mb-3">
<b-card-text class="text">
<!-- Some quick example text to build on the card and make up the bulk of the card's content. -->
<ul class="list-unstyled">
<b-row tag="li">
<span class="shop">{{ item.business }}</span>
</b-row>
<div cols="12" class="d-flex my-3">
<span class="date">{{ item.day }}/{{ item.month }}/{{ item.year}}</span>
<span class="status">{{ item.status }}</span>
</div>
<b-row class="my-3">
<span class="price">{{ item.sale }}</span>
</b-row>
</ul>
</b-card-text>
</b-card>
</div>
</div>
<div class="arrow-area">
<div class="svg">
<svg xmlns="http://www.w3.org/2000/svg" width="5.126" height="9.313" viewBox="0 0 5.126 9.313">
<g id="download" transform="translate(-116.995 9.036) rotate(-90)">
<path id="パス_390" data-name="パス 390" d="M8.452,117.33,4.4,121.385.344,117.33a.19.19,0,0,0-.269.269l4.189,4.189a.19.19,0,0,0,.269,0L8.722,117.6a.19.19,0,0,0-.265-.274l0,0Z" transform="translate(-0.021 0)" fill="#fff" stroke="#fff" stroke-width="0.5"/>
<path id="パス_391" data-name="パス 391" d="M4.377,121.845a.19.19,0,0,1-.135-.056L.053,117.6a.19.19,0,0,1,.269-.269l4.055,4.054,4.054-4.055a.19.19,0,0,1,.274.265l0,0-4.189,4.189A.19.19,0,0,1,4.377,121.845Z" transform="translate(0 -0.001)" fill="#fff" stroke="#fff" stroke-width="0.5"/>
</g>
</svg>
</div>
</div>
</div>
</b-container>
<b-button #click.prevent="nextPage" class="next">next</b-button>
<FooterMobile />
</div>
</template>
<script>
import CartSmartphone from "#/mobile/CartSmartphone.vue";
import NavbarMobile from "#/components/NavbarMobile.vue";
import FooterMobile from "#/sections/FooterMobile.vue";
import fireApp from '#/plugins/firebase'
const firebase = require("firebase");
require("firebase/firestore");
const db = firebase.firestore();
export default {
name: 'UserSmartphone',
components: {
CartSmartphone,
NavbarMobile,
FooterMobile
},
data() {
return {
customer: this.$route.params.id,
history: [],
sample: ""
}
},
mounted() {
// const customerId = this.$route.params.id
// this.customer = customerId
const dbOrdersRef = db.collection('OrdersUser').doc(this.$route.params.id).collection('Orders').orderBy("created_at", "desc").limit(5)
dbOrdersRef.onSnapshot((querySnapshot) => {
querySnapshot.forEach((doc) => {
const historyData = doc.data()
this.history.push(historyData)
this.sample = doc.data().sample
})
})
},
methods: {
nextPage() {
fireApp.auth().onAuthStateChanged((user) => {
if (user) {
const userId = fireApp.auth().currentUser.uid;
const first = db.collection('OrdersUser').doc(userId).collection('Orders').orderBy("created_at", "desc").limit(5)
return first.onSnapshot((querySnapshot) => {
// Construct a new query starting at this document,
// get the next 5 results.
var lastVisible = querySnapshot.docs[querySnapshot.docs.length - 1];
console.log("last", lastVisible);
var next = db.collection('OrdersUser').doc(userId).collection('Orders').orderBy("created_at", "desc")
.startAfter(lastVisible)
.limit(5);
next.onSnapshot((nextQuery) => {
nextQuery.forEach((doc) => {
const nextData = doc.data()
console.log(nextData)
this.history.push(nextData)
})
})
});
}
})
},
}
}
</script>
The collection name is OrdersUser and I am pushing the data to the array named history.
And then, I'm showing the results in the template section using the for loop.
You are not setting the last visible document outside your nextPage function, so that function is always starting the query after the 5 initial documents, what you need to do is:
Add a variable that stores the last visible document while you are first populating your list, as below:
const dbOrdersRef = db.collection('OrdersUser').doc(this.$route.params.id)
.collection('Orders').orderBy("created_at", "desc").limit(5);
dbOrdersRef.onSnapshot((querySnapshot) => {
querySnapshot.forEach((doc) => {
const historyData = doc.data()
this.history.push(historyData)
this.sample = doc.data().sample
})
this.lastVisible = querySnapshot.docs[querySnapshot.docs.length-1];
})
Use the lastVisible variable set at the initial load to start you subsequent query, like the following:
nextPage() {
fireApp.auth().onAuthStateChanged((user) => {
if (user) {
const userId = fireApp.auth().currentUser.uid;
const next = db.collection('OrdersUser')
.doc(userId)
.collection('Orders')
.orderBy("created_at", "desc")
.startAfter(this.lastVisible)
.limit(5);
return next.onSnapshot((nextQuery) => {
nextQuery.forEach((doc) => {
const nextData = doc.data()
console.log(nextData)
this.history.push(nextData)
})
this.lastVisible = nextQuery.docs[nextQuery.docs.length-1];
})
};
})
}
Declare the lastVisible variable to your data(), as this will make it accessible both in nextPage() and in mounted() by using this., so like the following:
data() {
return {
customer: this.$route.params.id,
history: [],
sample: "",
lastVisible: ""
}
},

Vue: Retrieve firestore data to show user's business name v-for loop

In my project, I am working on the result page of the e-commerce.
I want to retrieve the data from two collections.
One is called "Product", and the other one is called "ProUser".
Now, I could retrieve and show the product info from "Product" collection.
I used v-for loop to show the each item's information.
I also want to retrieve shop name in "ProUser" collection of each user at the same time.
I set the shop name in "business" field.
Product collection is corresponding to uid.
In my dev console, I could confirm I could retrieve all the data from "ProUser" collection.
Following is my vue.js code.
Now in my browser, I cannot show the shop name of each user.
<template>
<div class="main">
<section class="cards">
<div class="card-list" v-for="(item, index) in getMenuItems" :key="index">
<div class="card" >
<div class="product-list" v-if="item.quantity > 0">
<div class="quantity">
<span>{{ item.quantity }}</span>
</div>
<div class="card__image-container" v-for="(sample, index) in item.sample" :key="index">
<router-link to="/product">
<img
:src="sample"
alt="Detailed image description would go here."
class="image"
/>
</router-link>
<!-- Retrieve business name from the ProUser collection. -->
<div class="card__content" v-for="(item, index) in ProUsers" :key="index">
<div class="card__info">
<span class="text--medium">{{ item.business }}</span>
<span class="card__distance text--medium"> product.quantity -- orders </span>
</div>
</div>
</div>
<div class="icons">
<div class="time">
<span>{{ item.limitObject }}</span>
</div>
<div class="fav">
<span>Heart</span>
</div>
<div class="price">
<span>{{ item.sale }}</span>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
import fireApp from '#/plugins/firebase'
const firebase = require("firebase");
require("firebase/firestore");
const db = firebase.firestore();
import googleMapMixin from '#/mixins/googleMapMixin'
import { mapGetters } from 'vuex'
export default {
name: "UserLocation",
data() {
return {
address: "",
error: "",
spinner: false,
ProUsers: []
}
},
mixins: [googleMapMixin],
created() {
//vuexfire
const dbMenuRef = db.collection('Product')
this.$store.dispatch('setMenuRef', dbMenuRef)
//firestore
db.collection("ProUser")
.get()
.then((querySnapshot)=> {
querySnapshot.forEach((doc) => {
console.log(doc.id, " => ", doc.data());
this.ProUsers.push(doc.data())
});
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
},
computed: {
...mapGetters([
'getMenuItems'
])
},
methods: {
}
}
</script>
The problem now is, I could see all the shop name in <div class="card__info> tag.
What I want to achieve is to show one shop name of each user in here.
<!-- Retrieve business name from the ProUser collection. -->
<div class="card__content" v-for="(item, index) in ProUsers" :key="index">
<div class="card__info">
<span class="text--medium">{{ item.business }}</span>
<span class="card__distance text--medium"> product.quantity -- orders </span>
</div>
</div>
</div>
Not showing all the shop name.
My question is In other words, I want to fetch the product and the product owner.
Now in one tag, I could show one product with all the product owners in "ProUser" collection.
Hope someone helps me out.
If you need more information, please feel free to ask.
Here's how you can fetch data user from prouser collection and after then fetch the product related to the prouser and create a new object from data from both collection data.
let data = [];
let db = firebase.firestore();
db.collection("ProUser")
.get()
.then((userSnapshot) => {
db.collection("Product")
.get()
.then((productSnapshot) => {
userSnapshot.forEach((user) => {
productSnapshot.forEach((product) => {
if (user.id === product.id) {
data.push({
uid: user.id,
pId: product.id,
...user.data(),
...product.data(),
});
}
});
});
})
.catch((e) => {
console.log(e);
});
})
.catch((e) => {
console.log(e);
});

Property or method "sendResetMail" is not defined on the instance but referenced during render

I'm relatively new to Vue and super stuck with this error message when I try to make this reset email modal work in my Vue project:
Property or method "sendResetMail" is not defined on the instance but
referenced during render. Make sure that this property is reactive,
either in the data option, or for class-based components, by
initializing the property.
I have no idea what I need to do to make this work. I followed the Vue documentation and declared resetEmail in the data option.
ForgotPassword.vue:
<template>
<section>
<a #click="isComponentModalActive = true">
Forgot Password?
</a>
<b-modal :active.sync="isComponentModalActive" has-modal-card>
<modal-form v-bind="resetEmail"></modal-form>
</b-modal>
</section>
</template>
<script>
import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/firestore'
const ModalForm = {
props: ['resetEmail'],
template: `
<form #submit.prevent="sendResetMail">
<div class="modal-card" style="width: auto">
<header class="modal-card-head">
<p class="modal-card-title">Forgot password?</p>
</header>
<section class="modal-card-body">
<b-field label="Email">
<b-input
type="email"
:value="resetEmail"
placeholder="Your email"
required>
</b-input>
</b-field>
</section>
<footer class="modal-card-foot">
<button class="button" type="button" #click="$parent.close()">Close</button>
<button class="button is-primary">Reset</button>
</footer>
</div>
</form>
`
}
export default {
components: {
ModalForm
},
data () {
return {
isComponentModalActive: false,
resetEmail: '',
feedback: null
}
},
methods: {
sendResetMail () {
var auth = firebase.auth()
var emailAddress = this.resetEmail
auth.sendPasswordResetEmail(emailAddress).then(function () {
// Email sent.
console.log('email send')
}).catch(function (error) {
// An error happened.
this.feedback = error.message
console.log(error.message)
})
}
}
}
</script>
This is the file where I use the ForgotPassword.vue component,
Login.vue:
<template>
<section class="section">
<div class="container">
<div class="columns">
<div class="column"></div>
<div class="column is-half">
<div class="box">
<h1 class="title">Login</h1>
<form #submit.prevent="login">
<b-field label="Email" :message="feedback" :type="type">
<b-input placeholder="Email" icon="email" type="email" v-model="email">
</b-input>
</b-field>
<b-field label="Password" :message="feedback" :type="type">
<b-input placeholder="Password" type="password" icon="textbox-password" password-reveal v-model="password">
</b-input>
</b-field>
<button type="submit" class="button is-primary is-fullwidth">Login</button>
<div class="field">
<div class="control">
<p class="control has-text-centered">
<ForgotPassword/>
</p>
</div>
</div>
<div class="field">
<div class="control">
<p class="control has-text-centered">
Don't have an account?
<a href="/register">
<router-link :to="{ name: 'Signup' }">
Signup
</router-link>
</a>
</p>
</div>
</div>
</form>
</div>
</div>
<div class="column"></div>
</div>
</div>
</section>
</template>
<script>
import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/firestore'
import ForgotPassword from '#/components/auth/ForgotPassword'
export default {
name: 'login',
metaInfo: {
// specify a metaInfo.title, this title will be used
title: 'Login',
// all titles will be injected into this template
titleTemplate: '%s | Wterdrops.com'
},
components: {
ForgotPassword
},
data () {
return {
email: null,
password: null,
feedback: null,
type: null
}
},
methods: {
login () {
if (this.email && this.password) {
firebase
.auth()
.signInWithEmailAndPassword(this.email, this.password)
.then(cred => {
this.$router.push({
name: 'Dashboard'
})
})
.catch(err => {
this.feedback = err.message
})
this.feedback = null
} else {
this.feedback = 'Please fill in both fields.'
this.type = 'is-danger'
}
}
}
}
</script>
<style>
.login {
max-width: 400px;
margin-top: 60px;
}
</style>
I would be very grateful if someone can explain to me what I'm missing :)
You are referencing
<form #submit.prevent="sendResetMail">
inside your ModalForm component.
The problem is that this template is going to look for the method sendResetMail on that ModalForm component template when it gets rendered since you the code is referencing it. However this sendResetMail method is not directly associated on that.
You can consider using a mix-in if you need to use the sendResetMail in many places , or maybe just move that method directly to the same component "ModalForm" that is referencing it.
You can also look into for example eventBus to trigger the method by emitting an event.
The simplest option if you only need to call it from the MOdalForm component is to just move the sendResetMail direcly to that component. I believe that would probably fix your issue.

Vue.js show white space (line breaks)

How would I show line space in vue.js. Right now everything is after each other....
Already tried this:
https://laracasts.com/discuss/channels/vue/vuejs-how-to-return-a-string-with-line-break-from-database
But nothing seems work. Trying this for 3 days now -_-.
I'm using Vue.js 1.0 and browserify.
Thanks a lot!
--EDIT--
<template>
<div>
<bar :title="title" />
<div class="Row Center">
<div class="Message Center" v-if="!loading">
<div class="Message__body" v-if="messages">
<div class="Message__item__body" v-for="message in messages" v-link="{ name: 'Message', params: { message: message.slug }}">
<div class="Message__item__body_content">
<p class="Message__title">{{ message.subject }}</p>
</div>
<div class="Message__item__body_content">
<p>Reacties: {{ message.totalReactions }}</p>
</div>
<div class="Message__item__body_content">
<p>Door: {{ message.user.name }} {{ message.user.last_name }}</p>
</div>
</div>
<pagination :last-page="lastPage" :page="page" :name="Message" />
<p v-if="noMessages" class="Collection__none">Er zijn momenteel geen berichten voor het topic {{ topic.name }}.</p>
</div>
</div>
<div class="Loader" v-if="loading">
<grid-loader :loading="loading" :color="color" :size="size" />
</div>
</div>
<div class="Row center" v-if="!loading && page == 1 && topic">
<div>
<button type="submit" class="Btn Btn-main" v-link="{ name: 'NewMessage', params: { topic: topic.slug }}">Nieuw bericht</button>
</div>
</div>
</div>
</template>
<script>
import Bar from '../Shared/Bar.vue';
import Pagination from '../Shared/Pagination.vue';
import Topic from '../../Services/Topic/TopicService';
import { GridLoader } from 'vue-spinner/dist/vue-spinner.min.js';
export default {
components: { Bar, Pagination, GridLoader },
data () {
return {
title: 'Berichten',
messages: [],
topic: null,
noMessages: false,
loading: false,
color: "#002e5b",
page: 1,
lastPage: 1,
}
},
route: {
data ({ to }) {
this.loading = true;
this.page = to.query.page || 1;
Topic.show(this.$route.params.topic, this.page)
.then((data) => {
this.topic = data.data.topic;
if(!data.data.messages.data.length == 0) {
this.messages = data.data.messages.data;
this.lastPage = data.data.messages.last_page;
} else {
this.noMessages = true;
}
this.loading = false;
});
}
}
}
</script>
When I do it like this:
<div class="Message__body__message">
<p>{{ message.message.split("\n"); }}</p>
</div>
It only adds comma's.
--EDIT--
Set container white-space style to pre-line, as in:
<div style="white-space: pre-line;">{{textWithLineBreaks}}</div>
When you split the message, you get multiple data items, which you should handle with a v-for.
But also see LMK's answer wherein you don't have to split the message.
new Vue({
el: '#app',
data: {
message: `this is a message
it is broken across
several lines
it looks like a poem`
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.min.js"></script>
<div id="app">
<template v-for="line in message.split('\n')">{{line}}<br></template>
</div>
You have to transform your data before rendering it with Vue.
const lines = stringWithLineBreaks.split('\n')
// then render the lines
I can give a more specific answer if you share the code you're working with.

Categories