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'
Related
I've been trying to follow the documentation for the API on the Vue 3 website which says to use app.provide('keyName',variable) inside your main.js file like so:
import App from './App.vue'
import { createApp } from 'vue'
import axios from 'axios'
const app = createApp(App)
app.provide('axios', axios)
app.use('Vue')
app.mount('#app')
Then inject and use it in your child component like so:
export default {
inject: ['axios'],
...
createUser (data) {
return this.axios.post('/users', data)
}
}
However doing so just gives me this error in my console:
Uncaught TypeError: Cannot read properties of undefined (reading 'post')
Is there anything I'm missing? I didn't see any about an import unless you're using the Composition API. Can provide / inject be called from within a .js file? I would expect so as long as its within a export default {} statement
Ive tried following the API to a "T" but it simply refuses to work for me. Also tried searching the web for solutions but everything I've found says what I'm doing should be working just fine.
It works, see the playground.
But is not absolutely necessary, since with the browser library version axios is globally defined and could be accessed also without inject
You could also save yourself some time with the vue-axios plugin.
Example
const { createApp } = Vue;
const myComponent = {
inject: ['axios'],
created() {
this.axios.get('/')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
},
template: '<div>My Component</div>'
}
const App = {
components: {
myComponent
}
}
const app = createApp(App)
app.provide('axios', axios)
app.mount('#app')
<div id="app">
<my-component></my-component>
</div>
<script src="https://unpkg.com/vue#3/dist/vue.global.js"></script>
<script src="https://unpkg.com/axios#1.3.1/dist/axios.min.js"></script>
Can someone help me out configuring a global function that I can call in all my Vue files?
When there is this in my Vue file:
#click="ModalShow.show('my-create')"
In the app.js I defined this constant:
const Modals = {
show(screen) {
alert(screen);
// other logic that i implement that should be triggered
},
};
But I keep getting:
TypeError: undefined is not an object (evaluating '_ctx.Modals.show')
What am I missing? It's a Vue project with the composition API
You can use provide/inject, first provide your function to your child components from the app (or parent component)
const Modal = {...}
const app = createApp({})
app.provide('Modal', Modal)
Then inject it into your component
import { inject } from 'vue'
export default {
setup() {
const Modal = inject('Modal')
return { Modal }
}
}
Or via script setup:
<script setup>
import { inject } from "vue";
const Modal = inject("Modal");
</script>
I'm trying to use tiptap as a child component and pass its content to the parent's v-model but tiptap's documentation only seems to provide info on how to do this without script setup, which uses a different API.
This is my parent component:
<template>
<cms-custom-editor v-model:modelValue="state.content"/>
<p>{{state.content}}</p>
</template>
<script setup>
import CmsCustomEditor from '../../components/backend/cms-custom-editor.vue'
import {reactive} from "vue";
const state = reactive({
content: '<p>A Vue.js wrapper component for tiptap to use <code>v-model</code>.</p>',
})
</script>
and this the child component with tiptap:
<template>
<div id="cms-custom-editor" class="cms-custom-editor">
<editor-content :editor="editor"/>
</div>
</template>
<script setup>
import {useEditor, EditorContent} from '#tiptap/vue-3'
import StarterKit from '#tiptap/starter-kit'
const props = defineProps({
modelValue: {
type: String,
default: ''
}
})
const emit = defineEmits(['update:modelValue'])
const editor = useEditor({
extensions: [StarterKit],
content: props.modelValue,
onUpdate: () => {
emit('update:modelValue', editor.getHTML())
}
})
</script>
As soon as I type something into the editor field, this code line fails:
emit('update:modelValue', editor.getHTML())
and throws this error:
Uncaught TypeError: editor.getHTML is not a function
at Editor2.onUpdate (cms-custom-editor.vue?t=1654253729389:28:42)
at chunk-RCTGLYYN.js?v=89d16c61:11965:48
at Array.forEach (<anonymous>)
at Editor2.emit (chunk-RCTGLYYN.js?v=89d16c61:11965:17)
at Editor2.dispatchTransaction (chunk-RCTGLYYN.js?v=89d16c61:12252:10)
at EditorView.dispatch (chunk-RCTGLYYN.js?v=89d16c61:9138:27)
at readDOMChange (chunk-RCTGLYYN.js?v=89d16c61:8813:8)
at DOMObserver.handleDOMChange (chunk-RCTGLYYN.js?v=89d16c61:8924:77)
at DOMObserver.flush (chunk-RCTGLYYN.js?v=89d16c61:8575:12)
at DOMObserver.observer (chunk-RCTGLYYN.js?v=89d16c61:8455:14)
I've used the approach from the docs (chapter 5. v-model), which like I said, is not designed for script setup.
Man, the docs are confusing. They mix up standard composition api and script setup. Anyway this is how it works:
const editor = useEditor({
extensions: [StarterKit],
content: props.modelValue,
onUpdate: ({editor}) => {
emit('update:modelValue', editor.getHTML())
}
})
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
I have single page application that requires authentication. When user was authenticated then visit some pages or hit reload button in browser it will request an api that provide their auth data. then I have an error like this:
[Vue warn]: Error when evaluating expression "auth.name": TypeError: Cannot read property 'name' of null (found in component: <navbar>)
This error is caused because vue render auth data while the request to api have not finished yet.
Is possible to make vue wait the request api until finish first, before vue render auth data?
just more clearly what going on here. Here is the code:
// main.js
import Vue from 'vue'
import App from './App.vue' // root vue
import store from './vuex/store' // vuex
import router from './router' // my router map
sync(store, router)
router.start(App, '#app')
// end main.js
// App.vue
<template>
<main>
<div class="wrapper">
<router-view></router-view>
</div>
</main>
</template>
<script>
import authService from './services/auth' // import authservice
ready () {
// here is code that should be done first before vue render all authData
auth.getUser((response) => {
self.authData = response
})
},
data () {
return {
authData: null // default is null until the api finish the process
}
}
</script>
// end App.vue
// SomeRouterComponents.vue
<template>
<!-- some content -->
<div>
// always got error: cannot read property 'name' of null
// here I expect to render this after api has been resolved
{{ $root.authData.name }}
</div>
<!-- some content -->
</template>
The problem as you said is that you try to access an object that isn't present, and because of the error, Vue can't render it in the next tick. The solution is to use a simple v-if to check if the data is loaded, this work only for reactive data.
root component
import auth from './services/auth' // import authservice
ready () {
// here is code that should be done first before vue render all authData
auth.getUser((response) => {
self.authData = response
self.dataReady = true
})
},
data () {
return {
authData: null, // default is null until the api finish the process
dataReady: false
}
}
otherComponent
<div v-if="dataReady">
// note that if you use v-show you will get the same error
{{ $root.authData.name }}
</div>
<div v-if="!dataReady">
// or some other loading effect
Loading...
</div>
I used v-if="!dataReady" instead of v-else because it will be deprecated in Vue 2.0
You could use the data transition hook with the waitForDataoption enabled:
<script>
import authService from './services/auth'
export default {
route: {
waitForData: true, // wait until data is loaded
data (transition) {
authService.getUser((response) => {
transition.next({ authData: response }) // set data
})
}
},
data () {
return {
authData: null
}
}
}
</script>
Also, if you don't want to use that option, you could check if the data is loaded by using the $loadingRouteData property.
More details here:
http://router.vuejs.org/en/pipeline/data.html
You could just prevent Vue from trying to access the object property, like this:
{{ $root.authData ? $root.authData.name : null }}
You could even change null for a Loading... message in some cases.