Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
67
rated 0 times [  69] [ 2]  / answers: 1 / hits: 15224  / 5 Years ago, tue, may 7, 2019, 12:00:00

I'm fairly new to Vue.js and Vuetify (used AngularJS for several years but our company is switching to Vue.js). What I'm trying to accomplish is when the user clicks on a 'sign in' button it does some checks (i.e. username cannot be blank) and launches a Vuetify Dialog to alert the user. I know Vuetify has some built in validation but looking for something a little more robust where I can wait for a reponse (i.e. when I need to wait for something like can I use your history / location).



Basically looking to do:



if (!userName){
userName = await mbox('You must Enter your Username');
return
}


OR



var mProceed = await mbox('Can we use your location for awesome stuff?');


where mbox (a simple messagebox popup box) is a function that returns a promise, programmatically loads a vue component, adds it to the dom, and waits for the response.



Exmple



i.e.



async function mbox (mText) {
// load dialog component here and set message passed in
// How Do I load the template / wait for it?
return dialogResult

}


Vue Component would look something like (With button captions and text being variables I pass in to my mbox function):



<template>
<v-layout row justify-center>
<v-dialog
v-model=dialog
max-width=290
>
<v-card>
<v-card-title class=headline>Use Google's location service?</v-card-title>

<v-card-text>
Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.
</v-card-text>

<v-card-actions>
<v-spacer></v-spacer>

<v-btn
color=green darken-1
flat=flat
@click=dialog = false
>
Disagree
</v-btn>

<v-btn
color=green darken-1
flat=flat
@click=dialog = false
>
Agree
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>


I'm fine editing the template / adding the script for the vue component I'm just not sure how to have it called via a method that returns a promise and waits for the response?


More From » vue.js

 Answers
39

Ended up solving it this way:



I have a method called mbox (returns a promise) that creates a an instance of my component, adds it to the DOM, and then watches a property on that component to know which option the user chose. Resolves the promise once the user has chosen an option



My mbox method:



import MBOX from './components/mbox.vue';
import _Vue from 'vue';
export default {

mbox(mText, mTitle, mBtnCap1, mBtnCap2, mBtnCap3){
return new Promise(async (resolve, reject) => {
if (!mTitle){
mTitle = 'My Title';
}
if (!mBtnCap1){
mBtnCap1 = 'OK';
}

// I'm combining a bunch of stuff to make this work.
// First, create the vue component
var mboxInstance = _Vue.extend(MBOX); // mbox component, imported at top of Sublib
var oComponent = new mboxInstance({
propsData: {
msg: mText,
title: mTitle,
btnCap1: mBtnCap1,
btnCap2: mBtnCap2,
btnCap3: mBtnCap3,
retval: 0
}
}).$mount();

// now add it to the DOM
var oEl = document.getElementById('app').appendChild(oComponent.$el);

// NOTE: couldn't get it to work without adding a 'button' to activate it
// progrmatically click it and make the button invisible
// document.getElementById('mbox_btn_launch').click();
var oLuanchBtn = document.getElementById('mbox_btn_launch');
oLuanchBtn.style.visibility = 'hidden';
oLuanchBtn.click();

// Add a listener so we can get the value and return it
oComponent.$watch('retval', function(newVal, oldVal){
// this is triggered when they chose an option
// Delete the component / element now that I'm done
oEl.remove();
resolve(Number(newVal));
})
}); // promise
}, // mbox
}


And My MBOX component:



<template>
<v-dialog max-width=290 persistent v-if=showMbox>
<template v-slot:activator={on}>
<v-btn id=mbox_btn_launch v-on=on>
Test
</v-btn>
</template>
<v-card>
<v-card-title>{{title}}</v-card-title>
<v-card-text>{{msg}}</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn v-if=btnCap1 @click=btnClicked('1')>{{btnCap1}}</v-btn>
<v-btn v-if=btnCap2 @click=btnClicked('2')>{{btnCap2}}</v-btn>
<v-btn v-if=btnCap3 @click=btnClicked('3')>{{btnCap3}}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
name: 'mbox',
data: () => ({
showMbox: true
}),
props: [
// these can be passed in, the 'data' stuff can't
'msg',
'title',
'btnCap1',
'btnCap2',
'btnCap3',
'retval' // watches this so we know when they clicked something
],
created(){
this.showMbox = true;
},
methods: {
btnClicked: function(mBtnClicked){
// mBtnClicked = Char. Has to be a character in order for it to pass it in. Not sure why, numerics didn't work
mBtnClicked = Number(mBtnClicked);
this.retval = mBtnClicked; // watcher in Sublib will detect this value has changed
this.showMbox = false;
} // btnClicked
} // methods
} // export default
</script>
<style scoped>
</style>


I can then call it like so:



var mChoice = await mbox('What do you want to do?', 'Title', 'Option 1', 'Option 2');


or for a simple 'validation' prompt:



if (!userName){
mbox('You must enter a username');
return;
}

[#52149] Monday, April 29, 2019, 5 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
havenkamis

Total Points: 172
Total Questions: 93
Total Answers: 103

Location: Wales
Member since Mon, May 17, 2021
3 Years ago
;