Event after click element in Vue - javascript

This is my first post about VUE. I try use VUE in Laravel. I have this code:
index.blade.php:
#extends('front._layout.main')
#section('content')
<div class="container mx-auto" id="vue-rendered">
<p class="text-white text-3xl">PÅ‚yty</p>
<div class="mt-5 max-w-screen-md mx-auto text-text text-lg">
<div class="text-right text-xl">
<div class="text-white">Sortowanie:</div>
</div>
xxxxx
<product-list></product-list>
</div>
</div>
#endsection
ProductList.vue:
<template>
<form>
<div class="multiselect">
<div class="selectBox" id="selectBox">
<select>
<option>Typ</option>
</select>
<div class="overSelect"></div>
</div>
<div class="checkboxes">
<label for="one">
<input type="checkbox" id="one"/>First checkbox</label>
<label for="two">
<input type="checkbox" id="two"/>Second checkbox</label>
<label for="three">
<input type="checkbox" id="three"/>Third checkbox</label>
</div>
</div>
</form>
</template>
<script>
import axios from "axios";
export default {
name: "product-list",
mounted() {
this.loadProducts();
},
data() {
return {
products: [],
}
},
methods: {
loadProducts() {
axios
.get(route('json.products.get.list'))
.then(response => {
this.products = _.get(response, "data", []);
})
.catch(error => {
console.log(error);
});
}
}
}
window.onload = function () {
var selectBox = new Vue({
el: '#selectBox',
data: {
name: 'selectBox'
},
methods: {
showMultiselect: function (event) {
alert('It working')
showMultiselect();
}
}
});
}
</script>
multiselect.js:
var expanded = false;
function showMultiselect() {
var checkboxes = document.getElementsByClassName("checkboxes");
if (!expanded) {
checkboxes.style.display = "block";
expanded = true;
} else {
checkboxes.style.display = "none";
expanded = false;
}
}
app.js:
try {
window._ = require('lodash');
window.axios = require('axios');
window.route = require('#/common/route');
require('./libs/swal.js');
require('./vue');
require('./libs/multiselect.js');
window.Vue = require('vue');
Vue.component('product-list', require('./components/ProductList.vue').default);
const app = new Vue({
el: '#vue-rendered',
})
} catch (e) {
console.log(e);
}
My problem is no action after click after click #selectBox.
I want show alert and run function showMultiselect.
Htom, laravel show correct html code.
How can I repair it?
Please help me. I am beginner in Vue

Looking at the Vue file, you can handle click events using the v-on:click (or #click for shorthand) - see Vue Docs - Event Handling for more info. You can also handle conditional rendering of the checkboxes with the v-if directive - see Vue Docs - Conditional Rendering for more info.
The end result in the .vue file, using your previous code, would be something like this.
ProductList.vue:
<template>
<form>
<div class="multiselect">
<div class="selectBox" id="selectBox" #click="toggleMutliSelect">
<select>
<option>Typ</option>
</select>
<div class="overSelect"></div>
</div>
<div v-if="showMultiSelect" class="checkboxes">
<label for="one">
<input type="checkbox" id="one"/>First checkbox</label>
<label for="two">
<input type="checkbox" id="two"/>Second checkbox</label>
<label for="three">
<input type="checkbox" id="three"/>Third checkbox</label>
</div>
</div>
</form>
</template>
<script>
import axios from "axios";
export default {
name: "product-list",
mounted() {
this.loadProducts();
},
data() {
return {
products: [],
showMultiSelect: false,
}
},
methods: {
loadProducts() {
axios
.get(route('json.products.get.list'))
.then(response => {
this.products = _.get(response, "data", []);
})
.catch(error => {
console.log(error);
});
},
toggleMutliSelect() {
alert('It working')
this.showMultiSelect = !this.showMultiSelect
}
}
}
</script>

Related

Based on v-on:click, How to uncheck the checkbox values in Vuejs?

<div class="reser-productlist">RESET</div>
<div class="checkbox-alignment-form-filter">
<input type="checkbox" id="Coils" value="Coils" class="vh-product" v-model="checkedNames" />
<label class="productlist-specific" for="Coils">Cs</label>
</div>
<div class="checkbox-alignment-form-filter">
<input type="checkbox" id="Sheets" value="Sheets" class="vh-product" v-model="checkedNames" />
<label class="productlist-specific" for="Sheets">Sts</label>
</div>
Based on v-on:click, How to uncheck/reset the checkbox,
Basically i want to uncheck the checkboxes, When user click on the RESET button/label. Generally to do this do i need to use the v-model or id or for in label to target and trigger the reset functionality?
I think you can use below code.
<div class="reser-productlist" #click="reset">RESET</div>
<script>
export default
{
methods:{
reset()
{
this.checkedNames = '';
}
}
}
</script>
const App = new Vue({
el: '#app',
template: `<div>
<div class="reser-productlist" #click="reset">RESET</div>
<div v-for="product in products" class="checkbox-alignment-form-filter">
<input type="checkbox" :id="product" :value="product" class="vh-product" v-model="checkedNames" />
<label class="productlist-specific" :for="product">{{ product }}</label>
</div>
</div></div>
`,
data() {
return {
products: ['Coils', 'Sheets'],
checkedNames: [],
}
},
methods: {
reset() {
this.checkedNames = []
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.12"></script>
<div id=app>

How to checked radio button in Vue.js using V-Model?

Im new to laravel and vue.js. I'm developing a simple online examination and Im having a hard time in showing the answer of the user if he/she will click the previous button.
This my template I used v-for to loop the questions:
<div class="myQuestion" v-for="(question, index) in questions" :key="index + uuid">
<div class="row">
<div class="col-md-6">
<blockquote >
Total Questions {{ index+1 }} / {{questions.length}}
</blockquote>
<h2 class="question">Q. {{question.question}}</h2>
<form class="myForm" action="/quiz_start" v-on:submit.prevent="createQuestion(question.question_id, question.answer, auth.id, question.topic_id)" method="post">
<input class="radioBtn" v-bind:id="'radio'+ index" type="radio" v-model="result.user_answer" value="A" aria-checked="false" > <span>{{question.a}}</span><br>
<input class="radioBtn" v-bind:id="'radio'+ index+1" type="radio" v-model="result.user_answer" value="B" aria-checked="false"> <span>{{question.b}}</span><br>
<input class="radioBtn" v-bind:id="'radio'+ index+2" type="radio" v-model="result.user_answer" value="C" aria-checked="false"> <span>{{question.c}}</span><br>
<input class="radioBtn" v-bind:id="'radio'+ index+3" type="radio" v-model="result.user_answer" value="D" aria-checked="false"> <span>{{question.d}}</span><br>
<div class="row">
<div class="col-md-6 col-xs-8">
<button type="submit" class="btn btn-wave btn-block nextbtn">Next</button>
</div>
</div>
<div class="row">
<div class="col-md-6 col-xs-8">
<button type="submit" class="btn btn-wave btn-block prebtn">Previous</button>
</div>
</div>
</form>
</div>
</div>
</div>
This is my script to fetch the data and insert the data array to questions variable.
<script>
import { v4 as uuidv4 } from 'uuid';
export default {
props: ['topic_id'],
data () {
return {
questions: [],
answers: [],
uuid:0,
result: {
question_id: '',
answer: '',
user_id: '',
user_answer:0,
topic_id: '',
},
auth: [],
}
},
created () {
this.fetchQuestions();
},
methods: {
fetchQuestions() {
this.$http.get(`${this.$props.topic_id}/quiz/${this.$props.topic_id}`).then(response => {
this.questions = response.data.questions;
this.auth = response.data.auth;
this.uuid=uuidv4();
console.log(this.questions);
}).catch((e) => {
console.log(e)
});
},
createQuestion(id, ans, user_id, topic_id) {
this.result.question_id = id;
this.result.answer = ans;
this.result.user_id = user_id;
this.result.topic_id = this.$props.topic_id;
this.$http.post(`${this.$props.topic_id}/quiz`, this.result).then((response) => {
console.log(response.data.message);
let newdata=response.data.newdata;
this.questions.splice(newdata[0]["index"],1,newdata[0]);
}).catch((e) => {
console.log(e);
});
this.result.topic_id = '';
this.result.user_answer =0;
}
}
}
</script>
I used jQuery next() and prev() for the next and previous buttons. In questions variable, I store my array of objects from database which contains the questions and choices so after the user click next it will update the element of questions to insert the answer chosen by the user. My problem is how can I checked the answer by default chosen by the user if the question showed was answered already by the user. This is the time when the user wants to review his/her answers before finishing the exam.

VueJS = Uncaught TypeError: Cannot read property 'settings' of undefined

I have a basic input that should update a data on input change, but it doesn't because it returns Uncaught TypeError: Cannot read property 'settings' of undefined
Vue component
<template>
<div>
<div class="inner_container">
<p>
URL:
<span>{{settings.url}}</span>
</p>
<div class="input_row">
<input
class="input_text"
id="getURL"
type="url"
inputmode="url"
placeholder="Enter URL"
title="URL"
#input="changeUrl"
/>
<label class="label_" for="getURL">URL Link</label>
</div>
<button class="button" #click="saveSettings">Save all Values</button>
</div>
<div>
</template>
<script>
import axios from "axios";
import _ from "lodash";
export default {
name: "Home",
data() {
return {
settings: {
brightness: "",
},
};
},
methods: {
changeUrl: _.debounce((e) => {
this.settings.url = e.target.value;
}, 500),
},
};
</script>
On each input change I receive the above error.
What am I doing wrong ?
The problem is that this in the arrow function is not referring to the object you want. One solution is to use a normal function and predefine the property url in settings:
new Vue({
el: '#app',
data() {
return {
settings: {
brightness: "",
url: ""
},
};
},
methods: {
changeUrl: _.debounce(function(e) {
this.settings.url = e.target.value;
}, 500),
saveSettings(){
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.19/lodash.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<div id="app">
<div class="inner_container">
<p>
URL: <span>{{settings.url}}</span>
</p>
<div class="input_row">
<input
class="input_text"
id="getURL"
type="url"
inputmode="url"
placeholder="Enter URL"
title="URL"
#input="changeUrl"
/>
<label class="label_" for="getURL">URL Link</label>
</div>
<button class="button" #click="saveSettings">Save all Values</button>
</div>
</div>
A simpler approach you may find useful is to set the variable using v-model:
new Vue({
el: '#app',
data() {
return {
settings: {
brightness: "",
},
};
},
methods: {
saveSettings(){
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.19/lodash.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<div id="app">
<div class="inner_container">
<p>
URL: <span>{{settings.url}}</span>
</p>
<div class="input_row">
<input
class="input_text"
id="getURL"
type="url"
inputmode="url"
placeholder="Enter URL"
title="URL"
v-model="settings.url"
/>
<label class="label_" for="getURL">URL Link</label>
</div>
<button class="button" #click="saveSettings">Save all Values</button>
</div>
</div>
Ciao, try to use debounce like this:
_.debounce(function(e) {
this.settings.url = e.target.value;
}, 500)
The problem is that you are using this in a statement that is not being called on a JS class. Fix this by changing the this to a variable name, and setting that variable name to a class.

Initialise canvas for every Vue.JS template loop

I'm stuck trying to work out how to initialize a local "signaturePad" canvas for every loop / signature required.
I'm also keen to bind "dataURL" to signaturePad.toDataURL("image/jpg"). I.e. show the dataURI for each signature entered.
Hope you can help! Here's the JSfiddle too: https://jsfiddle.net/kaihendry/kt53sa2r/1/
// var canvas = document.querySelector("canvas");
// var signaturePad = new SignaturePad(canvas);
// var wrapper = document.getElementById("signature-pad");
// How do I initialise signaturePad for every signatureNeeded?
new Vue({
el: "#app",
data: {
signaturesNeeded: 2,
},
methods: {
submitForm: function(x) {
fetch('/echo/html', {
method: 'POST',
body: new FormData(x.target)
})
.then(() => {
var button = document.getElementById("button")
button.innerText = 'Sent!'
})
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/signature_pad#2.3.2/dist/signature_pad.min.js"></script>
<div id="app">
<label>Number of signatures required
<input type=number v-model.number="signaturesNeeded">
</label>
<form id="myForm" v-on:submit.prevent="submitForm">
<template v-for="item in signaturesNeeded">
<div class="signature-pad">
<div class="signature-pad--body">
<canvas></canvas>
</div>
<div class="signature-pad--footer">
<div class="description">Sign above</div>
</div>
<input required type=text size=80 placeholder="Name" name=name>
<input required type=text size=80 name=dataURL>
</template>
<button class="button" id="button" type="submit">Sign</button>
</form>
Signature pad sources
</div>
You can define custom component (signature-pad for example) and initialize SignaturePad there. I created working snippet below. It also update signature data url when user stops writing(it shows below the canvas) and as example all urls are collected by parent component. Check it:
Vue.component('signature-pad', {
template: '#signaturepad',
data() {
return {
signaturePad: null,
dataUrl: null
}
},
mounted() {
this.signaturePad = new SignaturePad(this.$refs.canv, {
onEnd: () => {
this.dataUrl = this.signaturePad.toDataURL();
// as example collect all url in parent
this.$emit('update', this.dataUrl)
}
});
}
});
new Vue({
el: "#app",
data: {
signaturesNeeded: 2,
// all signature urls as example
signatureDataUris: []
},
methods: {
submitForm: function (x) {
fetch('/echo/html', { method: 'POST',
body: new FormData(x.target) })
.then(() => {
var button = document.getElementById("button")
button.innerText = 'Sent!'
})
},
updateSignature(index, url) {
Vue.set(this.signatureDataUris, index, url);
console.log(this.signatureDataUris);
}
}
})
<script src="https://cdn.jsdelivr.net/npm/signature_pad#2.3.2/dist/signature_pad.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<label>Number of signatures required
<input type=number v-model.number="signaturesNeeded">
</label>
<form id="myForm" v-on:submit.prevent="submitForm">
<template v-for="item in signaturesNeeded">
<signature-pad #update="(val) => updateSignature(item-1, val)" ></signature-pad>
<input required type=text size=80 placeholder="Name" name=name>
</template>
<button class="button" id="button" type="submit">Sign</button>
</form>
Signature pad sources
</div>
<script type='text/x-template' id="signaturepad">
<div class="signature-pad">
<div class="signature-pad--body">
<canvas ref="canv"></canvas>
<div>{{dataUrl}}</div>
</div>
<div class="signature-pad--footer">
<div class="description">Sign above</div>
</div>
</div>
</script>

Reset form state VueJS and VueRouter

I am currently working on a step by step registration created with VueJS and VueRouter.
The basic premise of the form is that a user has to select a signup option before proceeding to enter his personal details. However, I would like the form to be reset every time a different sign up option is selected.
VueJs + VueRouter Multi Step Form
/**
*
* #type {Vue}
*/
let page2Component = Vue.component('pageTwo', {
data: function() {
return {
step1: {
firstname: '',
lastname: ''
}
}
},
template: `<div>
<h2>Registration</h2>
<form action="" method="post" role="form">
<legend>Details</legend>
<div class="form-group">
<label for="firstname">First name</label>
<input type="text" class="form-control" name="firstname" id="firstname" placeholder="First name..." v-model.trim="step1.firstname">
</div>
<div class="form-group">
<label for="lastname">Last name</label>
<input type="text" name="lastname" class="form-control" id="lastname" placeholder="Last name..." v-model.trim="step1.lastname">
</div>
</form>
<div>
<router-link to="/" class="btn btn-default">Back</router-link>
<router-link to="/" class="btn btn-primary">Next Page</router-link>
</div>
</div>`,
created: function () {
},
methods: {
resetUserDetails: function() {
this.step1.firstname = '';
this.step1.lastname = '';
}
}
});
/**
*
* #type {Vue}
*/
let page1Component = Vue.component('pageOne', {
data: function() {
return {
selectedSignUpOption: ''
}
},
template: `<div>
<h2>Registration</h2>
<form action="" method="post" role="form">
<legend>Sign Up Options</legend>
<div class="form-group">
<div>
<div class="radio">
<label>
<input type="radio" name="signup_option" value="user" v-model.trim="selectedSignUpOption"> Register As A User
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="signup_option" value="content-editor" v-model.trim="selectedSignUpOption"> Register As A Content Editor
</label>
</div>
</div>
</div>
</form>
<div>
<router-link to="/page2" class="btn btn-primary" v-bind:disabled="!signupOptionSelected">Next Page</router-link>
</div>
</div>`,
created: function () {
},
watch: {
'$route'(to, from) {
// react to route changes...
// don't forget to call next()
console.log('to: ', to);
console.log('from: ', from);
console.log(this);
},
selectedSignUpOption: function() {
console.log(this);
console.log(this.selectedSignUpOption);
}
},
computed: {
signupOptionSelected: function() {
return this.selectedSignUpOption !== '';
}
}
});
/**
*
* #type {Vue}
*/
let wizardComponent = Vue.component('wizardForm', {
template: `<div>
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>`,
created: function () {
let children = [];
children.push({path: '/', component: page1Component});
children.push({path: '/page2', component: page2Component});
router.addRoutes(children);
}
});
/**
* Vue App Initialisation
*/
Vue.config.devtools = true;
Vue.use(VeeValidate);
const routes = [];
const router = new VueRouter({
routes // short for routes: routes
});
console.log('routes', routes);
document.addEventListener('DOMContentLoaded', function () {
/**
*
*/
let vm = new Vue({
el: '#app',
router,
});
});
I have included a link to the form that I am working on. Any one have any idea as to how I can achieve this? Ideally, I would like to be able to call the resetUserDetails method in the page2Component when the sign up option is different to the last one that was selected.
Any suggestions would be appreciated. I am using VueJS 2 btw.
Thanks,
Emmanuel
For this to work you should pass selected value as to second component.
your route config will look like this
children.push({path: '/:option/page2', component: page2Component});
form component
watch: {
'$route.params.option'(to, from) {
if((this.prevSelection && this.$route.params.option) && (this.$route.params.option !== this.prevSelection)){
this.prevSelection = this.$route.params.option
this.resetUserDetails()
}
}
}
For more information please have a look at this

Categories