Unable to bind v-model with vue-date-picker - javascript

I have used vue-date-picker and v-model for two way data binding. Initially I have set value to date(i.e. startDate in this case) and in console I am printing that passed value(i.e. startDate). At first, that passed value to startDate (i.e. 2019-09-17 is printed) but when I chose new Date, startDate value didn't get updated rather value remained same as it was when it was initially passed.
<div class="col-md-3">
<label for="startDate" class>Start Date</label>
<datepicker v-model="startDate" :readonly="true" format="YYYY-MM-DD" name="startDate">
</datepicker>
</div>
<p>Start Date: {{startDate}}</p>
<div class="col-md-2">
<div class="md-form mb-0">
<button type="button" class="btn btn-primary" #click="showDateValues">Apply</button>
</div>
</div>
import datepicker from "vue-date-picker";
<script>
import datepicker from "vue-date-picker";
export default {
name: "Example",
components: {
datepicker
},
data() {
return {
startDate: "2019-09-17"
};
},
methods:{
showDateValues(){
console.log("Start Date: "+this.startDate)
}
}
};
</script>

try this:
data() {
return {
startDate: new Date("2019-09-17")
};
},

var elm = new Vue({
el: '.app8',
mounted () {
var vm = this
$('#datedate').datepicker ({
onSelect: function(dateText) {
vm.date = dateText
}
})
});
<div class="row mt-5">
<div class="col">
<div class="app8">
<input v-model="date" name="date" class="input" type="date" id="datedate">
</div>
</div>
</div>
Hope this will help

Related

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.

How to push new row which is blank

The user has the ability to add a row of fields if he would like to request multiple dates. However I am having an issue: when the row is added it is pre-filled with the values from the initial row. Additionally, any changes made are applied to all the fields so in the end all the fields have the same values. How can I fix this?
Here is my controller file:
import { Component, OnInit, ViewChild } from '#angular/core';
import { SelectItem } from 'primeng/api';
import { Router } from '#angular/router';
import { NgForm } from '#angular/forms';
let date = new Date();
interface Supervisor {
name: string;
code: string;
}
interface LeaveCode {
name: string;
code: string;
}
#Component({
selector: 'app-fill-request',
templateUrl: './fill-request.component.html',
styleUrls: ['./fill-request.component.css']
})
export class FillRequestComponent implements OnInit {
#ViewChild('testForm') public test1234Form: NgForm;
ngOnInit() {
let today = new Date();
let month = today.getMonth();
let year = today.getFullYear();
let nextMonth = (month === 11) ? 0 : month + 4;
this.minDate = new Date(Date.now() - 12096e5);
this.maxDate = new Date(new Date().setFullYear(new Date().getFullYear() + 1));
this.maxDate.setMonth(nextMonth);
}
// dates: SelectItem[];
supervisor2: Supervisor[];
selectedSupervisor2: Supervisor;
leaveCodes2: LeaveCode[];
selectedLeaveCode2: LeaveCode;
// clicks: number = 0;
dates = [1] //Initiazling date array
minDate: Date;
maxDate: Date;
fromDate: Date;
toDate: Date;
fromDateMin: Date;
toDateMin: Date;
fromDateMax: Date;
toDateMax: Date;
fromTime: Date;
toTime: Date;
// Method to add dates on button click for up to 4 dates
onAddClicked() {
if (this.dates.length < 8)
this.dates.push(1);
}
//Method to remove dates on button click. Will always have one date field displayed
onRemoveClicked() {
if (this.dates.length > 1) this.dates.pop();
}
submit(): void {
this.router.navigate(["submitted"]);
}
// Array of Supervisors
constructor(private router: Router, ) {
this.supervisor2 = [
{ name: 'Joe Rogan', code: 'JR' },
{ name: 'Alex Jones', code: 'AJ' },
{ name: 'Sam Smith', code: 'SS' },
];
//Array of Leave Codes
this.leaveCodes2 = [
{ name: 'Personal Leave', code: 'PL' },
{ name: 'Sick Leave', code: 'SL' },
{ name: 'Vacation Leave', code: 'VL' },
];
}
}
Here is the relevant HTML code:
<div class="Dates" *ngFor="let dateline of dates">
<div class="ui-g form-group">
<div class="ui-g-12 ui-md-1" id="test">
<button pButton type="button" id="deleteButton" icon="pi pi-times" class="ui-button-danger" (click)="onRemoveClicked()"></button>
</div>
<div class="ui-g-12 ui-md-2" id="test">
<!-- Leave code field -->
<p-dropdown [options]="leaveCodes2" [(ngModel)]="selectedleaveCodes2" name="selectedleaveCodes2" placeholder="Leave Code*" optionLabel="name" required></p-dropdown>
</div>
<div class="ui-g-12 ui-md-2" id="test">
<!-- Start date & time fields -->
<p-calendar [showIcon]="true" [(ngModel)]="fromDate" name="fromDate" [minDate]="minDate" [readonlyInput]="true" placeholder="From Date*" id="setter" required>
</p-calendar>
</div>
<div class="ui-g-12 ui-md-2" id="test">
<input type="text" [(ngModel)]="fromTime" name="fromTime" placeholder="Input Time*" style="height: 2.186em" size="7" maxlength="8" pInputText required>
<!-- <p-inputMask mask="99:99 aa" placeholder="Select Time"></p-inputMask> -->
</div>
<div class="ui-g-12 ui-md-2" id="test">
<!-- End date & time fields -->
<p-calendar [showIcon]="true" [(ngModel)]="toDate" name="toDate" [minDate]="minDate" [maxDate]="maxDate" [readonlyInput]="true" placeholder="To Date*" id="setter" required></p-calendar>
</div>
<div class="ui-g-12 ui-md-2" id="test">
<input type="text" [(ngModel)]="toTime" name="toTime" placeholder="Input Time*" style="height: 2.186em" size="7" maxlength="8" pInputText required>
</div>
</div>
</div>
<button pButton type="button" id="addButton" icon="pi pi-plus" class="ui-button-success" (click)="onAddClicked()"></button>
<br><br><br>
<!-- Action buttons to add or remove dates. Submit button available -->
<div class=modButtons>
<div class="ui-g-12">
<!-- <button pButton type="button" label="Add Dates +" class="ui-button-success" (click)="onAddClicked()"></button> -->
<!--<button pButton type="submit" label="Submit" [disabled]="testForm.invalid" (click)="submit()"
class="ui-button-success" id="righter"></button>-->
<button pButton type="submit"  class="ui-button-primary"  style="white-space:nowrap;margin:10px;"   label="Submit"   [disabled]="testForm.invalid||!(testForm.valid&&testForm.dirty)"  (click)="submit()"></button>
</div>
You are binding on single properties to all the elements like
<p-calendar [showIcon]="true" [(ngModel)]="fromDate" name="fromDate" [minDate]="minDate" [readonlyInput]="true" placeholder="From Date*" id="setter" required>
</p-calendar>
Here you are binding fromDate and which will be the same for all elements added by the button.
I suggest you use an object array like dates: {date:string, fromDate: string}[]; an populate your DOM.
Then in onAddedClicked()
onAddClicked() {
if (this.dates.length < 8)
this.dates.push({date:"", fromDate:""});
}

Vue.js: A value in a v-for loop is not staying with the correct array items

I am trying to create a simple application to request a car key for a service department. Obviously the code could be written better, but this is my third day with Vue.js. The time function that is called in the first p tag in the code updates every minutes to keep count of an elapsed time. The problem I am having is when I request a new key the time function doesn't follow the array items as intended. For example, if there are no other requests the first request I submit works perfectly. However, when I submit a new request the elapsed time from my first request goes to my second request. I am sure it could have something to do with the glued together code, but I have tried everything I can think of. Any help would be appreciated.
<template>
<div class="row">
<div class="card col-md-6" v-for="(key, index) in keys" :key="index">
<div class="card-body">
<h5 class="card-title">Service Tag: {{ key.service_tag }}</h5>
<p class="card-text"> {{time}} {{key.reqTimestamp}}min</p>
<p class="invisible">{{ start(key.reqTimestamp) }}</p>
<p class="card-text">Associates Name: {{key.requestor_name}}</p>
<p class="card-text">Model: {{key.model}}</p>
<p class="card-text">Color: {{key.color}}</p>
<p class="card-text">Year: {{key.year}}</p>
<p class="card-text">Comments: {{key.comments}}</p>
<p class="card-text">Valet: {{key.valet}}</p>
<input class="form-control" v-model="key.valet" placeholder="Name of the person getting the car...">
<button
#click="claimedKey(key.id, key.valet)"
type="submit"
class="btn btn-primary"
>Claim</button>
<button v-if="key.valet !== 'Unclaimed'"
#click="unclaimedKey(key.id, key.valet)"
type="submit"
class="btn btn-primary"
>Unclaim</button>
<button class="btn btn-success" #click="complete(key.id)">Complete</button>
</div>
</div>
<!-- END OF CARD -->
<!-- START OF FORM -->
<div class="row justify-content-md-center request">
<div class="col-md-auto">
<h1 class="display-4">Operation Tiger Teeth</h1>
<form class="form-inline" #submit="newKey(service_tag, requestor_name, comments, model, year, color, valet, reqTimestamp)">
<div class="form-group col-md-6">
<label for="service_tag">Service Tag: </label>
<input class="form-control form-control-lg" v-model="service_tag" placeholder="ex: TB1234">
</div>
<div class="form-group col-md-6">
<label for="service_tag">Associates Name: </label>
<!-- <input class="form-control form-control-lg" v-model="requestor_name" placeholder="Your name goes here..."> -->
<div class="form-group">
<label for="exampleFormControlSelect1">Example select</label>
<select v-model="requestor_name" class="form-control" id="requestor_name">
<option>James Shiflett</option>
<option>Austin Hughes</option>
</select>
</div>
</div>
<div class="form-group col-md-6">
<label for="service_tag">Model: </label>
<input class="form-control form-control-lg" v-model="model" placeholder="What is the model of the vehicle?">
</div>
<div class="form-group col-md-6">
<label for="service_tag">Color: </label>
<input class="form-control form-control-lg" v-model="color" placeholder="What is the color of the vehicle?">
</div>
<div class="form-group col-md-6">
<label for="service_tag">Year: </label>
<input class="form-control form-control-lg" v-model="year" placeholder="What year is the car?">
</div>
<div class="form-group col-md-6">
<label for="service_tag">Comments: </label>
<input class="form-control form-control-lg" v-model="comments" placeholder="Place any additional comments here...">
</div>
<div class="form-group col-md-6 invisible">
<label for="service_tag">Valet: </label>
<input v-model="valet">
</div>
<div class="form-group col-md-6 invisible">
<label for="service_tag">Timestamp: </label>
<input v-model="reqTimestamp">
</div>
<div class="col-md-12">
<button class="btn btn-outline-primary" type="submit">Request A Key</button>
</div>
</form>
</div>
</div>
</div>
</template>
<script>
import { db } from "../main";
import { setInterval } from 'timers';
export default {
name: "HelloWorld",
data() {
return {
keys: [],
reqTimestamp: this.newDate(),
service_tag: "",
requestor_name: "",
comments: "",
color: "",
model: "",
year: "",
inputValet: true,
valet: "Unclaimed",
state: "started",
startTime: '',
currentTime: Date.now(),
interval: null,
};
},
firestore() {
return {
keys: db.collection("keyRequests").where("completion", "==", "Incomplete")
};
},
methods: {
newKey(service_tag, requestor_name, comments, model, year, color, valet, reqTimestamp, completion) {
// <-- and here
db.collection("keyRequests").add({
service_tag,
requestor_name,
comments,
color,
model,
year,
valet,
reqTimestamp,
completion: "Incomplete",
});
this.service_tag = "";
this.requestor_name = "";
this.comments = "";
this.color = "";
this.model = "";
this.year = "";
this.reqTimestamp = this.newDate()
},
complete(id) {
db.collection("keyRequests").doc(id).update({
completion: "Complete"
})
},
// deleteKey(id) {
// db.collection("keyRequests")
// .doc(id)
// .delete();
claimedKey(id, valet) {
console.log(id);
this.inputValet = false
db.collection("keyRequests").doc(id).update({
valet: valet,
claimTimestamp: new Date()
})
},
moment: function () {
return moment();
},
newDate () {
var today = new Date()
return today
},
updateCurrentTime: function() {
if (this.$data.state == "started") {
this.currentTime = Date.now();
}
},
start(timestamp) {
return this.startTime = timestamp.seconds * 1000
}
},
mounted: function () {
this.interval = setInterval(this.updateCurrentTime, 1000);
},
destroyed: function() {
clearInterval(this.interval)
},
computed: {
time: function() {
return Math.floor((this.currentTime - this.startTime) /60000);
}
}
}
</script>
Ideally I am looking for the time lapse to follow each request.
So the problem lines in the template are:
<p class="card-text"> {{time}} {{key.reqTimestamp}}min</p>
<p class="invisible">{{ start(key.reqTimestamp) }}</p>
The call to start has side-effects, which is a major no-no for rendering a component. In this case it changes the value of startTime, which in turn causes time to change. I'm a little surprised this isn't triggering the infinite rendering recursion warning...
Instead we should just use the relevant data for the current iteration item, which you've called key. I'd introduce a method that calculates the elapsed time given a key:
methods: {
elapsedTime (key) {
const timestamp = key.reqTimestamp;
const startTime = timestamp.seconds * 1000;
return Math.floor((this.currentTime - startTime) / 60000);
}
}
You'll notice this combines aspects of the functions start and time. Importantly it doesn't modify anything on this.
Then you can call it from within your template:
<p class="card-text"> {{elapsedTime(key)}} {{key.reqTimestamp}}min</p>

$ref from child component is always undefined in parent(vuejs)

For some reason when trying to grab the ref for the child component I am getting undefined even when only asking for it later then lifecycle events of mounted and created.
Here is the child component:
<template>
<div>
<div class="form-row">
<label>Season</label>
<select placeholder="Season" v-model="semester.Season">
<option v-for="s in seasons" :value="s.key">{{s.key}}</option>
</select>
</div>
<div class="form-row">
<div class="form-columns start-year-group">
<div class="form-group" style="width:50%">
<label>Start Month</label>
<select v-model="StartMonth" #change="calculateStartDate('Month', $event.currentTarget.value)" placeholder="Start Month">
<option v-for="m in months" :value="m.value">{{m.key}}</option>
</select>
</div>
<div class="form-group" style="width:50%">
<label>Start Year</label>
<select v-model="StartYear" #change="calculateStartDate('Year', $event.currentTarget.value)" placeholder="Start Year">
<option v-for="y in years" :value="y.key">{{y.key}}</option>
</select>
</div>
</div>
</div>
<div class="form-row">
<div class="form-columns end-year-group">
<div class="form-group" style="width:50%">
<label>End Month</label>
<select v-model="EndMonth" #change="calculateEndDate('Month', $event.currentTarget.value)" placeholder="End Month">
<option v-for="m in months" :value="m.value">{{m.key}}</option>
</select>
</div>
<div class="form-group" style="width:50%">
<label>End Year</label>
<select v-model="EndYear" #change="calculateEndDate('Year', $event.currentTarget.value)" placeholder="End Year">
<option v-for="y in years" :value="y.key">{{y.key}}</option>
</select>
</div>
</div>
</div>
</div>
</template>
<script>
import { eMonth, eYear, eSeason } from '#/shared/lib/enums';
export default {
name: 'SemesterForm',
props: ['schoolID', 'sData', 'sessionSchool'],
data () {
var cYear = (new Date()).getFullYear();
return {
semester: {
Season: 'Spring',
StartDate: null,
EndDate: null,
SchoolID: null,
Interactions: []
},
StartMonth: 0,
StartYear: cYear,
EndMonth: 5,
EndYear: cYear
};
},
mounted () {
this.semester.SchoolID = this.schoolID || this.sessionSchool;
this.semester.StartDate = this.calculateDate(this.StartYear, this.StartMonth);
this.semester.EndDate = this.calculateDate(this.EndYear, this.EndMonth);
if (this.sData) {
Object.assign(this.semester, this.sData);
this.StartMonth = this.sData.StartMonth;
this.StartYear = this.sData.StartYear;
this.EndMonth = this.sData.EndMonth;
this.EndYear = this.sData.EndYear;
}
},
computed: {
seasons () {
return eSeason.enums;
},
months () {
return eMonth.enums;
},
years () {
return eYear.enums;
}
},
methods: {
calculateStartDate (yearOrMonth, value) {
var date;
if (yearOrMonth === 'Year') {
date = this.calculateDate(value, this.StartMonth);
}
else if (yearOrMonth === 'Month') {
date = this.calculateDate(this.StartYear, value);
}
this.semester.StartDate = date;
},
calculateEndDate (yearOrMonth, value) {
var date;
if (yearOrMonth === 'Year') {
date = this.calculateDate(value, this.EndMonth);
}
else if (yearOrMonth === 'Month') {
date = this.calculateDate(this.EndYear, value);
}
this.semester.EndDate = date;
},
calculateDate (year, month) {
return new Date(year, month, 1);
}
}
};
</script>
<style scoped>
.form-group{
flex: 1;
}
</style>
Here is the parent component, this component has very little beyond the $ref to the child and then a cancel/save option:
<template>
<div>
Add Semester
<Modal :show="show" title="Add New Semester" name="Semester" width="500px" height="360px" #close="toggleSemesterModal">
<template>
<div>
<semester-form ref="form" :schoolID="schoolID"></semester-form>
</div>
<footer>
<a #click.prevent="save" class="btn btn pull-right" style="margin-left: 10px;">Save</a>
<button href="#" class="btn btn pull-right" style="margin-left: 10px;" #click="toggleSemesterModal">Cancel</button>
</footer>
</template>
</Modal>
</div>
</template>
<script>
import Modal from '#/shared/components/ui/modal';
import SemesterForm from './SemesterForm';
export default {
name: 'NewSemester',
data: () => ({
semester: {},
show: false
}),
props: ['schoolID'],
components: { Modal, SemesterForm },
methods: {
toggleSemesterModal () {
this.show = !this.show
},
save () {
console.log(this.$refs); //undefined
const semester = this.$refs.form.semester;
console.log('need to save this data', {...semester});
this.show = !this.show
}
}
};
</script>
<style scoped>
.
.
.
</style>

how to get pre filled data in input type in vue js

i have chuck of code in vue js.. I am not able to get value from input
here is my code
HTML Codes:
<div id = "app">
<div class="form-group">
<input type="text" class="form-control" name = "name" value = "lorem" v-model = "name"/>
</div>
<button class="btn btn-primary btn-block" v-on:click="sendData()">SIGN UP</button>
</div>
Vue js codes:
<script>
var app = new Vue({
el: "#app",
data() {
errors :{}
return {
input: {
name: "",
},
}
},
methods: {
sendData() {
alert(this.name);
}
}
})
Thanks
As the declare for the data properties, uses v-model="input.name", then alert(this.input.name).
If you'd like to assign default value for the input, decalre the data property like {input:{name: 'lorem'}}.
var app = new Vue({
el: "#app",
data() {
errors: {}
return {
input: {
name: "", // or pre-fill with other default value like `lorem`
},
}
},
methods: {
sendData() {
alert(this.input.name);
}
}
})
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<div class="form-group">
<input type="text" class="form-control" name="name" value="lorem" v-model="input.name" />
</div>
<button class="btn btn-primary btn-block" v-on:click="sendData()">SIGN UP</button>
</div>
Use v-model only, without value attribute:
<div id = "app">
<div class="form-group">
<input
type="text"
class="form-control"
name="name"
v-model="name"
/>
</div>
<button
class="btn btn-primary btn-block"
#click="sendData"
>
SIGN UP
</button>
</div>
<script>
var app = new Vue({
el: "#app",
data () {
return {
name: 'lorem'
}
},
methods: {
sendData () {
alert(this.name)
}
}
})
</script>

Categories