link1781 link1782 link1783 link1784 link1785 link1786 link1787 link1788 link1789 link1790 link1791 link1792 link1793 link1794 link1795 link1796 link1797 link1798 link1799 link1800 link1801 link1802 link1803 link1804 link1805 link1806 link1807 link1808 link1809 link1810 link1811 link1812 link1813 link1814 link1815 link1816 link1817 link1818 link1819 link1820 link1821 link1822 link1823 link1824 link1825 link1826 link1827 link1828 link1829 link1830 link1831 link1832 link1833 link1834 link1835 link1836 link1837 link1838 link1839 link1840 link1841 link1842 link1843 link1844 link1845 link1846 link1847 link1848 link1849 link1850 link1851 link1852 link1853 link1854 link1855 link1856 link1857 link1858 link1859 link1860 link1861 link1862 link1863 link1864 link1865 link1866 link1867 link1868 link1869 link1870 link1871 link1872 link1873 link1874 link1875 link1876 link1877 link1878 link1879 link1880 link1881 link1882 link1883 link1884 link1885 link1886 link1887 link1888 link1889 link1890 link1891 link1892 link1893 link1894 link1895 link1896 link1897 link1898 link1899 link1900 link1901 link1902 link1903 link1904 link1905 link1906 link1907 link1908 link1909 link1910 link1911 link1912 link1913 link1914 link1915 link1916 link1917

[Vue.js] @keyup event not firing at all when the respective key assigned is pressed

I’m trying to make shortcut keys to execute certain functions in an application when building. I’m trying to use the “@keyup” event which is built in with VueJS. Whenever I use the Enter key for example the function never fires. The @keyup event never works and there is tried a lot of things. The code for my component is attached below:

<template>
<div>
<div id=”mainuserbox”>
<div>
<b> <h5 id=”userheader”> User Management </h5> </b>
</div>
<div id=”searchbar”>
<div class=”row”>
<div class=”column”>
<div class=”row”>
<q-input class=”inputspace” placeholder=”First Name” color=”secondary” v-model=”fname” @input=”finduser()”/>
<q-input class=”inputspace” placeholder=”Last Name” color=”secondary” v-model=”lname” @input=”finduser()”/>
</div>
<div class=”row”>
<q-input class=”inputspace” placeholder=”Phone Number” color=”secondary” v-model=”phonenumber” @input=”finduser()”/>
<q-input class=”inputspace” placeholder=”Address” color=”secondary” v-model=”address” @input=”finduser()”/>
</div>
</div>
<div>
<div class=”row”>
<q-btn icon=”clear” color=”secondary” @click=”clear()” class=”inputspace” @keyup.native.esc=”clear()”>
<q-tooltip anchor=”bottom middle” self=”top middle” :offset=”[10, 10]“ color=”secondary” @click=”showing = false”>
Clear (Ctrl + Q)
</q-tooltip>
</q-btn>
</div>
</div>
</div>
</div>
<center v-if=”users.length===0”>
<h6 class=”secondarycolor”> No Results </h6>
<q-btn v-if=”!arefieldsempty()” label=”Add New User” class=”inputspace” color=”secondary” @click=”adduser()”/>
</center> <br>
<div id=”userlist”>
<div class=”row justify-center”>
<q-card color=”secondary” dark class=”q-ma-sm” v-for=”user in users” :key=”user.UserID” >
<q-card-title>
<div class=”row”>
<div class=”row”>
<div id=”leftrow”>
<p class=”margintop”><b>First Name:</b></p>
<p class=”margintop”><b>Last Name:</b> </p>
<p class=”margintop”><b>Phone Number:</b> </p>
<p class=”margintop”><b>Address:</b> </p>
<p class=”margintop”><b>Username:</b> </p>
<p class=”margintop marginbottom”> <b>Password:</b> </p>
</div>
<div id=”rightrow”>
<p class=”margintop”>{ user.FirstName }</p>
<p class=”margintop”>{ user.LastName }</p>
<p class=”margintop”>{ user.PhoneNumber }</p>
<p class=”margintop”>{ user.Address }</p>
<p class=”margintop”>{ user.Username }</p>
<p class=”margintop marginbottom”>
<q-input type=”password” :value=”user.Password” class=”margintop passcode” color=”secondary” inverted readonly :style=”{‘min-width’: width}”/>
</p>
</div>
</div>
<div class=”column” slot=”right”>
<div>
<q-icon name=”person” size=”50px”/>
</div>
</div>
</div>
</q-card-title>

<q-card-separator />
<q-card-actions>
<q-btn icon=”edit” @click=”edituser(user)” class=”inputspace”>
<q-tooltip anchor=”bottom middle” self=”top middle” :offset=”[10, 10]“ color=”secondary” @click=”showing = false”>
Edit
</q-tooltip>
</q-btn>
<q-btn icon=”delete” color=”secondary” @click=”deactivate(user)” class=”inputspace”>
<q-tooltip anchor=”bottom middle” self=”top middle” :offset=”[10, 10]“ color=”secondary” @click=”showing = false”>
Deactivate
</q-tooltip>
</q-btn>
</q-card-actions>
</q-card>
</div>
</div>
<q-dialog
v-model=”dialog1”
prevent-close
\>
<span slot=”title” class=”secondarycolor”> Edit User </span>
<template slot=”message”>
<div class=”secondarycolor marginbottom”> First Name: </div>
<q-input v-model=”newfname” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Last Name: </div>
<q-input v-model=”newlname” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Address: </div>
<q-input v-model=”newaddress” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Phone Number: </div>
<q-input v-model=”newphonenumber” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Username: </div>
<q-input v-model=”newusername” type=”textarea” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Password: </div>
<q-input v-model=”newpassword” color=”secondary” @input=”popupinput()” type=”password”/>
</template>
<span slot=”buttons” slot-scope=”props”>
<q-btn label=”Submit” color=”secondary” @click=”yesclicked()” :disable=”edituserdisable”/>
<q-btn label=”Cancel” color=”red” @click=”noclicked()”/>
</span>
</q-dialog>
<q-dialog
v-model=”dialog3”
color=”secondary”
\>
<span slot=”title” class=”secondarycolor”> Update Request </span>
<span slot=”message”> User Edited Successfully </span>
</q-dialog>
<q-dialog
v-model=”dialog4”
color=”secondary”
\>
<span slot=”title” class=”secondarycolor”> Addition Request </span>
<span slot=”message”> User Added Successfully </span>
</q-dialog>
<q-dialog
v-model=”dialog2”
prevent-close
\>
<span slot=”title” class=”secondarycolor”> Add User </span>
<template slot=”message”>
<div class=”secondarycolor marginbottom”> First Name: </div>
<q-input v-model=”newfname” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Last Name: </div>
<q-input v-model=”newlname” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Address: </div>
<q-input v-model=”newaddress” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Phone Number: </div>
<q-input v-model=”newphonenumber” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Username: </div>
<q-input v-model=”newusername” type=”textarea” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Password: </div>
<q-input v-model=”newpassword” color=”secondary” @input=”popupinput()” type=”password”/>
<div class=”secondarycolor topspace marginbottom”> Admin Privilege: </div> <br>
<q-checkbox v-model=”admin” label=”Admin” color=”secondary”/> <br>
</template>
<span slot=”buttons” slot-scope=”props”>
<q-btn label=”Submit” color=”secondary” @click=”yesclicked1()” :disable=”edituserdisable”/>
<q-btn label=”Cancel” color=”red” @click=”noclicked1()”/>
</span>
</q-dialog>
<q-dialog
v-model=”dialog5”
color=”secondary”
\>
<span slot=”title” class=”secondarycolor”> Deactivate </span>
<span slot=”message”> Are you sure you want to deactivate this user? </span>
<span slot=”buttons” slot-scope=”props”>
<q-btn label=”Yes” color=”secondary” @click=”yesclicked2()”/>
<q-btn label=”No” color=”red” @click=”noclicked2()”/>
</span>
</q-dialog>
<q-dialog
v-model=”dialog6”
color=”secondary”
\>
<span slot=”title” class=”secondarycolor”> Deactivation Request </span>
<span slot=”message”> User has been deactivated successfully </span>
</q-dialog>
</div>
</div>
</template>

<script>
export default {
// name: ‘ComponentName’,
data () {
return {
fname: “”,
lname: “”,
users: [],
newfname: “”,
newlname: “”,
newusername: “”,
newpassword: “”,
dialog1: false,
dialog2: false,
edituserdisable: true,
dialog3: false,
userid: null,
dialog4: false,
dialog5: false,
dialog6: false,
visibility: false,
visicon: “visibility_off”,
admin: false,
phonenumber: “”,
address: “”,
newphonenumber: “”,
newaddress: “”,
width: “”
}
},
mounted() {
this.$nextTick (() => {
//this.width=document.getElementById(“rightrow”).offsetWidth + “px”
})
},
methods: {
clear: function () {
this.fname=””
this.lname=””
this.users=[]
this.address=””
this.phonenumber=””
},
arefieldsempty: function () {
if(this.fname==”” && this.lname==””)
{
return true
}
else
{
return false
}
},
adduser: function () {

},
input: function () {
this.visibility=false
this.visicon=”visibility_off”
if(this.fname==”” && this.lname==”” && this.address && this.phonenumber)
{
this.users=[]
}
else{
this.finduser()
}
},
finduser: function () {
if(this.fname!=’’||this.lname!=’’||this.address!=’’||this.phonenumber!=’’)
{
this.$Socket.emit(‘finduser’, {
FirstName: this.fname,
LastName: this.lname,
Address: this.address,
PhoneNumber: this.phonenumber
}, (userlist) => {
this.users=userlist
}
)
}
else
{
this.users=[]
}
},
popupinput: function () {
if( this.newfname==”” || this.newlname ==”” || this.newusername==”” || this.newpassword==”” || this.newaddress==”” || this.newphonenumber==””)
{
this.edituserdisable=true
}
else {
this.edituserdisable=false
}
},
yesclicked: function () {
this.$Socket.emit(‘edituser’, {
UserID: this.userid,
FirstName: this.newfname,
LastName: this.newlname,
Address: this.newaddress,
PhoneNumber: this.newphonenumber,
Username: this.newusername,
Password: this.newpassword
}, ({authenticated}) => {
if(authenticated==true)
{
this.dialog1=false
this.dialog3=true
this.clearpopup()
this.finduser()
}
})
},
clearpopup: function () {
this.newfname=””
this.newlname=””
this.newusername=””
this.newpassword=””
this.newaddress=””
this.newphonenumber=””
this.admin=false
},
noclicked: function () {
this.clearpopup()
this.dialog1=false
},
edituser: function (user) {
this.newfname=user.FirstName
this.newlname=user.LastName
this.newaddress=user.Address
this.newphonenumber=user.PhoneNumber
this.newusername=user.Username
this.newpassword=user.Password
this.dialog1=true
this.edituserdisable=true
this.userid=user.UserID
},
adduser: function () {
this.newfname=this.fname
this.newlname=this.lname
this.newaddress=this.address
this.newphonenumber=this.phonenumber
this.dialog2=true
this.edituserdisable=true
},
noclicked1: function () {
this.clearpopup()
this.dialog2=false
},
yesclicked1: function () {
this.$Socket.emit(‘adduser’, {
FirstName: this.newfname,
LastName: this.newlname,
Address: this.address,
PhoneNumber: this.phonenumber,
Username: this.newusername,
Password: this.newpassword,
PermissionLvl: this.convertbool(this.admin)
}, ({authenticated}) => {
if(authenticated==true)
{
this.dialog2=false
this.dialog4=true
this.finduser()
}
})
},
convertbool: function (data) {
if(data==true)
{
return 1
}
else {
return 0
}
},
deactivate: function (user) {
this.dialog5=true
this.userid=user.UserID
},
yesclicked2: function () {
this.$Socket.emit(‘deactivateuser’, {
UserID: this.userid
}, ({authenticated}) => {
if(authenticated==true)
{
this.dialog5=false
this.dialog6=true
this.finduser()
}
})
},
noclicked2: function () {
this.dialog5=false
},
passformat: function (pass) {
var password=””
for (var x=0; x<pass.length; x++)
{
password= password + “\u2022”
}
return password
},
visibilityfn: function () {
if(this.visibility==false)
{
this.visibility=true
this.visicon=”visibility”
}
else
{
this.visibility=false
this.visicon=”visibility_off”
}
}
}
}
</script>

<style>

#mainuserbox {
text-align: center;
}
.passcode {
max-width: 120px;
}

#userheader {
display: inline-block;
margin: 10px;
color: #26a69a;
}

#searchbar {
display: inline-block;
border-bottom: 2px solid #26A69A;
padding-bottom: 15px;
margin-bottom: 15px;
}

#userlist {
display: inline-block;
text-align: center;
}
.secondarycolor {
color: #26a69a;
}
.marginbottom {
margin-bottom: -10px;
}
.topspace {
margin-top: 15px;
}

#usericon {
vertical-align: top;
}
.margintop {
margin-top: -15px;
}

#visbtn {
margin-top: 40px;
}
.inputspace {
margin: 5px;
}

#leftrow {
margin-right: 5px;
text-align: right;
}

#rightrow {
text-align: left;
margin-left: 5px;
}
</style>

Solution :

The issue was happening because you were using the @keyup event handler on a button.

<q-btn icon=”clear” color=”secondary” @click=”clear()” class=”inputspace” @keyup.native.esc=”clear()”>

I moved that to each field, and it works properly..

[CodePen mirror]

//Quasar.icons.set(Quasar.icons.fontawesome);

new Vue({
el: ‘#q-app’,
data () {
return {
fname: “”,
lname: “”,
users: [],
newfname: “”,
newlname: “”,
newusername: “”,
newpassword: “”,
dialog1: false,
dialog2: false,
edituserdisable: true,
dialog3: false,
userid: null,
dialog4: false,
dialog5: false,
dialog6: false,
visibility: false,
visicon: “visibility_off”,
admin: false,
phonenumber: “”,
address: “”,
newphonenumber: “”,
newaddress: “”,
width: “”
}
},
mounted() {
this.$nextTick (() => {
//this.width=document.getElementById(“rightrow”).offsetWidth + “px”
})
},
methods: {
clear: function () {
this.fname=””
this.lname=””
this.users=[]
this.address=””
this.phonenumber=””
},
arefieldsempty: function () {
if(this.fname==”” && this.lname==””)
{
return true
}
else
{
return false
}
},
adduser: function () {

},
input: function () {
this.visibility=false
this.visicon=”visibility_off”
if(this.fname==”” && this.lname==”” && this.address && this.phonenumber)
{
this.users=[]
}
else{
this.finduser()
}
},
finduser: function () {
if(this.fname!=’’||this.lname!=’’||this.address!=’’||this.phonenumber!=’’)
{
this.$Socket.emit(‘finduser’, {
FirstName: this.fname,
LastName: this.lname,
Address: this.address,
PhoneNumber: this.phonenumber
}, (userlist) => {
this.users=userlist
}
)
}
else
{
this.users=[]
}
},
popupinput: function () {
if( this.newfname==”” || this.newlname ==”” || this.newusername==”” || this.newpassword==”” || this.newaddress==”” || this.newphonenumber==””)
{
this.edituserdisable=true
}
else {
this.edituserdisable=false
}
},
yesclicked: function () {
this.$Socket.emit(‘edituser’, {
UserID: this.userid,
FirstName: this.newfname,
LastName: this.newlname,
Address: this.newaddress,
PhoneNumber: this.newphonenumber,
Username: this.newusername,
Password: this.newpassword
}, ({authenticated}) => {
if(authenticated==true)
{
this.dialog1=false
this.dialog3=true
this.clearpopup()
this.finduser()
}
})
},
clearpopup: function () {
this.newfname=””
this.newlname=””
this.newusername=””
this.newpassword=””
this.newaddress=””
this.newphonenumber=””
this.admin=false
},
noclicked: function () {
this.clearpopup()
this.dialog1=false
},
edituser: function (user) {
this.newfname=user.FirstName
this.newlname=user.LastName
this.newaddress=user.Address
this.newphonenumber=user.PhoneNumber
this.newusername=user.Username
this.newpassword=user.Password
this.dialog1=true
this.edituserdisable=true
this.userid=user.UserID
},
adduser: function () {
this.newfname=this.fname
this.newlname=this.lname
this.newaddress=this.address
this.newphonenumber=this.phonenumber
this.dialog2=true
this.edituserdisable=true
},
noclicked1: function () {
this.clearpopup()
this.dialog2=false
},
yesclicked1: function () {
this.$Socket.emit(‘adduser’, {
FirstName: this.newfname,
LastName: this.newlname,
Address: this.address,
PhoneNumber: this.phonenumber,
Username: this.newusername,
Password: this.newpassword,
PermissionLvl: this.convertbool(this.admin)
}, ({authenticated}) => {
if(authenticated==true)
{
this.dialog2=false
this.dialog4=true
this.finduser()
}
})
},
convertbool: function (data) {
if(data==true)
{
return 1
}
else {
return 0
}
},
deactivate: function (user) {
this.dialog5=true
this.userid=user.UserID
},
yesclicked2: function () {
this.$Socket.emit(‘deactivateuser’, {
UserID: this.userid
}, ({authenticated}) => {
if(authenticated==true)
{
this.dialog5=false
this.dialog6=true
this.finduser()
}
})
},
noclicked2: function () {
this.dialog5=false
},
passformat: function (pass) {
var password=””
for (var x=0; x<pass.length; x++)
{
password= password + “\u2022”
}
return password
},
visibilityfn: function () {
if(this.visibility==false)
{
this.visibility=true
this.visicon=”visibility”
}
else
{
this.visibility=false
this.visicon=”visibility_off”
}
}
}
})

#mainuserbox {
text-align: center;
}
.passcode {
max-width: 120px;
}

#userheader {
display: inline-block;
margin: 10px;
color: #26a69a;
}

#searchbar {
display: inline-block;
border-bottom: 2px solid #26A69A;
padding-bottom: 15px;
margin-bottom: 15px;
}

#userlist {
display: inline-block;
text-align: center;
}
.secondarycolor {
color: #26a69a;
}
.marginbottom {
margin-bottom: -10px;
}
.topspace {
margin-top: 15px;
}

#usericon {
vertical-align: top;
}
.margintop {
margin-top: -15px;
}

#visbtn {
margin-top: 40px;
}
.inputspace {
margin: 5px;
}

#leftrow {
margin-right: 5px;
text-align: right;
}

#rightrow {
text-align: left;
margin-left: 5px;
}
<script src=”https://unpkg.com/vue@latest/dist/vue.min.js"></script>
<script src=”https://unpkg.com/quasar-framework@latest/dist/umd/quasar.mat.umd.min.js"></script>
<link href=”https://unpkg.com/quasar-extras@1.0.2/material-icons/material-icons.css" rel=”stylesheet”/>
<link href=”https://unpkg.com/quasar-framework@latest/dist/umd/quasar.mat.min.css" rel=”stylesheet”/>

<div id=”q-app”>

<div>
<div id=”mainuserbox”>
<div>
<b> <h5 id=”userheader”> User Management </h5> </b>
</div>
<div id=”searchbar”>
<div class=”row”>
<div class=”column”>
<div class=”row”>
<q-input @keyup.native.esc=”clear()” class=”inputspace” placeholder=”First Name” color=”secondary” v-model=”fname” @input=”finduser()” />
</div>
<div class=”row”>
<q-input @keyup.native.esc=”clear()” class=”inputspace” placeholder=”Last Name” color=”secondary” v-model=”lname” @input=”finduser()” />
</div>
<div class=”row”>
<q-input @keyup.native.esc=”clear()” class=”inputspace” placeholder=”Phone Number” color=”secondary” v-model=”phonenumber” @input=”finduser()” />
</div>
<div class=row>
<q-input @keyup.native.esc=”clear()” class=”inputspace” placeholder=”Address” color=”secondary” v-model=”address” @input=”finduser()” />
</div>
</div>
<div>
<div class=”row”>
<q-btn icon=”clear” color=”secondary” @click=”clear()” class=”inputspace” >
<q-tooltip anchor=”bottom middle” self=”top middle” :offset=”[10, 10]“ color=”secondary” @click=”showing = false”>
Clear (Ctrl + Q)
</q-tooltip>
</q-btn>
</div>
</div>
</div>
</div>
<center v-if=”users.length===0”>
<h6 class=”secondarycolor”> No Results </h6>
<q-btn v-if=”!arefieldsempty()” label=”Add New User” class=”inputspace” color=”secondary” @click=”adduser()” />
</center> <br>
<div id=”userlist”>
<div class=”row justify-center”>
<q-card color=”secondary” dark class=”q-ma-sm” v-for=”user in users” :key=”user.UserID”>
<q-card-title>
<div class=”row”>
<div class=”row”>
<div id=”leftrow”>
<p class=”margintop”><b>First Name:</b></p>
<p class=”margintop”><b>Last Name:</b> </p>
<p class=”margintop”><b>Phone Number:</b> </p>
<p class=”margintop”><b>Address:</b> </p>
<p class=”margintop”><b>Username:</b> </p>
<p class=”margintop marginbottom”> <b>Password:</b> </p>
</div>
<div id=”rightrow”>
<p class=”margintop”>{ user.FirstName }</p>
<p class=”margintop”>{ user.LastName }</p>
<p class=”margintop”>{ user.PhoneNumber }</p>
<p class=”margintop”>{ user.Address }</p>
<p class=”margintop”>{ user.Username }</p>
<p class=”margintop marginbottom”>
<q-input type=”password” :value=”user.Password” class=”margintop passcode” color=”secondary” inverted readonly :style=”{‘min-width’: width}” />
</p>
</div>
</div>
<div class=”column” slot=”right”>
<div>
<q-icon name=”person” size=”50px” />
</div>
</div>
</div>
</q-card-title>

<q-card-separator />
<q-card-actions>
<q-btn icon=”edit” @click=”edituser(user)” class=”inputspace”>
<q-tooltip anchor=”bottom middle” self=”top middle” :offset=”[10, 10]“ color=”secondary” @click=”showing = false”>
Edit
</q-tooltip>
</q-btn>
<q-btn icon=”delete” color=”secondary” @click=”deactivate(user)” class=”inputspace”>
<q-tooltip anchor=”bottom middle” self=”top middle” :offset=”[10, 10]“ color=”secondary” @click=”showing = false”>
Deactivate
</q-tooltip>
</q-btn>
</q-card-actions>
</q-card>
</div>
</div>
<q-dialog v-model=”dialog1” prevent-close>
<span slot=”title” class=”secondarycolor”> Edit User </span>
<template slot=”message”>
<div class=”secondarycolor marginbottom”> First Name: </div>
<q-input v-model=”newfname” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Last Name: </div>
<q-input v-model=”newlname” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Address: </div>
<q-input v-model=”newaddress” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Phone Number: </div>
<q-input v-model=”newphonenumber” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Username: </div>
<q-input v-model=”newusername” type=”textarea” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Password: </div>
<q-input v-model=”newpassword” color=”secondary” @input=”popupinput()” type=”password”/>
</template>
<span slot=”buttons” slot-scope=”props”>
<q-btn label=”Submit” color=”secondary” @click=”yesclicked()” :disable=”edituserdisable”/>
<q-btn label=”Cancel” color=”red” @click=”noclicked()”/>
</span>
</q-dialog>
<q-dialog v-model=”dialog3” color=”secondary”>
<span slot=”title” class=”secondarycolor”> Update Request </span>
<span slot=”message”> User Edited Successfully </span>
</q-dialog>
<q-dialog v-model=”dialog4” color=”secondary”>
<span slot=”title” class=”secondarycolor”> Addition Request </span>
<span slot=”message”> User Added Successfully </span>
</q-dialog>
<q-dialog v-model=”dialog2” prevent-close>
<span slot=”title” class=”secondarycolor”> Add User </span>
<template slot=”message”>
<div class=”secondarycolor marginbottom”> First Name: </div>
<q-input v-model=”newfname” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Last Name: </div>
<q-input v-model=”newlname” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Address: </div>
<q-input v-model=”newaddress” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Phone Number: </div>
<q-input v-model=”newphonenumber” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Username: </div>
<q-input v-model=”newusername” type=”textarea” color=”secondary” @input=”popupinput()”/>
<div class=”secondarycolor topspace marginbottom”> Password: </div>
<q-input v-model=”newpassword” color=”secondary” @input=”popupinput()” type=”password”/>
<div class=”secondarycolor topspace marginbottom”> Admin Privilege: </div> <br>
<q-checkbox v-model=”admin” label=”Admin” color=”secondary”/> <br>
</template>
<span slot=”buttons” slot-scope=”props”>
<q-btn label=”Submit” color=”secondary” @click=”yesclicked1()” :disable=”edituserdisable”/>
<q-btn label=”Cancel” color=”red” @click=”noclicked1()”/>
</span>
</q-dialog>
<q-dialog v-model=”dialog5” color=”secondary”>
<span slot=”title” class=”secondarycolor”> Deactivate </span>
<span slot=”message”> Are you sure you want to deactivate this user? </span>
<span slot=”buttons” slot-scope=”props”>
<q-btn label=”Yes” color=”secondary” @click=”yesclicked2()”/>
<q-btn label=”No” color=”red” @click=”noclicked2()”/>
</span>
</q-dialog>
<q-dialog v-model=”dialog6” color=”secondary”>
<span slot=”title” class=”secondarycolor”> Deactivation Request </span>
<span slot=”message”> User has been deactivated successfully </span>
</q-dialog>
</div>
</div>

</div>

[Vue.js] vue.config.js - Loading Multiple .scss files for global use

there is three .scss files in my vue.js project.

The main global one, which there is imported to my main app component.
Then, the other two are ones that container variables, and with such cannot be important in the same way, as the variable cannot be found.

So, I created a vue.config.js file, and added -

module.exports = {
css: {
loaderOptions: {
sass: {
data: `@import “@/styles/_variables.scss”;`
},
}
}
};

The issue is, that imports my _variables.scss file, but I also want to import a _other.scss file (from the same folder).

I cannot figure out how to structure it for it to import and use both.

Solution :

@import “@/styles/_variables.scss”; @import “@/styles/_other.scss”

Worked perfectly. But so did importing into one large file, and loading that.

[Vue.js] Angular ng-container equivalent in vue.js

In Angular there is a tag called ng-container used like so

<ng-container *ngIf=”false”>this wont be shown</ng-container>

now as per the angular docs

The Angular is a grouping element that doesn’t interfere with styles or layout because Angular doesn’t put it in the DOM.

Now this is really handy in angular since there are often times I would like to group a set of html elements without using a <div></div>

For example

<div class=”flex-div”>
<ng-container *ngIf=”true”>
<img src=”cool-img” alt=”awesome”>
<h1>Cool Title</h1>
<p>Cool Text</p>
</ng-container>
<ng-container *ngIf=”false”>
<img src=”not-so-cool-img” alt=”awesome”>
<h1>Not So Cool Title</h1>
<p>Not So Cool Text</p>
</ng-container>
</div>

here there is a div that has a position of flex on it and also rules about what the elements inside do..

Now If I wrapped the elements in a normal div it will break my flex styles but with the ng-container it contains my elements but is not rendered to them DOM

Is there an equivalent in Vue??

Solution :

You could use conditional grouping on a template as mentioned in the docs here. The template will serve as an invisible wrapper.

<div class=”flex-div”>
<template v-if=”true”>
<img src=”cool-img” alt=”awesome”>
<h1>Cool Title</h1>
<p>Cool Text</p>
</template>
<template v-if=”false”>
<img src=”not-so-cool-img” alt=”awesome”>
<h1>Not So Cool Title</h1>
<p>Not So Cool Text</p>
</template>
</div>

[Vue.js] How to add authentication headers to vuejs axios post?

I’m trying to make an post call to the spring-boot API which has authentication. there is used below approach to add the authentication, but it is giving me 401 error

var auth = {
username: ‘user’,
password: ‘secret’
};
var data = {
userid : this.userid
};

axios.post(“http://localhost:8004/api/v1/user", data, auth)
.then((response) => {
console.log(response.data);
}, (error) => {
console.log(error);
})

In the Spring-boot there is configured the authentication part as below which it authenticates on all the apis with prefix api/v1

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance()).withUser(“user”)
.password(“secret”).roles(“USER”).and().withUser(“admin”).password(“secret”).roles(“USER”, “ADMIN”);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().requestMatchers(EndpointRequest.to(ShutdownEndpoint.class)).hasRole(“ACTUATOR_ADMIN”)
.requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.antMatchers(“/“, “/api/v1/**“).hasRole(“USER”).antMatchers(“/**“).hasRole(“ADMIN”).and().csrf()
.disable().headers().frameOptions().disable().and().httpBasic();
}

Solution :

Well you seem to have put the credentials in the config object.

Here’s what you’re looking for:

var data = {
userid : this.userid,
username: ‘user’,
password: ‘secret’
};

axios.post(“http://localhost:8004/api/v1/user", data)
.then((response) => {
console.log(response.data);
}, (error) => {
console.log(error);
})

OR YOU CAN DO

var data = {
userid : this.userid
};

var auth = {
username: ‘user’,
password: ‘secret’
};

axios.post(“http://localhost:8004/api/v1/user", data, {auth: auth})
.then((response) => {
console.log(response.data);
}, (error) => {
console.log(error);
})

The types of requests that can be made are listed here.

Here is an example of the request object.

If you were using perhaps a JWT for authorisation, you can define that in the headers like so:

let config = {
headers: {
‘Authorization’: ‘Bearer ‘ + this.SomeToken
}
};

[Vue.js] How to fix v-select drop down position?

when using a v-select as an option for a sign-up view. However, its drop down menu shows up in the bottom right corner, instead of directly below it.

there is tried using position: relative in the div to no avail. there is even added a class to the v-select with position: relative and I still get the same result.

HTML:

<template>
<div class=”hello”>
<img src=”../assets/logo.png”>
<h1>{ msg }</h1>
<v-container fluid grid-list-xl>
<v-layout wrap align-center>
<div class=”inner”>
<br>
<v-text-field label = “Email” v-model=”email”></v-text-field>
<v-text-field label = “Password” v-model=”password” type=”password”></v-text-field>
<v-text-field label = “Name”></v-text-field>
<br>
<v-select class=”drop-down-test” label=”User type” :items=”items” ></v-select>
<br>
<v-btn depressed dark class=”orange font-weight-bold”>Sign Up</v-btn>
<br>
</div>
</v-layout>
</v-container>
<br>
<a style=”cursor: pointer; text-decoration: underline” v-on:click=”navigate()”>Return</a>
</div>
</template>

on export default there is these items under the data() return

items:[‘Administrator’,’Student’,’Teacher’]

CSS (style scoped since I’m working on a .vue.js file)

<style scoped>
h1, h2 {
font-weight: normal;
}

ul {
list-style-type: none;
padding: 0;
}

li {
display: inline-block;
margin: 0 10px;
}

a {
color: #42b983;
}

.inner {
position:relative;
display: table;
margin: 0 auto;
}

.drop-down-test{
position:relative;
}
</style>

It should show the items from the v-select right below it, but it is showing them in the bottom right corner.

Solution :

I solved the issue by placing <v-app> in between the template of the App.vue.js layout.

[Vue.js] Search with axios cancel previous request when new character

there is a searchbar, the results are updated on each letter, but when the user types 3 letters quickly for example, the previous requests are not cancelled so there is a ugly delay before he get his results.

there is read this https://github.com/axios/axios#cancellation and maybe when a bit tired but I struggle very much adding it in my project. It is almost doing the opposite effect, it now takes forever.
Do you have any suggetsion or maybe do you recommend a good tutorial so that I could understand this?

<input v-model=”query” type=”text” class=”form-control” placeholder=”Runner name or description”
aria-label=”Runner name or description”
aria-describedby=”basic-addon2”>

watch: {
query: {
handler: _.debounce(function () {
this.newSearch()
}, 100)
}
},
methods: {
searchItems() {
let filters = {
q: this.query
};

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.post(‘/Items/find’, filters, {
cancelToken: source.token
})
.catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log(‘Request canceled’, thrown.message);
}
})
.then(
response => {
if(this.Items!=null){
response.data.forEach(element => {
this.Items.push(element);
});
}
else
this.Items=response.data;
}
);
},
newSearch(){
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
source.cancel(‘Cancel previous request’);

this.countItems();
this.searchItems();
},
showMore(){
this.startindex = this.startindex+this.nbrows;
this.searchItems();
},
countItems(){
this.countItems=10;
let filters = {
q: this.query
};
axios.post(‘/Items/count’, filters).then(
response => {
this.countItems=response.data;
}
);
}
}

Solution :

I was able to get this to work.. The trick was to check if the cancel token existed before kicking off the API call, among other things.. I had to move the CancelToken and cancel variables outside of the vue.js object/component..

This example searches GitHub for repositories…

var cancel;
var CancelToken = axios.CancelToken;

new Vue({
el: “#app”,
data: {
query: “”,
results: “”,
isLoading: false
},
methods: {
clear() {
this.isLoading = false;
this.results = “”;
this.query = “”;
},

handleSearch: _.debounce(function() {
this.preApiCall();
}, 300),

preApiCall() {
if (cancel != undefined) {
cancel();
console.log(“cancelled”);
}
this.apiCall(this.query);
},

apiCall(query) {
if (query !== “”) {
this.isLoading = true;
axios({
method: “get”,
url: “https://api.github.com/search/repositories",
cancelToken: new CancelToken(function executor(c) {
cancel = c;
}),
params: {
q: query
}
}).then(res => {
this.results = JSON.parse(JSON.stringify(res.data.items));
this.isLoading = false;
}).catch(err => {
this.results = err.message;
throw Error(err.message);
this.isLoading = false;
});
} else {
this.clear();
}
}
}
});
<script src=”https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src=”https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<script src=”https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

<div id=”app”>
<input v-model=”query” @keyup.stop=”handleSearch” type=”text” class=”form-control” placeholder=”Search”>
<button @click.stop=”clear”>Clear</button>
<div v-if=”isLoading”>Loading…</div>
<ul v-if=”results !== ‘’”>
<li v-for=”(r, index) in results” :key=”index”>
{ r.name }
</li>
</ul>
</div>

[CodePen mirror]

Cancelled requests:

Solution 2:

The problem is that you’re creating a new canceltoken in the newSearch and canceling that instead of the original one.
If you save the source on the vue.js component you can check in newSearch if it exists and only cancel then.
When the post Promise has completed you delete the source again so you can’t cancel when it’s not needed (or possible).

{
searchItems() {
let filters = {
q: this.query
};

const CancelToken = axios.CancelToken;
this.searchItemsSource = CancelToken.source();

axios.post(‘/Items/find’, filters, {
cancelToken: this.searchItemsSource.token
})
.catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log(‘Request canceled’, thrown.message);
}
})
.then(
response => {
this.searchItemsSource = undefined;
if(this.Items!=null){
response.data.forEach(element => {
this.Items.push(element);
});
}
else
this.Items=response.data;
}
);
},
newSearch(){
if (this.searchItemsSource) {
this.searchItemsSource.cancel(‘Cancel previous request’);
}
this.countItems();
this.searchItems();
},
}

A side note about this code; I’d actually move the canceling of the previous request into the searchItems method since it never makes sense to have two running call’s at the same time. It would look more like this:

{
searchItems() {
let filters = {
q: this.query
};

if (this.searchItemsSource) {
this.searchItemsSource.cancel(‘Cancel previous request’);
}
const CancelToken = axios.CancelToken;
this.searchItemsSource = CancelToken.source();

axios.post(‘/Items/find’, filters, {
cancelToken: this.searchItemsSource.token
})
.catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log(‘Request canceled’, thrown.message);
}
})
.then(
response => {
this.searchItemsSource = undefined;
if(this.Items!=null){
response.data.forEach(element => {
this.Items.push(element);
});
}
else
this.Items=response.data;
}
);
},
newSearch(){
this.countItems();
this.searchItems();
},
}

At this point you can ask yourself if the newSearch method is needed at all, you might remove it and move the countItems call into searchItems as well. This all depends on the rest of the code and functionality though.

[Vue.js] List not rendering in v-for directive

there is what seems to be a pretty straightforward list rendering situation but can’t seem to get it to work. there is a component that when the mounted event fires sends an async call to an API to get data. Upon fetching the data, it sets the packages array with the value of the data. However, the list never actually renders in Vue. I’ve done this a number of times before without issue. Not sure what the problem is now.

Vue.component(“tech-editing-queue”, {
props: [],
data: function () {
return {
packages: []
};
},

template: `
<div>
<div class=”table-responsive”>
<table id=”package-table” class=”table table-striped”>
<thead>
<tr>
<th><a href=”#” style=”color: inherit;”>Package</a></th>
<th><a href=”#” style=”color: inherit;”>Submitter</a></th>
<th><a href=”#” style=”color: inherit;”>Status</a></th>
<th><a href=”#” style=”color: inherit;”>Pages</a></th>
<th><a href=”#” style=”color: inherit;”>Review Type</a></th>
<th><a href=”#” style=”color: inherit;”>Description</a></th>
<th><a href=”#” style=”color: inherit;”>Document Name(s)</a></th>
<th><a href=”#” style=”color: inherit;”>Submission Date</a></th>
<th><a href=”#” style=”color: inherit;”>Requested Due Date</a></th>
<th><a href=”#” style=”color: inherit;”></a></th>
</tr>
</thead>
<tbody>
<tr v-for=”package in packages”>
<td>
<button type=”button” class=”btn btn-link”>
<span class=”glyphicon glyphicon-duplicate”></span>
<span style=”margin: 0px 6px;”>{ package.PackageName }</span>
<span class=”label label-primary” style=”border-radius: 50%;”>1</span>
</button>
</td>
<td>{ package.Submitter.LastName }, { package.Submitter.FirstName }</td>
<td>
<h4 style=”margin: 0px;”>
<span class=”label label-info”>
{ package.StateString }
</span>
</h4>
</td>
<td>{ package.Pages }</td>
<td>{ package.ReviewType }</td>
<td>{ package.DocumentType.Description }</td>
<td><span>{ package.DocumentNames }</span></td>
<td><span>{ package.SubmissionDate }</span></td>
<td><span>{ package.RequestedDueDate }</span></td>
<td><button id=”package-menu-7112” type=”button” class=”btn btn-link”><i class=” fa fa-ellipsis-h fa-1x undefined” aria-hidden=”true”></i></button></td>
</tr>
</tbody>
</table>
</div>
</div>
`,

mounted: function () {
fetch(“/api/tech-editing-packages”)
.then(res => res.json())
.then(response => this.packages = response)
.catch(error => console.log(“Packages Error: “, error));
},

watch: {},

methods: {}
});

This packages list looks like this:

list view

The page looks like this after rendering.

page view

I expect the page to render the packages in table form but it doesn’t.

Solution :

Try check if has items before redder the items:

<tr v-if=”packages.length > 0” v-for=”package in packages”>

or

<tr v-if=”packages[0].Submitter !== undefiend” v-for=”package in packages”>

[Vue.js] VueJs - Pushing created item to existing array and having it display with the other existing items

I’m executing a POST request using vue.js to insert a new record to the database. This is working as expected and the next target is to have the newly created item pushed to the existing array and have it display in a table. This is being done in a vue.js component.

This is the form that is being submitted:

<form @submit.prevent=”createUser”>

This is the javascript part:

export default {
data(){
return{
users: {},

form: new Form({
name: ‘’,
email: ‘’,
password: ‘’,
type: ‘’,
bio: ‘’,
photo: ‘’,
})
}
},
methods:{
displayUsers(){
axios.get(‘api/user’).then( ({data}) => (this.users = data) )
},

createUser(){
this.form.post(‘api/user’).then( ({ data }) =>
this.users.push(data.data)
);
}
},
created() {
this.displayUsers();
}
}

From the createUser method, the entry is posted to the database and the created entry pushed to the existing users array. My backend code returns this data i.e.

return response()->json([‘data’ => $request->all()], 200);

Was thinking this would be enough to get the new entry to display on the table automatically without refresh as the users array has been updated but this is not happening.

The table displaying all the items looks like this:

<tr v-for=”user in users” :key=”user.id”>
<td>{ user.id }</td>
….

So what I’m i missing? Is there an extra step needed for my freshly created entry to be pushed automatically to my table?

Solution :

Try this -

In the createUser method, when you are assigning the newly created user, avoid mutation.

createUser(){
this.form.post(‘api/user’).then( ({ data }) =>{
this.users = [ …this.users, data.data ];
});
}

This will help vue.js identify that the list has changed as we are assigning an entirely new array to users everytime a new user is created.

The push method modifies the same array. The spread operator helps avoid this mutation as we are copying all users in the new array along with newly created user.

[Vue.js] Vue beforeUpdate event firing twice for recursive component

Just started learning vue.js js and have been experimenting with a recursive tree example based on this example the offical example here

The example above starts out with treedata having a single root followed by many children, I was trying to extend the same to having multiple root elements, example here.

In my example, I notice the beforeUpdate is being called twice for every component click, moreover even if I try to directly push elements into children, the beforeUpdate is still called twice whereas in the official recursive example, this happens once(debugged via vue-devtools). I’m unable to find a explanation for the above behaviour, can anyone advice on why this happens?

Is this because I do a v-for in li instead of the actual component name?

EDIT:
I add a datetime to see which all elements are being rendered & it appears in my example, all children to be re-rendered, seen via the time on the component

Solution :

The reason the onUpdate is called twice is because it is called once for the outer component, and once for the nested component. I added a unique ID to each component instance and confirmed this in the alert.

The project you reference only changes state in the clicked component node because the entire tree is already rendered by using the v-show directive instead of a v-if directive.

You example actually adds nodes to the data, so the child component is rendered, and the outer component is updated.

Solution 2:

Thanks to Steven Spungin who helped me track the id’s of the components that helped me debug this problem.

I’ve figured out the problem, when doing:

<li v-for=”(filter, index) in filters”
v-bind:key=”index”
v-on:click.self=”addfilter(filter)”>

{filter.name + new Date()}

<template v-if=”filter.children”>
<filter-tree
v-bind:filters=”filter.children”>
</filter-tree>
</template></div>

</li>

The loop on li creates a single parent with child multiple filter-tree components which is incorrect, it appears like a recursive call should be responsible to create/render itself & child components via the v-for on filter-tree as seen in official example.

Here’s the correct version of my example: https://jsfiddle.net/z3sekaqy/

[Vue.js] VueJs radio button with no value turns on all radio input elements

I don’t quite understand this behavior.

In view when dealing radio input elements that don’t have a value attribute set, clicking on one radio button turns all of them on. Why is this?

I know the solution is to add a value to each. In regular HTML this does not happen.

<!DOCTYPE html>
<html>
<head>
<title>My first vue.js app</title>
<script src=”https://cdn.jsdelivr.net/npm/vue"></script>
<style>

</style>
</head>
<body>
<div id=”multiple_radios”>
<input type=”radio” id=”PC” v-model=”picked”>
<label for=”PC”>PC (Windows)</label>

<input type=”radio” id=”Mac” v-model=”picked”>
<label for=”Mac”>Mac</label>

<p>{ picked }</p>
</div>
<script>
const multiple_radios = new Vue({
el: ‘#multiple_radios’,
data : {
picked : ‘’
}
});
</script>
</body>
</html>

Solution :

When you don’t set the value, both of them are undefined. So when you click on 1 radio button, picked value is set to undefined, too. That’s why both radio buttons are selected.

<!DOCTYPE html>
<html>
<head>
<title>My first vue.js app</title>
<script src=”https://cdn.jsdelivr.net/npm/vue"></script>
<style>

</style>
</head>
<body>
<div id=”multiple_radios”>
<input type=”radio” id=”PC” v-model=”picked”>
<label for=”PC”>PC (Windows)</label>

<input type=”radio” id=”Mac” v-model=”picked”>
<label for=”Mac”>Mac</label>

<p>Is undefined? { picked == undefined }</p>
</div>
<script>
const multiple_radios = new Vue({
el: ‘#multiple_radios’,
data : {
picked : ‘’
}
});
</script>
</body>
</html>

Solution 2:

I think that you must to add attribute value in the input. When you click on radio, picked will be set. If you don’t click on it, the value of picked will be unchanged.

<!DOCTYPE html>
<html>
<head>
<title>My first vue.js app</title>
<script src=”https://cdn.jsdelivr.net/npm/vue"></script>
<style>

</style>
</head>
<body>
<div id=”multiple_radios”>
<input type=”radio” id=”PC” value=”PC” v-model=”picked”>
<label for=”PC”>PC (Windows)</label>

<input type=”radio” id=”Mac” value=”Mac” v-model=”picked”>
<label for=”Mac”>Mac</label>

<p>{ picked }</p>
</div>
<script>
const multiple_radios = new Vue({
el: ‘#multiple_radios’,
data: {
picked : null
}
});
</script>
</body>
</html>