Vue Conditional rendering giving error against conditional - vue.js

I am trying to learn Vue and am having trouble with conditional rendering. It is not breaking the app but it's giving me a console error.
Initially, character is an empty object.
I am trying to only render the card when a character exists (when a button is pressed). Currently I am getting the error
Error in render: "TypeError: Cannot read property 'length' of undefined"
Currently a card does not render until it is supposed to, but it is giving me those errors.
My Component is:
<template>
<v-card v-if="character" min-width="350" outlined>
<div class="d-flex flex-no-wrap justify-space-between">
<v-avatar class="ma-3" size="125" tile>
<v-img :src="character.image"></v-img>
</v-avatar>
<div>
<v-card-title class="secondary--text text-h6">{{
character.name
}}</v-card-title>
<v-card-subtitle class="secondary--text"
>Featured in {{ character.episode.length }} episodes</v-card-subtitle
>
<v-card-subtitle class="secondary--text pb-0 pt-0">{{
character.species
}}</v-card-subtitle>
<br />
<v-card-subtitle class="secondary--text pt-0"
>Origin: {{ character.origin.name }}</v-card-subtitle
>
</div>
</div>
</v-card>
<div v-else></div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
name: 'CharacterCard',
computed: mapGetters(['character'])
};
</script>

You said
Initially, character is an empty object.
and then you are trying to access character.episode.length which is giving the error "TypeError: Cannot read property 'length' of undefined" because character.episode is undefined, which has no property 'length'
There are several potential solutions. Here are a few:
(character.episode || []).length
character.episode && character.episode.length || 0
character.episode?.length || 0 note - may require some babel magic to get optional chaining to work. see: https://forum.vuejs.org/t/does-vue-cli-3-come-with-pre-configured-optional-chaining/42609
You could either put this directly in the template in-line, or it would may be better to put it in a computed property.

Related

[Vue warn]: The data property “x” is already declared as a prop. BootstrapVue

Could someone kindly advise me what I am doing wrong here?
I am using BootstrapVue to create radio buttons, in second image. In spite of I even didn't declare “checked” prop, still getting the error, in first image, for every buttons and also every form-groups in the project.
<template>
<div>
<b-form-group
label-cols="auto"
label="Peer Groups:"
class="pg-button-group"
label-class="text-primary"
label-size="sm"
v-if="peerGroups"
>
<b-form-radio-group
v-model="selectedPg"
:options="peerGroups"
button-variant="primary"
#change="pgSelectedByClick"
buttons
size="sm"
class=""
>
</b-form-radio-group>
</b-form-group>
</div>
</template>
The Error I got:
Buttons which I try to create:

How to use router-link in vue js?

I am a beginner to laravel-vue and I have a problem with router-link when I get data from the database to view, all things work correctly, but when I set the path to router link, it does not work.
The error is like:
Invalid prop: type check failed for prop “to”. Expected String, Object, got Undefined found in ---> RouterLink
Here is my template code:-
<template>
<v-card>
<v-card-title primary-title>
<div>
<h3 class="headline mb-0">
<router-link :to="data.path">{{data.title}}</router-link>
</h3>
<div class="grey--text">
{{data.created_at}}
</div>
</div>
</v-card-title>
<v-card-text>
{{data.body}}
</v-card-text>
</v-card>
</template>
This is my script:-
<script>
export default {
props:['data']
}
This is the form template view that I read questions inside it:-
<template>
<v-container fluid grid-list-md>
<v-layout row wrap>
<v-flex xs8>
<question v-for="question in questions"
:key="question.path"
:data=question
>
</question>
</v-flex>
sidebar
</v-layout>
</v-container>
</template>
And this is forum script:-
<script>
import question from './question'
export default {
data(){
return{
questions:{}
}
},
components:{question},
created(){
axios.get('/api/question')
.then(res=> this.questions = res.data.data)
.catch(error=>console.log(error.response.data))
}
}
</script>
Hello is says its expcting a string or an object ,, but it received an undefinded .
how to debug this ?
you should go back in steps
1. check the item you accessing maybe console log it : here it looks fine :to="data.path" but data could be empty or undefined
2 . check the prop for changes :it didnt change
3 . check prop passing :data=question aha !: here is the problem i think you are missing quotes here
it should be :data="question"
<question v-for="question in questions"
:key="question.path"
:data="question"
>
4. this would be where you check your request ... so always check your data with console log , how it is formatted what it contains and then use it ,, if its alright than you probably have soime syntax issue

Async calls with Apollo + Vue

Currently, I am trying to fetch data from my server, but the problem that I am running into is that the data takes a little time to fetch(in postman though it is instantaneous), longer than it takes the DOM to get mounted/loaded, and hence I get errors(data not defined) and nothing will load to the DOM.
If I console.log the data after the DOM has finished mounting then I can see it in the console, but I haven't been able to find a workaround where the component waits to render until the data is fetched.
I tried using a v-if statement, and writing it in a few different ways, but I am still getting the errors of the data not being defined, and it does not load either after the query is done fetching. Currently I've set the data to first be equal to null, which in JS is actually an object and it does get filled with the data after the fetching is done. I can see this in the console. Before that I tried a simple v-if="GameWeek", and with GameWeek defined as both an empty object and an empty array, but none of these will work, and force the component to wait until the data is done fetching.
My question is, is there any way to do this asynchronously, or better yet, make the component wait until the data has been fetched and then correctly load it to the DOM?
This is what my component looks like:
<template>
<!-- Highest climber & longest fall -->
<v-container>
<v-card class="card-container mx-auto" v-if="GameWeek !== null" :v-for="player in GameWeek" :key="player.player_id">
<!-- Top part of card -->
<v-list-item three-line>
<v-list-item-content>
<div class="card_top_section">
<v-avatar>
<img
src="https://cdn.vuetifyjs.com/images/john.jpg"
alt="John"
>
</v-avatar>
<div class="ml-3">
<p class="cardText player_name">
{{ player.player_name }}
</p>
<p class="cardText team_name">
{{ player.team_name }}
</p>
</div>
</div>
<div class="card_divs mt-7">
<p class="cardText points">
Points this week {{ player.points }}
</p>
<!-- <p class="points_green points">
</p> -->
</div>
<!-- Second Row Card -->
<div class="card_divs bottom_line">
<p class="cardText points">
Total points {{ player.total }}
</p>
<!-- <p class="points_green points">
</p> -->
</div>
</v-list-item-content>
</v-list-item>
</v-card>
</v-container>
</template>
<script>
import gql from 'graphql-tag'
export default {
name: 'PlayerCard',
data: () => {
return {
GameWeek: null
}
},
apollo: {
GameWeek: gql`query GameWeek {
GameWeek {
team_id
points
player_name
rank
previous_rank
total
player_id
team_name
}
}`
},
mounted() {
console.log('This is the gameweek', this.GameWeek)
},
}
</script>
Well, turns out this was easy to solve once I found the issue.
It was the : infront of the v-for statement. Once that was removed it all worked :)

Vuetify Unable to locate target when using attach on v-autocomplete

I want to use autocomplete from Vuetify and I am facing issues there because on my website I have one of the outer divs position: relative the dropdown part of the autocompelete, which is position: absolute, is attaching itself not to the bottom of the input but in random place.
Autocomplete has a prop attach which Specifies which DOM element that this component should detach to. Use either a CSS selector string or an object reference to the element. so I thought I use that and set it to class of my input.
And this works but it causes warning in the console
[Vuetify] Unable to locate target v-autocomplete
found in
---> <VMenu>
<VAutocomplete>
<VCard>
<VApp>
<Root>
Here the link where I reproduced the console warning.
If you are not using v-app component in App.vue, make sure to add data-app attribute to the div with the id app in App.vue.
The result will be like the following:
<template>
<div id="app" data-app>
.... All components, routers, views here ...
</div>
</template>
This worked for me:
<div id="app">
<v-app id="inspire">
<v-card>
<v-card-title class="headline font-weight-regular blue-grey white--text">Profile</v-card-title>
<v-card-text>
<v-subheader class="pa-0">Where do you live?</v-subheader>
<v-autocomplete
v-model="model"
:hint="!isEditing ? 'Click the icon to edit' : 'Click the icon to save'"
:items="states"
:readonly="!isEditing"
:label="`State — ${isEditing ? 'Editable' : 'Readonly'}`"
persistent-hint
prepend-icon="mdi-city"
:attach="'#attach'"
>
<template v-slot:append-outer>
<div id="attach"></div>
<v-slide-x-reverse-transition
mode="out-in"
>
<v-icon
:key="`icon-${isEditing}`"
:color="isEditing ? 'success' : 'info'"
#click="isEditing = !isEditing"
v-text="isEditing ? 'mdi-check-outline' : 'mdi-circle-edit-outline'"
></v-icon>
</v-slide-x-reverse-transition>
</template>
</v-autocomplete>
</v-card-text>
</v-card>
</v-app>
</div>

Vue Component prop in vuetify component

I am not able to pass data to my custom component, my component uses vuetify, currently I dont get any message:
MY component:
<template>
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-card>
<v-img
src="https://cdn.vuetifyjs.com/images/cards/desert.jpg"
aspect-ratio="2.75"
></v-img>
<v-card-title primary-title>
<div>
<h3 class="headline mb-0">{{ tenantName }}</h3>
<div>{{ tenantDescription }}</div>
</div>
</v-card-title>
</v-card>
</v-flex>
</v-layout>
</template>
<script>
export default {
data () {
return {
// ...
}
},
props: ['tenantImage', 'tenantName', 'tenantDescription']
}
</script>
And this is how I call in my view:
<tenant-card
imgSrc="https://fuckoffgoogle.de/wp-content/uploads/2017/12/cropped-logo_midres-1.png"
:tenantName="my Name is"
:tenantDescription="this is a description"
></tenant-card>
The component is registered I see it on my view just without any data.
I get this outside in the page source
<div class="layout" tenantimage="https://fuckoffgoogle.de/wp-content/uploads/2017/12/cropped-logo_midres-1.png" tenantname="my Name is" tenantdescription="this is a description">
...
The names of your properties are wrong:
<tenant-card
tenant-image="'https://fuckoffgoogle.de/wp-content/uploads/2017/12/cropped-logo_midres-1.png'"
:tenant-name="'my Name is'"
:tenant-description="'this is a description'">
</tenant-card>
HTML attribute names are case-insensitive. Any uppercase character will be interpreted as lowercase. So camelCased prop names need to use their kebab-cased equivalents.
Edit:
And as already mentioned by #Sergeon you have to add the extra '' to pass an string as a property value