How to format Vue.compile and render errors? - vue.js

I am trying to make a little component editor and try to render it real time. I have problems with handling Vue.compile and render errors.
Here is the component editor (https://jsfiddle.net/gecjfk1w/5/):
<div id="app">
<textarea v-model="some_text" cols="30" rows="10"></textarea>
<div>
The rendered component:
<component :is="component"></component>
</div>
</div>
const ComponentFactory = (template) => {
return {
template
}
}
new Vue({
el: "#app",
data: {
some_text: `<div>Hello World</div>`
},
computed: {
component () {
return ComponentFactory(this.some_text)
}
}
})
Try to update the textarea with <div>Hello World {{ hello }}</div>
You will see in the console the following error:
[Vue warn]: Property or method "hello" is not defined on the instance but referenced during render
This is normal behavior but I'd like to display something when this error appears.
Like: "An error have been detected: {{ error }}"
I have tried the renderError function on the ComponentFactory and the errorCaptured hook on the parent element (https://jsfiddle.net/gecjfk1w/5/) with no success.
However, the renderError and errorCaptured methods work well when the error is not a compile error:
Example: <div>Hello World {{ hello.f }}</div> throws a "TypeError: Cannot read property 'f' of undefined" and activates renderError and errorCaptured.
However, I'm not even sure that renderError should be used because the documentation says that it is not available in production mode.
How could I catch compile and render errors? It would be like a try/catch on the template level

Related

Vue how to implement a retry button in error boundary component

I am trying to create a Vue error handling component following a similar pattern to the one documented here. It is basically a wrapper that uses the errorCaptured lifecycle hook to detect errors in its child components. If an error is caught, it hides the content passed into its slot and shows an error message instead. Pretty simple. Something like this:
ErrorBoundary.vue
<template>
<div>
<slot v-if="!err"></slot>
<h1 v-else>Oopsy</h1>
</div>
</template>
<script>
export default {
name: 'errorBoundary',
data(){
return {err: false};
},
errorCaptured(err){
this.err = true;
console.log(err);
}
}
</script>
The problem I have is that errorCaptured does not capture errors thrown in its own component's scope. For example, here nothing is caught and logged.
ErrorThrower.vue
<template>
<div>Some content</div>
</template>
<script>
export default {
name: 'errorThrower',
created(){
throw new Error();
},
errorCaptured(err){
console.log(err);
}
}
</script>
If the above example caught the error, then I could add a retry prop to the ErrorBoundary component and accept the content as a slot. Like this:
ErrorThrower.vue
<template>
<ErrorBoundary :onRetry="loadContent">
<div>Some content</div>
</ErrorBoundary>
</template>
<script>
export default {
name: 'errorThrower',
created(){
this.loadContent();
},
methods: {
loadContent(){
// make some call that fails
}
}
}
</script>
Unfortunately this doesn't work, due to the slotted content being on the same scope as the ErrorBoundary component.
Whereas if ErrorThrower is a child compoment, ErrorBoundary will log the error and display a message, because now ErrorThrower's error is caught by errorCaptured.
SomeParent.vue
<template>
<error-boundary>
<error-thrower/>
</error-boundary>
</template>
How can I include a retry button in ErrorBoundary's error message, that will retry some failed async operation if desired? Ideally I want to pass in the callback for the error component to retry on error.

Vue complains about undefined properties that are in fact defined

I have a weird occurrence where vue claims a property is undefined on the instance when it really is defined. I have made a minimal version of the component that still displays this weird behaviour. This is my component:
<template>
<div>
<h1>{{ formtitle }}</h1>
</div>
</template>
<script>
export default {
name: 'RequestPasswordChange',
data () {
return {
formtitle: 'blabla'
}
}
}
</template>
When viewed in the browser, vue throws the familiar error:
Property or method "formtitle" is not defined on the instance but referenced during render, but as can bee seen, the property is defined in the data function. What other conditions could trigger this error?
You have </template> instead of </script> as the final closing tag.

how to fix error The value for a v-bind expression cannot be empty Vue Js

Iam tryng in tutorial vue js basic , but i have error on v-bind . i use v-for but having error like this :
<template>
<div class="todo-list">
<todo-items
v-for="todo in todos" // error on here
:title="todo.title" // here
:description="todo.description"/> // on here
</div>
</template>
<script>
import TodoItems from '#/components/TodoItems.vue'
export default {
components:{
TodoItems
},
props:{
todos:{
required:true,
type:Array
}
}
}
</script>
i dont know what happen on my code , but this tutorial is fine and not get error . but my code is have error on v-for
this error is
Errors compiling template:
The value for a v-bind expression cannot be empty. Found in
"v-bind:"
can someone tell me about this error ?
The error occurs because the title field of at least one todo object inside the array is undefined or empty.
If you provide the exact structure of the todos array I will update my answer with more details.

[Vue warn]: Invalid handler for event "click": got undefined

I am using vue js as my frontend framework and I have defined a #click event on a button. However, when I click it, I am getting following error:-
[Vue warn]: Property or method "getArea" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
[Vue warn]: Invalid handler for event "click": got undefined
found in
---> <ElButton> at packages/button/src/button.vue
<ElCard> at packages/card/src/main.vue
<ElCol>
<ElRow>
<ElCol>
<ElRow>
<ElHeader> at packages/header/src/main.vue
<ElContainer> at packages/container/src/main.vue
<ProgressBar> at src/views/Map/components/ProgressBar.vue
I found a similar question at the following link:-
VueJS - Invalid handler for event "click": got undefined
but does not seem to solve the problem
ProgressBar.vue
<template>
<el-col class="progress-bar-icon" :span="6">
<span class="step-text">Step-2<br/></span>
<el-button id="two" class="icon" icon="el-icon-location-outline" circle></el-button>
<el-card v-if="ifLocation" class="dialog-box-card">
<h4 class="heading">Pin Down Your Roof On The Map</h4>
<el-button type="primary" round #click="getArea">Next <i class="el-icon-arrow-right"></i>
</el-button>
</el-card>
</el-col>
</template>
<script>
export default {
name:'progress-bar',
data(){
return {
ifLocation:true,
ifArea:false,
}
},
method:{
getArea(){
this.ifLocation=false
this.ifArea=true
}
}
};
</script>
index.vue
<template>
<div>
<progress-bar></progress-bar>
</div>
</template>
<script>
import ProgressBar from './components/ProgressBar';
export default {
name:'index',
components:{
'progress-bar':ProgressBar,
},
};
</script>
Please change "method" to "methods"
like this :
methods:{
getArea(){
this.ifLocation=false
this.ifArea=true
}
}
I finally found it. An error occurs because we call a function not found in methods. For example; we use the "increase" function in a div, but we don't define this function in methods. When we add this function to methods, the problem disappears.

Displaying Vue Component's computed property: [Vue warn]

I created a simple Vue 2 component:
Vue.component('upper', {
props: ['value'],
template: '#upper-template',
computed: {
formattedValue: function() {
return this.value.toUpperCase();
}
}
});
Here is the template:
<template id="upper-template">
<span>{{ formattedValue }}</span>
</template>
And when I use it:
<upper value="test"></upper>
it works fine, but I am getting the following warning:
[Vue warn]: Property or method "formattedValue" is not defined on the
instance but referenced during render. Make sure to declare reactive
data properties in the data option. (found in root instance)
Can you tell me what is wrong with my code and how can I fix this? I read the documentation, but I could not understand what I am doing wrong.
My <template id="upper-template"> was in new Vue({el: '#app', ... ) (it was placed inside <div id="app">), and that's why I was getting that warning.