My vue component like this :
<template>
<div>
...
<form class="form-horizontal" id="form-profile">
...
<input type="number" class="form-control" required>
...
<button type="submit" class="btn btn-primary" #click="submit">Submit</button>
...
</form>
...
</div>
</template>
<script>
export default {
...
methods: {
submit(e) {
e.preventDefault()
if (this.checkForm()) {
// do ajax here
}
},
checkForm() {
let field = true
$('#form-profile :required').each(function(i) {
if(this.checkValidity() == false)
field = false
})
return field
},
}
}
</script>
I using required html5 to validation
I using e.preventDefault() to prevent page redirects. Because I want to using ajax
My problem here is the required validation html5 not show if not filled. Maybe it because I using e.preventDefault()
How can I display the required html5?
In order to work as expected you have to set the v-on:submit method on the form tag, and have a button/input type "submit".
Also, notice the event modifier prevent on the #submit, it's a shorcut to not have to write e.preventDefault() on the method
new Vue({
el: '#app',
data() {
return {
myText: ''
}
},
methods: {
submitForm() {
alert('submited: ' + this.myText)
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.15/vue.js"></script>
<div id="app">
<form #submit.prevent="submitForm">
<input type="text" v-model="myText" required />
<button type="submit">Submit</button>
</form>
</div>
Related
I am trying to validate the check box and navigate to next link for ex google.com. I found the solution for checkbox validation from the below link
Vue JS - Checkbox validation error on submit from #wolfrevo
new Vue({
el: "#app",
data: {
termsState: false,
validated: false,
nextPageUrl:'www.google.com'
},
computed: {
termsError() {
return this.validated && !this.termsState
}
},
methods: {
handleTermsState() {
this.validated = false
},
handleSubmit() {
this.validated = true
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id='app'>
<label for="terms">
Terms and Privacy Policy
<input type="checkbox" id="terms" name="terms" v-model="termsState" #change="handleTermsState">
{{ termsState }}
</label>
<p style="color: red" class="for-error terms-error" v-if="termsError">You have to agree the terms and privacy condition.</p>
<router-link :to="nextPageUrl">
<div><button type="submit" #click="handleSubmit">Submit</button></div>
</router-link>
</div>
I tried adding router-link, it is redirecting even without validating the checkbox. what is that I am missing?
How do I access a variable defined in a js file from a vue file? Is there a way to pass this variable to the vue file? In the code below, I've got a template.js file and a contact.vue file. I am converting mjml to html in the template file and I need to access the output saved to the plainHmtl variable from the vue file.
template.js
const mjml2html = require('mjml')
const Vue = require('vue')
const app = new Vue({
data: {
name: ''
},
template: `
<mj-section>
<mj-column>
<mj-text font-size="20px" color="#F45E43" font-family="helvetica">Hello {{ name }}</mj-text>
</mj-column>
</mj-section>`
})
const renderer = require('vue-server-renderer').createRenderer({
template: `
<mjml>
<mj-body>
<!--vue-ssr-outlet-->
</mj-body>
</mjml>`
})
renderer.renderToString(app).then(html => {
const htmlWithoutDataServerRenderedAttribute = html.replace(`data-server-rendered="true"`, '')
const plainHtml = mjml2html(htmlWithoutDataServerRenderedAttribute)
console.log(plainHtml.html)
})
contact.vue
<template>
<div class="sign_up" id="signupform">
<main role="main">
<div class="SignUp_container">
<form class="form-signup" #submit.prevent="processForm">
<input type="text" name="name" placeholder="Enter First Name" required/>
<input type="text" name="lname" placeholder="Enter Last Name" required/>
<input type="email" name="mailaddr" placeholder="Your email address" required/>
<div class="sign_cancel_buttons">
<router-link to="/">
<button id="canlbtn" type="cancel" class="clbtn">
Cancel
</button>
</router-link>
<button id="signupbtn" type="submit" name="sendmsg-button" class="signbtn">
Sign Up
</button>
</div>
</form>
</div>
</main>
</div>
</template>
<script>
export default {
methods: {
// how do I access plainHtml here?
}
}
</script>
In template.js, define a variable where you will have the final result of converting your html, once defined just add this to the end of the file:
export { varHTML }
Now in contact.vue you have to import and use the export we made from template.js, consider that you must modify the import path according to the case that you are handling for your files:
import { varHTML } from './template.js'
<script>
export default {
data() {
return {
plainHtml: null
}
}
methods: {
// how do I access plainHtml here?
// any method that is going to be needed now will have plainHtml available
},
created () {
this.plainHtml = varHTML
}
}
</script>
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.
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>
Long story short, it works if I change < to = here:
const rtmNav = {
bindings: {
from:'<',
to:'<',
submit: '&'
},
controller: angular.noop,
templateUrl: require('./rtmNav.html')
}
export default rtmNav;
This is the controller where dataa object is defined:
class DemandCtrl {
constructor(ChartDataService) {
this.ChartDataService = ChartDataService;
debugger;
this.dataa = {
from: '10/01/2017',
to: '10/03/2017'
};
}
$onInit() {
getData.call(null, this);
}
update() {
getData.call(null, this);
}
}
The component looks like this:
<div class="rtm-nav">
<div ng-app>
<form ng-submit="$ctrl.submit()">
<label>From:
<input type="text" name="input" ng-model="$ctrl.from">
</label>
<label>To:
<input type="text" name="input" ng-model="$ctrl.to">
</label>
<input type="submit" id="submit" value="Apply" />
</form>
</div>
</div>
And the html page like this:
<div class="demand page">
<rtm-header title="Demand" icon="fa fa-line-chart" link=true></rtm-header>
<rtm-nav from="$ctrl.dataa.from", to="$ctrl.dataa.to", submit="$ctrl.update()">
</rtm-nav>
<div id="chart" class="demand-chart">
</div>
</div>
When I first run the application, it shows the chart between the hardcoded values (10/01/2017 and 10/03/2017). If it is made as two-way data binding, if I change those values and click on apply it will re-render the chart with the new data.
My constraint is do to it one-way data binding.
I don't know how to do it, show I send the new parameters in update() or should I add them somehow in the component?