How to use template inside a form in vue js - javascript

I have created a vue instance for the form
var formObject = new Vue({
el: '#amount_form',
data: {
logdate: '',
amount:'',
description:''
},
methods: {
processForm :function(event)
{
var data = {"logdate":this.logdate,"amount":parseFloat(this.amount),"description":this.description};
console.log(data);
var parameters =
{
"data":data,
"url":"save",
"type":"post",
"data_type":"JSON",
"callback":function(data)
{
alert(data);
}
}
sendDataToSErver(parameters);
}
}
});
i have a template for categories
var categorySelect = Vue.component('category-select',
{
data()
{
return{
options:[],
cat:""
}},
template:'<select class="form-control form-control-sm" v-model="cat">' +
' <option v-for="option in options" v-bind:value="option.id">{{option.name}}</option></select>',
created :function()
{
var templateObject = this;
var parameters =
{
"url":"getCategories",
"type":"GET",
"async":true,
"data_type":"JSON",
"callback":function(data)
{
templateObject.options = data;
}
}
sendDataToSErver(parameters);
}
});
i am using this template inside the form
<div class="row">
<div class="col-3">
<div class="form-group">
<label for="log_date" class="sr-only">Date</label>
<input v-model="logdate" type="datetime-local" id="log_date" class="form-control form-control-sm" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-sm">
</div>
</div>
<div class="col-3">
<div class="form-group">
<label for="amount" class="sr-only">Amount</label>
<input v-model="amount" type="text" class="form-control form-control-sm" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-sm">
</div>
</div>
<div class="col-3">
<div class="form-group">
<label for="category" class="sr-only">Category</label>
<category-select></category-select>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="form-group">
<label for="description" class="sr-only">Description</label>
<textarea v-model="description" class="form-control" id="description" aria-label="With textarea"></textarea>
</div>
</div>
</div>
</form>
Now how can get the value in form.

You can emit an event from the child. The parent needs to listen for the custom event and get the data from there. You also need to listen for onChange on your select to emit the event.
The template for categories should be something like this
var categorySelect = Vue.component('category-select',
{
data()
{
return {
options:[],
cat:""
}
},
template:'<select class="form-control form-control-sm" v-model="cat" #change="handleUpdateSelectedValue($event)">' +
' <option v-for="option in options" v-bind:value="option.id">{{option.name}}</option></select>',
methods: {
handleUpdateSelectedValue(event) {
this.$emit('selectedValue', event.target.value) //emitting the event here
}
}
created :function()
{
var templateObject = this;
var parameters =
{
"url":"getCategories",
"type":"GET",
"async":true,
"data_type":"JSON",
"callback":function(data)
{
templateObject.options = data;
}
}
sendDataToSErver(parameters);
}
});
And now you need to listen for the event in the parent
<div class="col-3">
<div class="form-group">
<label for="category" class="sr-only">Category</label>
<category-select #selectedValue="handleSelectedValue"></category-select>
</div>
</div>
Now, the only thing that remains to do is to define handleSelectedValue in your parent component and do something with that value.
var formObject = new Vue({
el: '#amount_form',
data: {
logdate: '',
amount:'',
description:''
},
methods: {
handleSelectedValue(value) {
}
}
...

Related

Need the value (subtraction of value) to effect the value of another input

I'm trying to the value of money_due and have the value for deposit subtracted from it if the deposit input is holding a value. So far, it is adding it on just fine, but it is not removing it when I empty the value.
<div class="col-sm-12 col-md-6 col-lg-4">
<div class="form-group">
<label>Total Sum Due <span class="note">2</span></label>
<input type="text" class="form-control" v-model="document.money_due" placeholder="">
</div>
</div>
<div class="col-sm-12 col-md-6 col-lg-4">
<div class="form-group">
<label>Deposit <span class="note">2</span></label>
<input type="text" class="form-control" #change="hasDeposit" v-model="document.deposit" placeholder="">
</div>
</div>
data() {
return {
now: new Date().toISOString(),
document: {
deposit: '',
money_due: '',
}
}
},
this.document.deposit = this.listing.price;
this.document.money_due = this.document.last_month + this.document.security_deposit,
methods: {
hasDeposit() {
if(this.document.deposit == '') {
return this.document.money_due = this.document.money_due + this.document.deposit;
} else {
return this.document.money_due = this.document.money_due;
}
},
mounted() {
this.hasDeposit();
},
Sorry, but it's a bit unclear what you want to achieve with your code.
I created a snippet where I tried to model the deposit and the money_due relations.
new Vue({
el: "#app",
data: {
listing: {
price: 10
},
document: {
last_month: -20,
security_deposit: 10,
deposit: 0,
money_due: 0
},
},
computed: {
hasDeposit() {
return Number(this.document.money_due) + Number(this.document.deposit)
}
},
mounted() {
this.document.deposit = this.listing.price;
this.document.money_due = this.document.last_month + this.document.security_deposit
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<label>Total Sum Due <span class="note">2</span>
<input type="text" class="form-control" v-model="hasDeposit" placeholder=""></label><br />
<label>Deposit <span class="note">2</span>
<input type="text" class="form-control" v-model="document.deposit" placeholder=""></label>
</div>
I mocked the data that's referenced in your code
Moved hasDeposit() from being a method to computed (it only returns a calculated value)
Changed what's in mounted
I hope this is what you were after.

How do I use one input to control the other in vuejs

I need to find a way to basically show "per Month" in the assessments_period input if the assessments fee input has a typed-in value.
I've tried bindings and components but can't pull this off.
<div class="col-lg-6">
<div class="form-group">
<label>Assessment Fee <span class="note">C</span></label>
<input type="text" class="form-control" v-model="document.assessments_fee" placeholder="$">
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<label>Assessment Period <span class="note">C</span></label>
<input type="text" class="form-control" v-model="document.assessments_period" placeholder="(per month/quarter/etc.)">
</div>
</div>
data() {
return {
now: new Date().toISOString(),
document: {
assessments_fee: '',
assessments_period: '',
}
}
},
components: {
assessments_fee: function() {
if(this.assessments_fee != null || '') this.assessments_period = "per Month";
}
},
you can create a watcher for assessments_fee so when its not null assessments_period= 'per Month'.
Here is how you can do it:
new Vue({
el: '#app',
data() {
return {
now: new Date().toISOString(),
document: {
assessments_fee: '',
assessments_period: '',
}
}
},
computed: {
assessmentsFee() {
return this.document.assessments_fee
}
},
watch: {
assessmentsFee() {
this.document.assessments_fee ?
this.document.assessments_period = "per Month" :
this.document.assessments_period = ""
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="col-lg-6">
<div class="form-group">
<label>Assessment Fee <span class="note">C</span></label>
<input type="text" class="form-control" v-model="document.assessments_fee" placeholder="$">
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<label>Assessment Period <span class="note">C</span></label>
<input type="text" class="form-control" v-model="document.assessments_period" placeholder="(per month/quarter/etc.)">
</div>
</div>
</div>

Vuelidate errors return true but elements don't render

I have a contact form that uses vuelidate to validate fields. The problem is - the validation works, but the errors don't render.
$v.name.dirty is TRUE and $v.name.required is FALSE.
Logging $v.name.dirty && !$v.name.required returns TRUE which is the same condition in the v-if directive but the error elements still don't show.
However, when .$touch() is called and $v.name.dirty becomes true and $v.name.required false, anything I type in the input fields will show the errors.
JS:
import translationsBus from "../../app/translations";
export default {
name: "contactForm",
beforeMount() {
this.$store.dispatch("updateTranslations", translationsBus.translations);
},
data: function () {
return {
name: '',
email: '',
subject: '',
message: ' ',
errors: [],
isSuccessful: ''
}
},
mounted() {
var my_axios = axios.create({
baseURL: '/'
});
Vue.prototype.$http = my_axios;
},
computed: {
isLogged: function () {
return isLoggedOn;
},
shouldShowSubjectOption: function () {
return showSubjectOption;
},
translations: function () {
return this.$store.state.translations.translations;
},
},
methods: {
onContactUsClick: function onContactUsClick() {
const _this = this;
this.$v.$touch();
if (!this.$v.$error) {
let model = {
senderName: _this.name,
senderEmail: _this.email,
subject: _this.subject,
message: _this.message
};
this.$http.post('/home/contactus', model)
.then(response => {
console.log(response);
_this.isSuccessful = response.data;
})
.catch(e => {
console.log(e);
});
}
}
},
validations: {
email: {
required: required,
isValidEmail: function isValidEmail(value) {
var re = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/;
return re.test(value);
}
},
name: {
required: required
},
subject: {
required: required
},
message: {
required: required
}
}
}```
HTML:
<div v-bind:class="{ 'col-lg-6' : shouldShowSubjectOption, 'col-lg-12' : !shouldShowSubjectOption }">
<div id="form-contact">
<h1 class="lead">Get in touch...</h1>
<form class="text-center" >
<div class="form-group">
<label for="name">{{translations['contact_Form_Name']}}</label>
<div class="input-group">
<span class="input-group-addon"><span class="fa fa-user"></span></span>
<input type="text" class="form-control" name="senderName" id="senderName" v-model:bind="name" v-bind:placeholder="translations['contact_Form_NamePlaceholder']" />
</div>
<div class="has-error" v-cloak>
<label class="control-label" v-if="$v.name.$dirty && !$v.name.required">{{translations['shared_Validation_ReuiredField']}}</label>
</div>
</div>
<div class="form-group">
<label for="email">{{translations['contact_Form_EmailAddress']}}</label>
<div class="input-group">
<span class="input-group-addon"><span class="fa fa-envelope"></span></span>
<input type="email" class="form-control" name="senderEmail" id="senderEmail" v-model:bind="email" v-bind:placeholder="translations['contact_Form_EmailAddressPlaceholder']" />
</div>
<div class="has-error" v-cloak>
<label class="control-label" v-if="$v.email.$dirty && !$v.email.required">{{translations['shared_Validation_ReuiredField']}}</label>
<label class="control-label" v-if="$v.email.$dirty && $v.email.required && !$v.email.isValidEmail">{{translations['contact_Form_EmailAddressValidationMessage']}}</label>
</div>
</div>
<div class="form-group" v-if="shouldShowSubjectOption">
<label for="subject">{{translations['contact_Form_Subject']}}</label>
<select id="subject" name="subject" class="form-control" v-model:bind="subject" v-bind:title="translations['contact_Form_SubjectPickerText']">
<option value="service">1</option>{{translations['contact_Form_SubjectOption_GCS']}}
<option value="suggestions">2</option>{{translations['contact_Form_SubjectOption_Suggestions']}}
<option value="product">3</option>{{translations['contact_Form_SubjectOption_ProductSupport']}}
</select>
</div>
<div class="has-error" v-cloak>
<label class="control-label" v-if="$v.subject.$dirty && !$v.subject.required" v-cloak>{{translations['shared_Validation_ReuiredField']}}</label>
</div>
<div class="form-group">
<label for="name">{{translations['contact_Form_Message']}}</label>
<textarea name="message" id="message" class="form-control" v-model:bind="message" rows="9" cols="25"
placeholder="">{{translations['contact_Form_Message']}}</textarea>
</div>
<div class="has-error" v-cloak>
<label class="control-label" v-if="$v.message.$dirty && !$v.message.required">{{translations['shared_Validation_ReuiredField']}}</label>
</div>
<div class="form-group" v-if="isLogged">
<div class="g-recaptcha" data-sitekey=""></div>
</div>
<button type="button" class="btn btn-primary btn-block" v-on:click="onContactUsClick" id="btnContactUs">{{translations['contact_Form_SendMessageButton']}}</button>
</form>
</div>
</div>
</div>
</div>
I expect error elements to appear on submit.

how to set value form input vue js from json

please have a problem here. I want to display the value from the input form: name and position. but the data is in the form of json.
{"id":5,"name":"the name","pos":"the position"}
This is template html vue js
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
Edit <b>{{name}}</b>
</div>
<div class="card-body">
<form #submit="edit()" method="post" onclick="return false">
<div class="form-group">
<label for="">Name</label>
<input v-model="input.nameInput" type="text" value="?" autocomplete="off" class="form-control">
</div>
<div class="form-group">
<label for="">Position</label>
<input v-model="input.posInput" value="?" type="text" autocomplete="off" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Edit</button>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
And this is java script of template file vue js
<script>
export default {
data(){
return{
name:'',
pos:'',
input:{
nameInput:'',
posInput:''
}
}
},
methods:{
getEmploye(){
axios.get('/employes_api/'+this.$route.params.id).then(response => {
this.name = response.data.name;
this.pos = response.data.pos;
});
},
edit(){
axios.put('/employes_api/'+this.$route.params.id, {
name: this.name,
pos: this.position,
}).then(response => {
this.$route.employe;
});
}
},
mounted(){
this.getEmploye();
}
}
</script>
Thanks for your help.
As described in your question, if the data received is
{"id":5,"name":"the name","pos":"the position"}
then you getEmploye method should be :
getEmploye(){
axios.get('/employes_api/'+this.$route.params.id).then(response => {
this.name = response.name;
this.pos = response.pos;
});
On element’s value, you may use the following to display data you have received from the api:
value=“{{name}}”
That means you are getting the value from name data.
Also, to test if that works, you may assign first a dummy data/value to name.
You don't need to make two separate variables one for the inputs and the other for the display, just keep the same variable for both, it will be automatically updated on the display and in the inputs while the user is typing, that's the beauty of Vue.
So instead of
data(){
return{
name:'',
pos:'',
input:{
nameInput:'',
posInput:''
}
}
},
Just keep
data(){
return{
name:'',
pos:''
}
},
For the template inputs use :
<input v-model="name" type="text" autocomplete="off" class="form-control">
...
<input v-model="pos" type="text" autocomplete="off" class="form-control">
The overall result should look like this :
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
Edit <b>{{name}}</b>
</div>
<div class="card-body">
<form #submit="edit()" method="post">
<div class="form-group">
<label for="">Name</label>
<input v-model="name" type="text" autocomplete="off" class="form-control">
</div>
<div class="form-group">
<label for="">Position</label>
<input v-model="position" type="text" autocomplete="off" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Edit</button>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return{
name:'',
pos:''
}
},
methods:{
getEmploye(){
axios.get('/employes_api/'+this.$route.params.id).then(response => {
this.name = response.data.name;
this.pos = response.data.pos;
});
},
edit(){
axios.put('/employes_api/'+this.$route.params.id, {
name: this.name,
pos: this.pos,
}).then(response => {
this.$route.employe;
});
}
},
created(){
this.getEmploye();
}
}
Ps : Didn't test the code, if there is any error just let me know
Use :value=“name”, e.g <input :value="name"/>.

Use CKeditor instance in Vue.js

I am trying to implement CKeditor in my Laravel-backoffice which build its views with Vue.js
In this form I want to replace the "textarea" with name="ckeditor1" with a texteditor
<form method="POST" v-on="submit: onSubmitForm">
<div class="col-md-4">
<h1>Pagina: #{{ page.name }}</h1>
<h2>Pagina algemeen</h2>
<div class="form-group">
<label for="name">
Name
<span class="error" v-if="! page.name">*</span>
</label>
<input type="text" name="name" id="name" class="form-control" v-model="page.name">
</div>
<ul class="nav nav-tabs">
<li class="" v-repeat="page.translations" v-class="active: language == defaultLanguage"><a
data-toggle="tab" href="##{{ language }}">#{{ language }}</a></li>
</ul>
<div class="tab-content">
<div v-repeat="page.translations" id="#{{ language }}" class="tab-pane fade in "
v-class="active: language == defaultLanguage">
<h2>Pagina inhoud</h2>
<div class="form-group">
<label for="name">
Titel
</label>
<input type="text" name="title_#{{ language }}" id="title_#{{ language }}"
class="form-control" v-model="title">
</div>
<div class="form-group">
<label for="content">
Inhoud
</label>
<textarea name="ckeditor1" id="content_#{{ language }}"
class="form-control editor" v-model="content"></textarea>
</div>
<h2>Seo</h2>
<div class="form-group">
<label for="meta_keywords">
Meta keywords
</label>
<input type="text" name="meta_keywords_#{{ language }}"
id="meta_keywords_#{{ language }}" class="form-control"
v-model="meta_keywords">
</div>
<div class="form-group">
<label for="meta_decription">
Meta description
</label>
<textarea name="meta_description_#{{ language }}"
id="meta_description_#{{ language }}" class="form-control"
v-model="meta_description"></textarea>
</div>
<input type="hidden" name="page_id_#{{ language }}" id="page_id_#{{ language }}"
class="form-control" v-model="page_id" value="#{{ pageId }}">
</div>
</div>
<div class="form-group" v-if="! submitted">
<button type="submit" class="btn btn-default">
Opslaan
</button>
</div>
</div>
</form>
The #{{ }} fields are loaded and filled with json call and vue.js but there is no problem cause all fields are filled perfectly as needed. The problem is just the initializing of my editor.
This is where I get my data:
Vue.http.headers.common['X-CSRF-TOKEN'] = document.querySelector('#token').getAttribute('value');
var pages = new Vue({
el: '#page',
data: {
pageId: document.querySelector('#page-id').getAttribute('value'),
pageTitle: 'Pagina',
page: [],
submitted: false,
defaultLanguage: 'nl',
errors: false
},
ready: function() {
this.fetch();
},
methods: {
fetch: function() {
this.$http.get('/api/pages/' + this.pageId, function(response) {
this.page = response;
});
},
onSubmitForm: function(e) {
e.preventDefault();
this.submitted = true;
this.errors = false;
if(this.pageId == 0) {
this.$http.post('/api/pages/', this.page, function (response) {
if (response.errors.length) {
this.errors = response.errors;
this.submitted = false;
return;
}//endif
this.submitted = false;
window.location.href = '/admin/pages';
});
}
else
{
this.$http.put('/api/pages/' + this.pageId, this.page, function (response) {
if (response.errors.length) {
this.errors = response.errors;
this.submitted = false;
return;
}//endif
this.submitted = false;
window.location.href = '/admin/pages';
});
}
}
}
});
UPDATE -> SOLVED
By adding Vue.nextTick I can initialize an editor. I added a class 'editor' to every textarea I want it to be an editor and then find all id's from the textareas with class="editor".
fetch: function() {
this.$http.get('/api/pages/' + this.pageId, function(response) {
this.page = response;
Vue.nextTick(function () {
$('textarea.editor').each(function(){
CKEDITOR.replace(this.id);
});
});
});
},
By adding Vue.nextTick I can initialize an editor. I added a class 'editor' to every textarea I want it to be an editor and then find all id's from the textareas with class="editor".
fetch: function() {
this.$http.get('/api/pages/' + this.pageId, function(response) {
this.page = response;
Vue.nextTick(function () {
$('textarea.editor').each(function(){
CKEDITOR.replace(this.id);
});
});
});
}
I am also using CKeditor with laravel-vue. You just need to set and get data with CKeditor for basic thing.
This is my main.html file in which i need CKeditor.
<div class="row">
<div class="col-md-2">
<label for="body" >Mail Body :</label>
</div>
<div class="col-md-10" >
<textarea class="ckeditor" id="body" rows="5" cols="70" name="body" v-model="template.body" ></textarea>
</div>
</div>
After that i initialize my CKeditor value in app.js file
var vm = this;
axios.post('/fetchEmailTemplate', {
'template_id' : template_id
}).then(function (response) {
vm.template = response.data.emailTemplate;
CKEDITOR.instances['body'].setData(vm.template.body);
}).catch(function (error) {
console.log(error);
setNotification(error, "danger");
});
If I'm not mistaken ckeditor replaces the original textarea by a custom template. So what you see within ckeditor will not be put into your messageArea textarea automatically. That's why you don't see any changes to your model. So, for making changes you need to replace updated text before submit in app.js file like below.
this.template.body = CKEDITOR.instances['body'].getData();

Categories

Resources