Vue 2, Cannot reference Prop Object in template - laravel

Problem: Although from the Vue DevTools I am passing the prop correctly and the router-view component has access to the data that it needs and in the correct format, whenever I try to access any of the data properties from within the template I get Uncaught TypeError: Cannot read property 'name' of null. It's really confusing because from the DevTools everything is a valid object and the properties are not null.
App.js
const game = new Vue({
el: '#game',
data: function() {
return {
meta: null,
empire: null,
planets: null
};
},
created: () => {
axios.get('/api/game').then(function (response) {
game.meta = response.data.meta;
game.empire = response.data.empire;
game.planets = response.data.planets;
});
},
router // router is in separate file but nothing special
});
main.blade.php
<router-view :meta="meta" :empire="empire" :planets="planets"></router-view>
script section of my Component.vue file
export default {
data: function() {
return {
}
},
props: {
meta: {
type: Object
},
empire: {
type: Object
},
planets: {
type: Array
}
}
}
Any ideas? Thanks in advance.

Because of your data is async loading so when my Component.vue renders your data in parent component may not be there. So you need to check if your data is loaded. You can try this code:
{{ meta != null && meta.name }}
PS: Your created hook should be:
created() {
axios.get('/api/game').then((response) => {
this.game.meta = response.data.meta;
this.game.empire = response.data.empire;
this.game.planets = response.data.planets;
});
},

router-view is a component from view-router which can help render named views. You can not pass empire and planets to it as those are props of your component.
You have to have following kind of code to pass empire and planets to your component:
<my-component :meta="meta" :empire="empire" :planets="planets"></my-component>
You can see more details around this here.

Related

vue not loading data into child component

I've a hard time in understanding the methods of vue. In my put-request users can edit, delete images. In parent component the get-request loads the images and the are pushed to an image-gallery (the child-component) via properties. In my set up the console.log is always empty.
//PARENT COMPONENT
<template>
<div class="form-group">
<image-gallery :serverData="serverMap"/>
</div>
</template>
<script>
import ImageGallery from './ImageGallery.vue';
export default {
components:{ImageGallery},
data: () => ({
serverMap: {
title: '',
file: ''
}
}),
mounted () {
//AJAX ETC get servermap
.then((response) => {
this.serverMap = response.data
})
}
Just a normal straight parent-child situation. Here under the child-component
<template>
</template>
<script>
export default {
name: 'ImageGallery',
//incoming data
props: {
serverData: {
type: Object,
default () {
return {
hasLabels: true,
isHorizontal: false
}
}
}
},
created: function () {
this.loadImages()
},
methods: {
loadImages () {
console.log(this.serverData.file)
//do something with the serverData
//prepare for fileReader function
//together with new image validation
}
}
The method 'loadImages' should be automatically delevering the serverData via computed.But is doesn t. Who can help?
There is race condition.
Either not render a child until data is available; serverMap needs to be null instead of empty object in order to be distinguished from populated object:
<image-gallery v-if="serverMap" :serverData="serverMap"/>
Or delay data access in a child until it's available instead of doing this immediately in created:
watch: {
serverData(data) {
if (data)
this.loadImages()
}
}

Vue error in Laravel blade: Property or method "type" is not defined on the instance but referenced during render

Would like some assistance on this error I am getting in Vue: Property or method "type" is not defined on the instance but referenced during render.
Vue code:
Vue.component('content-text-area', {
data() {
return {
type: document.getElementById('type').value
}
},
mounted: function () {
console.log(this.type)
},
template: '<p>Testing</p>'
})
new Vue({ el: '#content-text-area-div' });
Blade code:
<div id="content-text-area-div">
<content-text-area v-if="type === 'article'"></content-text-area>
</div>
There is 2 issues to fix here:
type should be defined in the parent component:
new Vue({
el: '#content-text-area-div',
data() {
type: '' // Initialize it here
}
});
You can't refrence the DOM in data, as it is instantiated before the DOM is built. So you should read and assign the value in the mounted hook.
See the Vue lifecycle.
mounted() {
this.type = document.getElementById('type').value
}
Or even better (the "Vue way"):
<input ref="type"/>
mounted() {
this.type = this.$refs.type.value;
}
See also: Refs

VueJs Props not read when setting initial value in data

I've been struggling a lot lately on how to set the initial value in local data property. I'm using Laravel with Vue.js
I have this code below in my component
props: {
user: '',
dates: {}
},
data() {
return {
bloodTypes: {},
bloodComponents: {},
data: {
order_date: this.dates.order_date,
order_details: []
},
}
},
I'm trying to get the value of the props 'dates' into the local variable.
order_date: this.dates.order_date
return undefined. Although you can see in the picture below that the props have been initialized.
I want to know how to get the props value into my local data
variables.
A little late to the party but I thought I would share my workaround when working with async data:
// in the parent component
<template>
<child :foo="bar" v-if="bar" />
</template>
Then you can safely follow the guide's recommended ways to initialize data value with props as so:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
Happy coding!
try this:
watch: {
dates: {
handler(val){
this.data.order_date = val.order_date;
},
deep: true
}
}
I finally solved this with, I have changed some variable name so that I won't be confused. It seems that you need to put props under watch in order to manipulate it.
props: [ 'user','blood_components', 'blood_types', 'current_date'],
data() {
return {
list: {
order_date: '',
}
}
},
watch:{
current_date: function() {
let self = this
self.list.order_date = this.current_date
}
},
How about using computed instead?
props: [
'user',
'dates'
],
data() {
return {
bloodTypes: {},
bloodComponents: {}
}
},
computed: {
data: function() {
return {
order_date: this.dates.order_date,
order_details: [] <= should be changed to something dynamically changed object
}
}
}
The problem is your props are not declared correctly.
props: {
user: '', // <-- DON'T DO THIS
dates: {} // <-- DON'T DO THIS
}
When using the object syntax for props, each key is the prop name, and the value is either a data type (e.g., String, Number, etc.):
props: {
user: String,
dates: Object
}
...or an object initializer (which allows you to specify data type and default value) like this:
props: {
user: {
type: String,
default: ''
},
dates: {
type: Object,
default: () => ({})
}
},
demo
Assign the values in the created or mounted hook.
Example: https://github.com/jserra91/vuejs_wrapper_elements_and_unit_tests/blob/master/src/components/ae/components/ea-select/EaSelect.vue

{{ obj.data }} not displaying in vue template after axios get

I am trying to build a carousel using Laravel 5.6 and Vue.js. I can call the data from db, and console.log response.data. It works like expect it to. Script below.
<script>
$(document).ready(function() {
$("#availability").owlCarousel();
});
export default {
props: {
areaId: null,
tutorId: null,
},
data () {
return {
availability: []
}
},
methods: {
getAvailability () {
var that = this;
axios.get( '/' + this.areaId + '/' + this.tutorId + '/availability').then((response) => {
console.log(response.data)
that.availability = response.data;
});
}
},
mounted () {
this.getAvailability();
}
}
</script>
Now I would expect to be able to display the data like
{{availability.monday_begin}}
but it displays nothing, empty tags.
When I add a second .data to response, so change
that.availability = response.data;
to
that.availability = response.data.data;
The data object shows up as undefined in the vue-dev tools, and {{ availability.monday_begin }} throws an error cannot read property of undefined.
I also tried adding a v-if to the template, based on a couple different articles I read, but nothing I tried worked.
Thanks for your help.

How can I access Vue JS props in a method in a component?

I may be wrong in my understanding of props but I can't seem to be able to pass a prop to a component and then use the value in a method?
So far I am able to get data from a fixed API and output everything from the vue component, now I would like the api source to be dependent on the variable passed to the component.
My blade template:
<projectstatuses :userslug="this-user" :projectslug="this-project"></projectstatuses>
Then in my Vue Component:
export default {
props: {
userslug: {
type: String,
default: "other-user",
},
projectslug: {
type: String,
default: "other-project",
}
},
data() {
return {
statuses : [],
}
},
created(){
this.getStatuses();
},
methods : {
getStatuses(){
console.log(this.userslug);
console.log(this.projectslug);
axios.get('/api/' + this.userslug + '/' + this.projectslug)
.then((response) => {
let statuses = response.data;
this.statuses = statuses.statuses;
console.log(response.data.statuses);
})
.catch(
(response) => {
console.log('error');
console.log(response.data);
}
);
}
}
}
In the console I get the default values, if I remove the default values I get undefined. I have tried removing the api method and simply console logging the values but I still get undefined. Is what I'm trying to do possible or have I completely misunderstood how props work?
You are trying to bind this-user and this-project as a properties not as values ,
So you will need to define them in the data object in the parent,
but if you want to pass this-user and this-project just as value remove the : try that:
<projectstatuses userslug="this-user" projectslug="this-project"></projectstatuses>
Dynamic-Props
Don't add : in your template:
<projectstatuses userslug="this-user" projectslug="this-project"></projectstatuses>
Vue will expect there's data bound to this-user.

Resources