Property Undefined on Vue Component - javascript

Getting an error that project is undefined when trying to render out some text using {{project.projectSummary}} in my ProjectContainer component. I'm guessing when the component is initialized project is undefined because it shows up in VueTools fine on my component.
So next, I try to set v-if="resource.project" on the parent component
<template v-if="resource.project">
<div class="resourceContainer">
<resource-card :resource="resource" :showResourceBtn="showResourceBtn"></resource-card>
<project-container :project="resource.project"></project-container>
</div>
</template>
<script>
import { firebaseAuth, database } from '../../database/database'
import Vue from 'vue'
import VueFire from 'vuefire'
import ResourceCard from '../ResourceCard/ResourceCard'
import ProjectContainer from './Project'
Vue.use(VueFire);
export default {
name: 'Resource',
components: {
ResourceCard,
ProjectContainer
},
data () {
return {
showResourceBtn: true
}
},
computed: {
fbUser () {
return firebaseAuth.currentUser
}
},
created () {
// Load resource
this.$bindAsObject('resource', database.ref('/resources/' + this.$route.params.resourceKey));
}
}
</script>
But this isn't working either. Gives me a warning in the console that Invalid prop: type check failed for prop "project". Expected Object, got Undefined.
Any thoughts? Thanks

Related

How to use Oruga components (and progamatic components) in Vue 3 with the Options API?

I am finally starting to play around with Vue 3 and am migrating an app from Vue 2 + Buefy to Vue 3 + Oruga.
In the Oruga docs it looks like every example for importing a component or programatic component uses the composition API.
The Notification component for example imports the programatic component into the app/components/view's setup function which is using the composition API
import { defineComponent } from 'vue'
import { useProgrammatic } from '#oruga-ui/oruga-next'
import NotificationForm from './_notification-form.vue'
export default defineComponent({
setup() {
const { oruga } = useProgrammatic()
function toast() {
oruga.notification.open({
message: 'Something happened correctly!',
rootClass: 'toast-notification',
position: 'top'
})
}
The other examples show the Vue app importing either all of Oruga, or each component at a root level:
import { createApp } from 'vue'
import Oruga from '#oruga-ui/oruga-next'
import '#oruga-ui/oruga-next/dist/oruga.css'
createApp(...).use(Oruga);
------------------
import { createApp } from 'vue'
import { OAutocomplete, OSidebar } from '#oruga-ui/oruga-next'
import '#oruga-ui/oruga-next/dist/oruga.css'
createApp(...)
.component(OAutocomplete)
.component(OSidebar)
I however, would like to import components into my components/views which are using the options API (which I prefer), how would I do that?
I tried to import things as I would in in Vue2, but I get warnings like: 'Failed to resolve component: o-button'
import { OButton } from '#oruga-ui/oruga-next';
export default {
components: {
OButton
}
}
Or in the case of the programmatic notification I get 'Uncaught TypeError: Cannot read properties of undefined (reading 'open')':
import { useProgrammatic } from '#oruga-ui/oruga-next';
const { oruga } = useProgrammatic()
export default {
methods: {
onAlert() {
oruga.notification.open({
message: 'Something happened correctly!',
rootClass: 'toast-notification',
position: 'top'
})
},
},
}
Vue composables should be called inside the setup function or setup script only, so calling useProgrammatic under the script tag is wrong, what you should do instead is something like this:
import { useProgrammatic } from '#oruga-ui/oruga-next';
export default {
setup() {
const { oruga } = useProgrammatic()
return {
oruga
}
},
methods: {
onAlert() {
this.oruga.notification.open({
message: 'Something happened correctly!',
rootClass: 'toast-notification',
position: 'top'
})
},
},
}
and about calling the components, I tested what you did and it works fine, I think you need to re-install the package because maybe something went wrong
Please check this sample for more details: stackblitz

Vue register component keep failing

I'm doing a FE based on [THIS VUE TEMPLATE][https://www.creative-tim.com/product/vue-material-dashboard-pro]
I am trying to register a component locally, but I keep getting the error:
"103:5 error The "BFCookieCard" component has been registered but
not used"
I did not have any success with the answers shared in:
I'm getting an error of 13:5 error The “Home” component has been registered but not used vue/no-unused-components
component has been registered but not used vue/no-unused-components
Vue component defined but not used error message. How do I use it properly?
Remove 'component has been registered but not used' in eslint for Vue.js
My Files are as follows:
BFConsentCookie.vue
<template>
<h1> HELLO </h1>
</template>
<script>
export default {
name: "bf-cookie-card",
data() {
return {};
},
beforeMount() {
},
}
Login.vue
<template>
<div>
<bf-cookie-card>
</bf-cookie-card>
</div>
</div>
</template>
<script>
import { BFCookieCard} from "#/components";
export default {
components: {
BFCookieCard,
},
data() {
return {};
},
}
index.js
import BFCookieCard from "./Cards/BFCookieCard.vue";
export {
BFCookieCard
}
The problem is the capital F in BFCookieCard, replace it with BfCookieCard.
In your login.vue you can also import your component like that:
components: {
BfCookieCard: () => import('path to component file.vue'),
},

Unable to initialise LiveLike chat in Vue 3, Failed to resolve component

I'm running into the following error when trying to initialise the LiveLike Chat.
[Vue warn]: Failed to resolve component: livelike-chat
Stripped back view:
<template>
<livelike-chat></livelike-chat>
</template>
<script>
import LiveLike from "#livelike/engagementsdk";
import { onMounted } from "vue";
export default {
setup() {
onMounted(() => {
let clientId = 'somelongclientidsuppliedbylivelike';
LiveLike.init({ clientId });
});
}
};
</script>
The livelike chat is supposed to initialise to a custom element, <livelike-chat>, the trouble is Vue sees that and tries to find the component livelike-chat. How do I "tell" Vue to ignore that element, its not a component but a tag reserved for LiveLike?
You could use an isCustomElement config for this:
// main.js
const app = createApp({})
app.config.isCustomElement = tag => tag === 'livelike-chat'

Uncaught error when trying to embed a Vega chart in Vue + Vuex project

I am trying to use vega-embed within a Vue.js (together with vuex for state management) project. Basically the backend serves a Vega json object which is picked up by the frontend via HTTP GET request with a click event. However I have to click twice to get the plot displayed and the first click event always triggers an error "Uncaught (in promise) TypeError: Cannot read property '$schema' of null". Can someone help me debug? Very much appreciated. Details shown below:
The vue component file:
<template>
<button #click.native="fetchCars(); displayVegaPlot()">fetch cars</button>
<div id="vega-example"></div>
</template>
<script>
import {default as vegaEmbed} from 'vega-embed'
import {
mapState
} from 'vuex'
export default {
name: 'VegaExample',
props: {
component_msg: String
},
methods: {
fetchCars () {
this.$store.dispatch('fetchCars')
},
displayVegaPlot () {
vegaEmbed('#vega-example', this.vega_cars, {actions: false})
}
},
computed: {
...mapState([
'vega_cars'
])
}
}
</script>
... and the store js file:
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
strict: true,
state: {
error: '',
vega_cars: null
},
mutations: {
SET_CARS: (state, cars) => {
state.vega_cars = cars
},
SET_ERROR: (state, error) => {
state.error = error
}
}
actions: {
fetchCars: (context) => {
axios.get(`vega_cars`)
.then(response => context.commit('SET_CARS', response.data))
.catch(error => context.commit('SET_ERROR', error))
}
}
Thanks a lot for the comment from #TommyF, after some doc reading I think I figured out the solution (apparently as a newcomer to web app dev and Vue I didn't know Vue offers a special watch facility). So in the component Vue file, instead of declaring a method displayVegaPlot to call imperatively, a watch can be setup to do the display the Vega plot, as soon as vega_cars changes value:
watch: {
vega_cars: (spec) => {
console.log('$store.state.vega_cars changed value')
if (spec) {
vegaEmbed('#vega-example', spec, {actions: false})
}
}
}
and of course ...mapState(['vega_cars']) needs to be put in computed.

vue js 2 : how to communicate between store and a component

I am a beginner with vue js.
i m trying to handle errors from component and display it on other component.
Apparently handling work becase i can see data in my store
With a props to my component (error.vue), it handle it in the data variable.
But after that it can t display it on my vue .
Why ?
Here is my code :
My store is :
var store = new Vuex.Store(
{
state: {
errors:{}
},
mutations: {
setErrors(state, error) {
for(var err in error) {
state.errors[err] = error[err]
}
}
}
})
my vue where i put my error component:
<template>
<div id="wrapper">
<div class="container">
<error_handling></error_handling>
<router-view></router-view>
</div>
</div>
</template>
<script>
import Error from './components/Error.vue'
import store from './store';
export default {
components: {
'error_handling': Error
},
data() {
return {
erreurs: store.state.errors
}
}
}
</script>
my error vue :
<template>
<div>
<ul>
{{errors_handling}}
<!--<li v-for="error in errors_handling">{{ error }}</li>-->
</ul>
</div>
</template>
<script>
export default {
props: ['errors_hand'],
data() {
return {
errors_handling: this.errors_hand
}
}
}
</script>
Based on your provided code.
You are getting a state of "errors"
You are not committing a mutation
By not committing a mutation, you are not changing a state
Docs: Vuex Mutations
Store.js
var store = new Vuex.Store(
{
state: {
errors:{}
},
mutations: { // Change the state object
setErrors(state, error) {
for(var err in error) {
state.errors[err] = error[err]
}
}
},
getters:{
// getters gets the current object of state
GetErrors(state) //by default getters get state as first paramater
{
return state.errors;
}
},
})
Error Component
<script>
export default {
computed:{
errors_handling(){
return this.$store.getters.GetErrors;
}
},
methods:{
//commit your mutation or dispatch when using action
ChangeState(error){
this.$store.commiit('setErrors',error);
}
}
}
</script>
But you must use actions to run it asyncronously
I would use a bus to pass errors from wherever they occur to the error component. This way the error component need not interact with your store or any other component directly, and can manage its own internal state easily. You also would not need to include the error component in any other component.
This example assumes that you are wanting only a single Error Component instance in your UI. I would put the error component instance in your main App template and have it show or hide itself based on whether it has any non-handled errors.
To declare a simple bus...
in file errorBus.js
import Vue from 'vue'
const errorBus = new Vue();
export default {
errorBus
}
Wherever an error occurs that you want to pass to the error component, use...
import errorBus from './errorBus.js'
errorBus.errorBus.$emit("notifyError", { msg: 'An error has occurred'});
In the error component...
import errorBus from './errorBus.js'
and within the component definition...
created: function() {
errorBus.errorBus.$on("notifyError", function(error) {this.addError(error)};
},
data () {
return {
errors: []
};
},
methods: {
addError: function(error) {
this.errors.push(error);
}
}
With this mechanism in place, you could easily handle different errors in different ways by passing additional information in the error object - for example, you could add {handling: "toast", priority: 0} which would cause the error component to immediately toast the error.
If you use this to toast, consider having the errors remain for later viewing after the error is toasted - I have always wanted something like an error drawer that I could open at my leisure instead of having to handle a toast immediately before it disappears.

Categories

Resources