How to use router-link in vue js? - 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

Related

Vue Conditional rendering giving error against conditional

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.

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

Vuetify: How to use my own component inside of a Vuetify Expansion Panel Component

I'm just starting with VueJS and Vuetify, so maybe this is a very basic error..
I'm trying to use the vuetify exansion panel component: https://vuetifyjs.com/components/expansion-panels
Basically I want to define my own component to use as v-expansion-panel-content but I can't make it work.
What I could make work was define 2 components, one for the header and another one for the content and use them inside of the v-expansion-panel-content
But when I try to encapsulate all in 1 component the expansion panel shows the header but it will not expands to show the item content.
Thanks in advance.
CodePen: https://codepen.io/arcard/pen/YEJrZd
HTML:
<v-expansion-panel-content>
<div slot="header">Item - without use of component - works OK</div>
<v-card>
<v-card-text class="grey lighten-3">Lorem ipsum dolor sit amet.</v-card-text>
</v-card>
</v-expansion-panel-content>
<v-expansion-panel-content>
<vc-prod-header slot="header"></vc-prod-header>
<vc-prod-content></vc-prod-content>
</v-expansion-panel-content>
<!-- this one doesn't work -->
<vc-exp-panel-comp></vc-exp-panel-comp>
</v-expansion-panel>
</div>
JS:
Vue.component('vc-prod-header',{
template: `
<div>Item - using 2 components: one for the header and one for the content - works OK</div>
`
});
Vue.component('vc-prod-content',{
template: `
<v-card>
<v-card-text class="grey lighten-3">component 2: content</v-card-text>
</v-card>
`
});
Vue.component('vc-exp-panel-comp',{
template: `
<v-expansion-panel-content>
<div slot="header">component title - this one will not expand to show the content</div>
<v-card>
<v-card-text class="grey lighten-3">component body: this is now showing</v-card-text>
</v-card>
</v-expansion-panel-content>
`
});
new Vue({
el: '#example'
})

How to trigger a method at component opening in vuejs?

I have a main component that is used to display items using a loop:
<v-list-tile v-for="(item, index) in items" :key="item.title">
...
<report type="item.type"> </report>
</v-list>
The report component is used to report abuse on the system, and report type may vary depending on the item from the parent loop.
As users are very unlikely to use report on a regular basis I would like to only load v-select elements when the Dialog (modal) is opened.
Using created or mounted triggers the loading method everytime the report component is generated and not when the report component is opened.
Is there a smart way to prevent this and only have the loading method within report being triggered only when the component is opened.
=== Report.vue file ===
=== This file is loaded in the parent component
<template lang="html">
<v-dialog v-model="dialog" persistent max-width="800px" lazy>
<v-btn icon slot="activator">
<v-icon>error_outline</v-icon>
</v-btn>
<v-card>
<v-card-title>
<div class="headline"><v-icon large>error_outline</v-icon> Reporting</div>
</v-card-title>
<v-card-text>You are about to report the following {{ reportType }}: "<i>{{ reportContent.title }}</i>"
<v-container v-if="this.$store.getters['report/getLoadedState']" grid-list-md >
<v-layout wrap>
<v-flex xs12 sm12>
<v-select
label="Select a reason"
required
cache-items
:items="items"
item-text="title"
item-value="id"
></v-select>
</v-flex>
<v-flex xs12 sm12>
<v-text-field
label="Please provide additional information here"
multi-line></v-text-field>
</v-flex>
</v-layout>
</v-container>
<v-container v-else grid-list-md>
<v-layout>
<v-flex xs12 sm12>
Loading
</v-flex>
</v-layout>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="green darken-1" flat="flat" #click.native="cancel">Cancel</v-btn>
<v-btn color="green darken-1" flat="flat" #click.native="report">Report</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
name: 'report',
data () {
return {
dialog: false,
items: this.$store.getters['report/getItems']
}
},
props: ['reportType', 'reportContent'],
methods: {
cancel () {
this.dialog = false
},
report () {
this.dialog = false
},
loadReasons (type) {
if (!this.$store.getters['report/getLoadedState']) {
this.$store.dispatch('report/setItems', type)
}
}
}
}
</script>
<style lang="css" scoped>
</style>
PS 1: I'm not using JQuery and do not intend to use it
PS 2: Calling the method outside of the report component is not an option as I want to maximize reusability of this compenent and only pass arguments to it using props
How I have done this in the past is to use a "dynamic component." Vue uses a special syntax for dynamic components <component v-bind:is="currentView"></component> see: Vue dynamic components
You can set the "currentView" property to null and then on a button click another event set the currentView to report. Doing it this way will allow you to use the mounted method as the component is not rendered or created until it is dynamically called.
<component :is="myComponent"></component>
<v-btn #click="loadComponent">Show Report</v-btn>
then...
data:{
myComponent: null;
},
methods: {
loadComponent: function(){
this.myComponent = 'report';
}
}
P.S. You can of course use this method to render any other components in the same place. i.e. you can set the 'currentView' to the name of any available component and it will be instantly rendered in its place.
I ended up using a watch on the boolean managing the dialog...
Make a function which loads the v-select. Don't initialize it just create it. Now whenever user clicks the report model you can initialize multiple functions using v-on:click or #click.
For example :
<div v-on:click="return function() { fn1('foo');fn2('bar'); }()"> </div>
This solution can also be found on :
Stackoverflow Link