How to create two datepicker using vuejs and momentjs? - vue.js

I'm using moment js to change the format of my date. I'm trying to create a start and end date to view all the transaction of the customer. I already create the first date. And I want to create another one for my end date. How can I do that? Can somebody help me with my problem? Here's my jsfiddle: https://jsfiddle.net/89vwy2od/1/
var vm = new Vue({
el: '#app',
data: {
date : "",
date2 : ""
},
methods : {
showDate1 : function() {
alert(this.date);
},
showDate2 : function() {
alert(this.date2);
}
},
mounted: function() {
var args = {
format: 'MM-DD-YYYY'
};
this.$nextTick(function() {
$('.datepicker').datetimepicker(args)
});
this.$nextTick(function() {
$('.time-picker').datetimepicker({
format: 'LT'
})
});
}
})
$('.datepicker').on('dp.change', function(event) {
if (event.date) {
var date = event.date.format('YYYY-MM-DD');
console.log(date);
Vue.set(vm, 'date', date);
}
});

One possible solution (not optimal) is using 2 different class or different id
<div class="col-md-2">
<input type="text" v-model="date" class="datepicker form-control form-control-sm" placeholder="Enter Date 1">{{date}}
<input type="text" v-model="date2" class="datepicker2 form-control form-control-sm" placeholder="Enter Date 1">{{date2}}
</div>
then you need to init 2 twices:
this.$nextTick(function() {
$('.datepicker').datetimepicker(args)
$('.datepicker2').datetimepicker(args)
});
and
$('.datepicker').on('dp.change', function(event) {
if (event.date) {
var date = event.date.format('YYYY-MM-DD');
console.log(date);
Vue.set(vm, 'date', date);
}
});
$('.datepicker2').on('dp.change', function(event) {
if (event.date) {
var date = event.date.format('YYYY-MM-DD');
console.log(date);
Vue.set(vm, 'date2', date);
}
});
You can check demo here
A better solution is creating a custom component.

Related

Get name model in vue js with help id input or name

Can i get model name if i now id input?
For examle
<input v-model="data.name" id="name_db">
I have in db value for data.name
Before vue i did this:
valuesFromDb.forEach(data=>{
if(data.fromdb==name_db)
$("#name_db").val(data.fromdb)
}
...
But it can't work with vueJS
I know i can do this:
data.name = data.fromdb
But i have many data in db and before vue i put data with help forloop.
Model and id have different names ​​and it will take a long time to manually iterate through all the data
Now i want get model name and put value to it
Somethinks like this:
var modelName = $("#name_db").getModelNameVue();
modelName=data.fromdb
If i do this, in input value change but in data dont
data(){
return{
mainPdf:{
left: 5,
bottom:5,
top:5,
right:5
}
}
}
<input v-model="mainPdf.left" id="left_margin">
<input v-model="mainPdf.bottom" id="bot_margin">
<input v-model="mainPdf.isMargin" id="right_margin">
<input v-model="mainPdf.isMargin" id="up_margin">
getFromdb(){
api.getFromdb(e=>{ // string=e
var string = "left_margin=0&bot_margin=1&right_margin=2&up_margin=3"
var rPlus = /\+/g;
$.each( string.split( "&" ), function( index, field ) {
$.each( string.split( "&" ), function( index, field ) {
var current = field.split( "=" );
if( current[ 1 ] && current[ 0 ]) {
var name = decodeURIComponent(current[0].replace(rPlus, "%20"));
var value = decodeURIComponent(current[1].replace(rPlus, "%20"));
$("#"+ name).val(value);
}
});
})
})
I can't dynamic-binding because i can't change name of properties in mainPdf, because i have entity with same fields(left,bottom,top,right) in my backend
==========i found solution
i used dispatchEvent
$("#" + NAME).prop("checked", true);
$("#"+ NAME")[0].dispatchEvent(new Event('change')); //or input
Using Vue.js and dynamic programming techniques, it's a piece of cake.
Vue.component('dynamic-binding', {
template: `
<div style="display: flex;">
<input
v-for="field in Object.keys(mainPdf)" :key="field"
v-model="mainPdf[field]"
>
</div>
`,
data() {
return {
mainPdf: {},
};
},
methods: {
fromDb(val = 'left_margin=0&bot_margin=1&right_margin=2&up_margin=3') {
const db = new URLSearchParams(val);
this.mainPdf = Object.fromEntries(db);
},
},
mounted() {
this.fromDb();
},
});
new Vue({ el: '#app' });
<div id="app">
<dynamic-binding></dynamic-binding>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

VueJS change date format

Now VueJS display me date in format 2021-02-24 00:12:42, but how i can change display only 00:12? Without year, month, date and seconds?
In vue i use:
<div class="jhistory" v-for="game in histories" :key="game.game_id">
{{ game.date }}
</div>
<script>
export default {
data() {
return {
histories: {},
}
},
mounted() {
this.$root.isLoading = true
this.getHistory();
},
methods: {
getHistory() {
this.$root.axios.post('/jackpot/history').then(res => {
this.histories = res.data;
this.$root.isLoading = false;
});
}
}
}
</script>
One way to do this is to create a component method that converts the string into a Date object, uses Date.prototype.toTimeString(), and takes only the first 5 characters, which contains only the hh:mm portion. Another simpler way is to just extract the substring with String.prototype.substr(), assuming the format never changes.
export default {
methods: {
toTime(date) {
// Option 1
return new Date(date).toTimeString().substr(0,5)
// Option 2
return date.substr(11,5)
}
}
}
Then use the method in your template:
{{ toTime(game.date) }}
new Vue({
el: '#app',
data: () => ({
game: {
date: '2021-02-24 00:12:42'
}
}),
methods: {
toTime(date) {
return new Date(date).toTimeString().substr(0,5)
// OR
// return date.substr(11,5)
}
}
})
<script src="https://unpkg.com/vue#2.6.12"></script>
<div id="app">
<p>{{ toTime(game.date) }}</p>
</div>

Vue Component does not render changes of object (despite $set being used)

I am trying to build a Vue component that displays the hour and minute of a Date and emits a changed version when a + or - button is pressed.
Screenshot: https://i.imgur.com/hPUdrca.png
(not enough reputation to post image)
Using the Vue.js Devtools (in Google Chrome) I observed that:
The change event fires and contains a correct date
The date prop was updated correctly
It just does not rerender the date.
https://jsfiddle.net/JoshuaKo/6c73b2gt/2
<body>
<div id="app">
<time-input :date="meeting.startDate"
#change="$set(meeting, 'startDate', $event)"
></time-input>
<p>
{{meeting.startDate.toLocaleString()}}
</p>
</div>
</body>
Vue.component('time-input', {
props: {
date: Date,
minuteSteps: {
type: Number,
default: 1
}
},
methods: {
increaseTime: function() {
if (!this.date) return
const newDate = this.date
newDate.setMinutes(this.date.getMinutes() + this.minuteSteps)
this.$emit('change', newDate)
},
decreaseTime: function() {
if (!this.date) return
const newDate = this.date
newDate.setMinutes(this.date.getMinutes() - this.minuteSteps)
this.$emit('change', newDate)
},
time: function() {
if (!this.date) return '??:??'
const h = this.date.getHours().toString()
const m = this.date.getMinutes().toString()
return _.padStart(h, 2, '0') + ':' + _.padStart(m, 2, '0')
}
},
computed: {
},
template: `
<div class="time">
<button :disabled="!date" class="control" #click="decreaseTime">-</button>
<span>{{time()}}</span>
<button :disabled="!date" class="control" #click="increaseTime">+</button>
</div>
`.trim()
})
const app = new Vue({
el: '#app',
data: {
meeting: {
name: 'test meeting',
startDate: new Date(),
endDate: null
}
}
})
The object in meeting.startDate is always the same, so it doesn't trigger anything.
You should create a new Date object each time, so change the lines:
const newDate = this.date
to:
const newDate = new Date(this.date.getTime())
Also, the $set (alias of Vue.set) is intended to add properties that must be reactive. As no propperty is added (just modified), you don't need it here.

vue: changes not triggered #input

Below is vue script - the concern method is called notLegalToShip which checks when age < 3.
export default {
template,
props: ['child', 'l'],
created() {
this.name = this.child.name.slice();
this.date_of_birth = this.child.date_of_birth.slice();
},
data() {
return {
edit: false,
today: moment().format('DD/MM/YYYY'),
childUnder3: false
};
},
computed: {
age() {
var today = new Date();
var birthDate = new Date(this.child.date_of_birth);
var age = today.getFullYear() - birthDate.getFullYear();
var m = today.getMonth() - birthDate.getMonth();
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
return age;
}
},
methods: Object.assign(
mapActions(['updateChild']),
{
notLegalToShip() {
if(this.age < 3){
this.childUnder3 = true;
}
this.childUnder3 = false;
},
showForm() {
this.edit = true;
},
hideForm() {
this.edit = false;
},
submitForm() {
this.hideForm();
this.updateChild({
child: this.child,
name: this.name,
dateOfBirth: this.date_of_birth,
childUnder3 : this.childUnder3
});
}
}
)
}
Here's the snippet of my template. The input as below.
I want the notLegalToShip method to be triggered when I click arrow changing the year. A warning will appear when childUnder3 is "true". I've tried #change, #input on my input but my method is not triggered at all:
<div>
{{childUnder3}}
{{age}}
<div class="callout danger" v-if="childUnder3">
<h2>Sorry</h2>
<p>Child is under 3!</p>
</div>
<div v-if="!edit">
<a #click.prevent="showForm()" href="#" class="more-link edit-details edit-child">
<i class="fa fa-pencil" aria-hidden="true"></i>{{ l.child.edit_details }}
</a>
</div>
<form v-show="edit" #submit.prevent="submitForm()">
<div class="input-wrap">
<label for="account__child__date-of-birth__date">{{ l.child.date_of_birth }}</label>
<input id="account__child__date-of-birth__date" type="date" name="date_of_birth" v-on:input="notLegalToShip" v-model="date_of_birth" v-validate="'required'">
<p class="error-message" v-show="errors.has('date_of_birth')">{{ l.child.date_of_birth_invalid }}</p>
</div>
</form>
</div>
Any help checking my code above would be appreciated!
You have a couple of problems...
Initialise the name and date_of_birth properties in the data() initialiser so Vue can react to them. You can even initialise them from your child prop there...
data() {
return {
edit: false,
today: moment().format('DD/MM/YYYY'),
name: this.child.name // no need to use slice, strings are immutable
date_of_birth: this.child.date_of_birth
}
}
Use this.date_of_birth inside your age computed property instead of this.child.date_of_birth. This way, it will react to changes made via your v-model="date_of_birth" input element.
Make childUnder3 a computed property, it will be easier that way
childUnder3() {
return this.age < 3
}
Alternately, ditch this and just use v-if="age < 3"
With the above, you no longer need any #input or #change event listeners.

Performing action when clicking off an element

The below code allows me to have a click-to-edit header tag within my application.
I'm looking for the best way to handle exiting editing mode when any other action is performed on the page... either a click or a drag-n-drop.
<validator name="teamSetValidation">
<input id='teamSetName' v-if="isEditingName" type="text" v-model="teamSet.name" class="semi-bold p-t-10 p-b-10 m-l-15 edit-header" v-on:keyup.enter="saveTeamSetName()" v-on:keyup.esc="doneEditing()" v-validate:name.required.maxlength="teamSetRules" :isEditingName="true"/>
<h3 v-else class="semi-bold p-t-10 p-b-10 m-l-15" v-on:click="editing()" :isEditingName="false">{{ teamSet.name }} <span class="fa fa-edit"></span></h3>
<div class="text-small">
<span class="text-danger" v-if="$teamSetValidation.teamSet.name.required">A name is required.</span>
<span class="text-danger" v-if="$teamSetValidation.teamSet.name.maxlength">The name you provided is too long.</span>
</div>
<div class="b-grey b-b m-t-10"></div>
</validator>
Javascript:
var vm = new Vue({
el: '#page',
data: {
// When true, user can edit the teamSet name
isEditingName: false,
teamSet: teamSet,
teamSetRules: {
required: false,
maxlength: 64
}
},
methods: {
editTeamSetName: function () {
alert('editing');
},
saveTeamSetName: function () {
if(this.$teamSetValidation.valid) {
this.doneEditing();
var teamSet = this.teamSet,
self = this;
$.ajax({
url: '/team/'+teamSet.id,
type: 'PATCH',
data: {
'name': teamSet.name
},
error: function(res) {
Messenger().post({
message: 'Unable to save changes',
type: 'error',
hideAfter: 3
});
self.editing();
}
});
}
},
editing: function () {
this.isEditingName = true;
Vue.nextTick(function () {
$('#teamSetName').focus();
});
},
doneEditing: function () {
this.isEditingName = false;
}
}
});
Attaching a blur event to the input should do the trick:
<input id='teamSetName' v-if="isEditingName"
type="text" v-model="teamSet.name"
class="semi-bold p-t-10 p-b-10 m-l-15 edit-header"
v-on:keyup.enter="saveTeamSetName()"
v-on:keyup.esc="doneEditing()"
v-validate:name.required.maxlength="teamSetRules"
:isEditingName="true" v-on:blur="doneEditing()"
/>