How to include promises in vuejs methods - vue.js

The code below has vuejs methods. One is calling another through the promise function. How can I make handleStart be invoked first, then once done is true, foo will be resolve, and handleStart will finish. The start button must be clicked first
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button
#click="handleStart"
>
START
</button>
<button
#click="done = true"
>DONE</button>
<h1>Start the app: {{start}}</h1>
<h1>Is it done? {{done}}</h1>
</div>
<script>
var app = new Vue({
el: '#app',
data () {
return {
start: false,
done:false
}
},
methods: {
foo() {
return new Promise( (resolve) => {
if (this.done) {
console.log("done is recorded")
resolve("Yaa")
}
})
},
handleStart () {
this.start = true
// how to make this an obsersable
this.foo()
.then( (data ) => console.log("I must be printed with:", data))
}
}
})
</script>
</body>
</html>

you need to use watchers to watch this.done change
watch: {
done(newVal, oldVal) {
if (newVal) {
// do something
}
}
},
methods: {
async handleStart () {
// how to make this async
this.start = true
const data = await this.foo()
console.log("I must be printed with:", data))
}
}

The problem is with the if (this.done) check.
When done is false, the promise is never resolved, and the handleStart never receives data.
If you need to react when a data has changed, take a look Vue's watchers

Related

VueJS - Access multiple data within one methods

I'm pretty new in Vue and I'm trying to write down a function that returns true or false on a given data when input modified. I have 4 different data that I need possibly to change the truthiness.
My logic was to produce a function that accepts data as parameter but... It doesn't work. Maybe it's not the proper way to go for...
Here the HTML:
<input type="text" v-model="bannerContent.button" #input="checkMaxChar(48,bannerContent.button.length,isButtonTooLong)" id="banner-button">
And the JS
var app = new Vue({
el: '#app',
data: {
bannerContent: {
title : 'Title',
text: 'Text',
copyright: 'Copyright',
button: 'Button'
},
isButtonTooLong: false,
},
methods: {
checkMaxChar: function(a,b,c) {
var vm = this
if( a < b ) {
vm.c = true;
};
console.log(this.c);
}
}
})
I'm not sure why you are doing var vm = this and also where do you defined c?
for your purpose define c in the data section like code below and work wit your input:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<title>Document</title>
</head>
<body>
<div id="app">
<input
type="text"
v-model="bannerContent.button"
#input="checkMaxChar(48,bannerContent.button.length,isButtonTooLong)"
id="banner-button"
/>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
bannerContent: {
title: "Title",
text: "Text",
copyright: "Copyright",
button: "Button",
},
isButtonTooLong: false,
c: false,
},
methods: {
checkMaxChar(a, b, c) {
if (a < b) {
this.c = true;
}
console.log(this.c);
},
},
});
</script>
</html>
Hope it helps You ;)

Vue - #input is triggered by :placeholder in Internet Explorer 11 immediately upon page load not when entering a value

Vue - #input is triggered by :placeholder in Internet Explorer 11 immediately upon page load not when entering a value. That is, the problem is only in the explorer. When the page loads, input is triggered immediately, but only if there is a placeholder
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Тег SCRIPT</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<component-c/>
</div>
<script type="text/javascript">
var ComponentA = Vue.component('ComponentA', {
props: ['field'],
methods: {
//#input is triggered by :placeholder in Interner Exployer 11 immediately upon page load not when entering a value
validator: function (ev){
console.log(ev.target.value, 'value in validator');
}
},
computed: {
fieldPlaceholder: function () {
return this.field.placeholder;
},
},
template: '<input type="password" #input="validator" :placeholder = "fieldPlaceholder">'
});
var ComponentС = Vue.component('ComponentB', {
data: function () {
return {
field: {
placeholder: 'place'
}
}
},
components: {
'component-a': ComponentA,
},
template: '<component-a :field = "this.field" />'
})
var app = new Vue({
el: '#app',
components: {
'component-c': ComponentС,
}
})
</script>
</body>
</html>

Vue.js - How to switch the URL of an image dynamically?

I am working on a site where the user can select an image via radio selection.
I would like to dynamically update the image URL depending on selection of the user. My approach is to use a computed variable which returns the URL from a list of objects depending on the selection of the user.
<template>
<v-img
:src="require(currBackgroundURL)"
class="my-3"
contain
width="397"
height="560"
></v-img>
</template>
<script>
// data() ...
currBackground: 0,
backgrounds: [
{
name: "Flowers",
url: "../assets/background/bg_1.png"
},
// ...
computed: {
currBackgroundURL: function() {
return this.backgrounds[this.currBackground].url
}
}
</script>
Unfortunately, i get an error which says Critical dependency: the request of a dependency is an expression.
And the browser console says: [Vue warn]: Error in render: "Error: Cannot find module '../assets/background/bg_1.png'"
Question: What is the right way to switch the URL of the image dynamically?
Thanks for your help!
Here is a working example:
var app = new Vue({
el: '#app',
data: () => ({
currBackground: 0,
backgrounds: [
{
name: "black",
url: "https://dummyimage.com/600x400/000/fff"
},
{
name: "blue",
url: "https://dummyimage.com/600x400/00f/fff"
},
{
name: "red",
url: "https://dummyimage.com/600x400/f00/fff"
}
]
}),
computed: {
currBackgroundURL: function() {
return this.backgrounds[this.currBackground].url
}
},
methods: {
nextImage() {
this.currBackground += 1
if (this.currBackground > 2) {
this.currBackground = 0
}
}
}
})
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.18/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
<div id="app">
<v-btn #click="nextImage()">Change image</v-btn>
<v-img
:src="currBackgroundURL"
class="my-3"
contain
width="397"
height="560"
></v-img>
</div>
</body>
I removed the require.
The src is a link/path so you don't need require. require will try to take a path and load it into a module instead of a link/path.
Hopefully, this helps.

Vue - implementing this.$options.staticRenderFns

I am trying to implement a Vue Component with a custom render function.
As soon as my template has nested HTML elements, i get this error:
TypeError: this.$options.staticRenderFns is undefined
How do I implement staticRenderFns?
Code:
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<comp temp="temp1"></comp>
</div>
<script>
var myTemplates = new Array();
myTemplates['temp1'] = Vue.compile("<div><div>This template will come from an AJAX source</div></div>").render;
var Comp = {
props: ["temp"],
data() {
return {
renderFunc: myTemplates[ this.$props.temp ],
}
},
render(h) {
return this.renderFunc()
}
};
new Vue({
el: "#app",
data: { },
components: { Comp }
});
</script>
</body>
</html>

VueJS Data ForLoop Issue

I'm using forloop to check the items in my data in COMPONENT.
{
data:function(){
return {
items:[
{id:1,name:'John'},
{id:2,name:'FooBz'}
]
}
}
}
now I want to check the value first in console in ready hook of my component.
{
.....
ready:function(){
console.log(this.items);
// this return a [__ob__: Observer]
this.items.forEach(function(x,y){
............
});
}
}
the this.items return a '[ob: Observer]' which I can't iterate through because the length of that value is 0 it supposed to be 2.
EDIT:
this is strange on my JSBIN all are working but in my real code its not. Even though I copied my logic from my real code I'm using Laravel Elixir to compile my javascript and 1.0.24 version of Vue.
http://jsbin.com/gijaniqero/edit?html,js,console,output
Your code should be okay.
Just using your code, i have made demo. It should be okay
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<test_component></test_component>
</div>
<template id="test_component">
<div></div>
</template>
<script src="js/vue.js"></script>
<script>
var vm = new Vue({
el:'#app',
data: {
},
components : {
'test_component' : {
template : '#test_component',
data:function(){
return {
items:[
{id:1,name:'John'},
{id:2,name:'FooBz'}
]
}
},
ready : function(){
this.items.forEach(function(x,y){
console.log( 'id is : ' + x.id);
console.log( 'name is L ' + x.name);
console.log( 'key is ' + y);
});
}
}
}
})
</script>
</body>
</html>