Passing a axios request to a child component in vue.js - javascript

I am breaking my head in this. I am new to a fullstack project involving fullstack with vue.js and node.js.
My problem is: My get request is functioning and fetching data from database, but, I can't pass these data's via props on a component. It keeps telling that "paciente" is not defined.
Here's the code:
<div><div v-for="(paciente, index) in pacientes" :key="index">
<div class="blocoDeInformacao">
<h2 class="nomePessoa">{{paciente.nome}}</h2>
<h4 class="cpfPessoa">{{paciente.cpf}}</h4>
<div class="bordinha"></div>
<span class="botoes">
<button class="botao " #click="s1 = 1, bExcluir = false"><img class="icone" src="#/assets/paper.png" alt="editarPaciente"></button>
<button class="botao" #click="bExcluir = true, bCerto = paciente.id"><img class="icone" src="#/assets/trash.png" alt="excluirPaciente"></button>
</span>
<div class="excluir" v-show="bExcluir == true && bCerto == informacaoPessoa.id">
<img class="alertIcon" src="#/assets/alert.png" alt="iconeAlerta">
<h2 class="confirmacaoExclusao">Quer realmente excluir esse paciente?</h2>
<div>
<button class="botaoEscolha" #click="confirmacaoExcluir(paciente.idpaciente)">Sim</button>
<button class="botaoEscolha" #click="bExcluir = false">Não</button>
</div>
</div>
</div>
</div></div>
</div>
</div>
</div>
<div v-else-if="s1 == 1">
<editarPaciente :nomePessoa="paciente.nome"
:cpfPessoa="paciente.cpf" :senhaPessoa="paciente.senha" :id="paciente.idpaciente" :key="paciente.idpaciente"/>
</div>
and the props from components:
export default {
name: 'editarPaciente',
components: {
},
props: {
nomePessoa: String,
cpfPessoa: String,
senhaPessoa: String,
id: String
},
}
</script>

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)

Problem with Axios PUT and GET request, sometimes work well, sometimes doesn't

I'm using Axios to fetch data from a server, I'm trying to do a PUT request and I need to get data info from 3 tables in order to fill the form, when I do the PUT it sometimes works and sometimes doesn't, but when I open the browser terminal to debug the problem, the PUT request always works, also I notice that another component without nested GET requests always works fine, but I can't fetch the data from the server if those GET requests aren't nested.
Here is my script code, I don't know what I'm doing wrong with this.
<template>
<div class="container-fluid">
<div style="margin:40px;background-color:rgba(255, 255, 255, 0.7);">
<div class="row">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item">Usuarios</li>
<li class="breadcrumb-item">Roles</li>
<li class="breadcrumb-item"><a v-bind:href="rol_url">{{rol_name}}</a></li>
<li class="breadcrumb-item active" aria-current="page">Editar Rol</li>
</ol>
</nav>
</div>
<div class="row">
<div class="col-md-8 offset-md-2" style="margin-bottom:80px;">
<div class="row">
<div class="col">
<button onclick="window.history.back();" class="btn btn-primary" style="background:#003e1e;border-color:#003e1e;">
<font-awesome-icon icon="arrow-left" size="lg"></font-awesome-icon>
</button>
</div>
</div>
<div> </div>
<div class="row justify-content-center">
<div class="col-5 align-self-center">
<form>
<div class="form-group">
<label for="rolName">Nombre del rol:</label>
<input v-model="rol_name" type="text" class="form-control" id="rolName" aria-describedby="rolName" placeholder="Nombre">
</div>
<div class="form-group">
<label for="rolModules">Modulos del rol:</label>
<multiselect v-model="rol_mod" :options="modules" :multiple="true" :close-on-select="true" :clear-on-select="false" :hide-selected="true" :preserve-search="true" placeholder="Seleccione los modulos" label="name" track-by="modulo" :preselect-first="false">
</multiselect>
</div>
<div v-for='(module, index) in rol_mod' :key='index' class="form-group">
<label for="rolModules">Permisos de {{module.name}}</label>
<multiselect v-model="module.permisos" :options="permits" :multiple="true" :close-on-select="true" :clear-on-select="false" :hide-selected="true" :preserve-search="true" placeholder="Seleccione los permisos del modulo" label="name" track-by="_id" :preselect-first="false">
</multiselect>
</div>
<div class="form-group">
<label for="rolStates">Estado del rol:</label>
<multiselect v-model="rol_state" :options="states" track-by="name" label="name" :searchable="false" :close-on-select="true" :show-labels="true" :placeholder="rol_state_get">
</multiselect>
</div>
<div class="form-group">
<label for="permitDescription">Descripción:</label>
<textarea v-model="rol_description" class="form-control" aria-label="permitDescription"
placeholder="Descripción" :rows="6" :max-rows="10"></textarea>
</div>
<div> </div>
<div class="row justify-content-center">
<div class="col-4 text-center">
<button class="btn btn-primary" v-on:click="submit()" style="background:#003e1e;border-color:#003e1e;">
<font-awesome-icon icon="save" size="lg"></font-awesome-icon>
Guardar
</button>
</div>
<div class="col-4 text-center">
<a class="btn btn-primary" style="background:#003e1e;border-color:#003e1e;" v-bind:href="rol_url">
<font-awesome-icon icon="times-circle" size="lg"></font-awesome-icon>
Cancelar
</a>
</div>
</div>
<div> </div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
const axios = require('axios');
var API_IP = process.env.VUE_APP_API_IP
export default {
components: {
Multiselect
},
data () {
return {
rol_auditoria: {},
modules: [],
permits: [],
rol_name: "",
rol_state: "",
rol_state_get: "",
rol_description: '',
states: [
{ name: "Activo", activo: "true" },
{ name: "Inactivo", activo: "false" }
],
rol_mod: [],
rol_url: ""
}
},
mounted () {
axios
.get(API_IP+'/rol/'+this.$route.params.id)
.then(response => {
this.rol_auditoria = response.data.data.auditoria;
this.rol_name = response.data.data.nombre;
this.rol_state = response.data.data.activo;
response.data.data.activo? this.rol_state_get="Activo" : this.rol_state_get="Inactivo";
this.rol_description = response.data.data.descripcion
this.rol_id = response.data.data._id
this.rol_url = "/roles/"+response.data.data._id
for (var k in response.data.data.modulos){
var mod_info = {}
console.log(response.data.data.modulos[k].modulo.nombre);
mod_info["_id"] = response.data.data.modulos[k]._id
mod_info["modulo"] = { "_id" : response.data.data.modulos[k].modulo._id }
mod_info["name"] = response.data.data.modulos[k].modulo.nombre
var mod_per = []
for (var j in response.data.data.modulos[k].permisos){
var perms = {}
perms["_id"] = response.data.data.modulos[k].permisos[j]._id
perms["name"] = response.data.data.modulos[k].permisos[j].nombre
mod_per.push(perms)
}
mod_info["permisos"] = mod_per
this.rol_mod.push(mod_info)
}
axios
.get(API_IP+"/module/")
.then(response => {
for(var k in response.data.data){
var mod = {}
mod["modulo"] = { "_id" : response.data.data[k]._id }
mod["name"] = response.data.data[k].nombre;
this.modules.push(mod);
}
axios
.get(API_IP+"/permit/")
.then(response => {
for(var k in response.data.data){
var per = {}
per["name"] = response.data.data[k].nombre;
per["_id"] = response.data.data[k]._id;
this.permits.push(per);
}
});
});
})
},
methods: {
submit: function() {
axios
.put(API_IP+"/rol/"+this.$route.params.id, {
auditoria: this.rol_auditoria,
activo: this.rol_state.activo,
_id: this.rol_id,
nombre: this.rol_name,
descripcion: this.rol_description,
modulos: this.rol_mod
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
this.$router.push({ name: 'showrol', params: { id: this.rol_id} });
}
}
}
</script>
This may be a long shot without having information from the console output and the actual info or errors being returned from the GET requests, but I noticed a lot of "this" use on your code.
You are double nesting axios calls, which are async. "this" tends to be hard to debug in javascript, even if youre using arrow functions which should be relatively safe.
Please try to add:
let self = this;
Before you start your GET requests, and use "self" instead of "this" inside your promises.
This may be obvious, but I dont see you calling this.submit() anywhere in your code. Where inside the GET callbacks are you calling SUBMIT for the PUT request?

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.

Displaying information using v-if from an API

I want the tag that currently says true or false, I want it to say "FREE" if it's free and say "PAID" if it's not.
https://www.eventbriteapi.com/v3/events/search/?location.address=45+Depot+Ave.++Bronx%2C+NY+10457&location.within=50mi&token=6RXWSSZPE4APEYSWTJJF
I'm getting a response from data.events.is_free in the form of a boolean that's true if free and false if not.
I know I have nothing between the v-if tags, but the whole thing goes blank if add anything.
HTML:
<div id="app" class="container">
<h1 id="header" class="title is-1 has-text-centered">Event Lookup for ECH</h1>
<div v-for="event in info">
<h2 class="title is-4" id="eventName">{{ event.name.html }} <span v-if="" class="tag is-success">{{ event.is_free }}</span></h2>
<div id="eventDescription">{{ event.description.text }}</div>
<div id="eventDateTime">{{ event.start.local }} - {{ event.end.local }}</div>
</div>
</div>
Vue / JS
// The plan is to make this more extensive later
// https://www.eventbriteapi.com/v3/events/search/?location.address=45+Depot+Ave.++Bronx%2C+NY+10457&location.within=50mi&token=6RXWSSZPE4APEYSWTJJF
// This is a random address...
const baseUrl = 'https://www.eventbriteapi.com/v3/events/search/?location.address=45+Depot+Ave.++Bronx%2C+NY+10457&location.within=50mi&token=6RXWSSZPE4APEYSWTJJF';
new Vue({
el: '#app',
data () {
return {
info: null
}
},
mounted () {
axios
.get(baseUrl)
.then(response => (this.info = response.data.events))
},
computed () {
isFree
if (response.data.events.is_free == true) {
return true;
}
else {
return false;
}
}
})
https://codepen.io/Mortiferr/pen/qyajJd
Here's a link to my Codepen.
You can use v-if and v-else.
<div id="app" class="container">
<h1 id="header" class="title is-1 has-text-centered">Event Lookup for ECH</h1>
<div v-for="event in info">
<h2 class="title is-4" id="eventName">{{ event.name.html }}
<span v-if="event.is_free" class="tag is-success">Free</span>
<span v-else class="tag is-success">Paid</span>
</h2>
<div id="eventDescription">{{ event.description.text }}</div>
<div id="eventDateTime">{{ event.start.local }} - {{ event.end.local }}</div>
</div>
</div>
You don't need a computed property for this. You can use v-if and v-else.
Alternatively, if you know that you will only have the text "FREE" or "PAID" without any markup needed, you might want to consider just using a ternary expression:
<span class="tag is-success">{{event.is_free ? "FREE" : "PAID"}}</span>
I added a cost class just to make it a little easier to see.
const baseUrl = 'https://www.eventbriteapi.com/v3/events/search/?location.address=45+Depot+Ave.++Bronx%2C+NY+10457&location.within=50mi&token=6RXWSSZPE4APEYSWTJJF';
new Vue({
el: '#app',
data() {
return {
info: null,
isFree: false
}
},
mounted() {
axios
.get(baseUrl)
.then(response => {
this.info = response.data.events;
this.isFree = response.data.events
})
}
})
.cost {
color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<div id="app" class="container">
<h1 id="header" class="title is-1 has-text-centered">Event Lookup for ECH</h1>
<div v-for="event in info">
<!-- Using v-if/else -->
<h2 class="title is-4" id="eventName">{{ event.name.html }}
<span v-if="event.is_free" class="cost tag is-success">FREE</span>
<span v-else class="cost tag is-success">PAID</span>
</h2>
<!-- Using ternary -->
<h2 class="title is-4" id="eventName">{{ event.name.html }}
<span class="cost tag is-success">{{event.is_free ? "FREE" : "PAID"}}</span>
</h2>
<!--<div id="eventDescription">{{ event.description.text }}</div>-->
<div id="eventDateTime">{{ event.start.local }} - {{ event.end.local }}</div>
</div>
</div>

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