How to select three days using datepicker in vue - vue.js

Im using VCalendar - datepicker and I want to highlight days which are in my array: ['2022-02-01', '2022-02-08', '2022-02-15'], I cant find this in documentation, there is only single date or range of dates, but not alone dates like in my array, which are all tuesdays for example.

Actually VCalendar has documentation to achieve multiple date selection
https://vcalendar.io/examples/datepickers.html#multiple-dates
new Vue({
el: "#app",
data: () => ({
dates: ['2022-02-01', '2022-02-08', '2022-02-15']
}),
computed: {
attributes() {
return this.dates.map(date => ({
highlight: true,
dates: date,
}));
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/v-calendar#2.4.0/lib/v-calendar.umd.min.js"></script>
<div id="app">
<v-calendar :attributes="attributes" />
</div>

Related

VueJS - counter doesn't increase when I click the button

I'm learning VueJS with Maximilian Schwarzmüller in his VueJS course on Udemy and whenever I run his example on my local machine, it doesn't increase my counter variable.
<div id="app">
<button :click="increase">Click me</button>
<p>{{ counter }}</p>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
increase() {
return this.counter++
}
}
})
</script>
Any idea what's wrong with the code?
Thanks a lot.
Data needs to be a function:
<script>
new Vue({
el: '#app',
data() {
return {
counter: 0
}
},
...
})
</script>
You have to use the # symbol for events, instead of : which is used for binding props.
<button #click="increase">Click me</button>
try this:
data: () => ({
counter: 0,
})
Your script will execute before your document is ready therefore Vue will not find your element to mount to.
Also as others already mentioned - your data property should be a function to make each instance with unique data object.
document.addEventListener('DOMContentLoaded', mountVue);
function mountVue() {
new Vue({
el: '#app',
data() {
return {
counter: 0
};
},
methods: {
increase() {
return this.counter++;
}
}
});
}
The problem was actually this:
<button :click="increase">Click me</button>
I was using the wrong short-hand syntax. I had to use the # sign (for events) instead.
<button #click="increase">Click me</button>
I was looking at this example here on CodePen and I noticed that their data object is not a function. Must the data object be a function? Are their benefits that I don't know about?
I'm very new to Vue right now and I'm learning from Max's course on Udemy. Thanks a lot.

How to add a listener to a vue-multiselect after the page has loaded?

I need to add a listener to a vue-multiselect, like this (but this does not work):
$('.multiselect').change(console.log("multiselect changed"));
It must be added in the updated hook.
I've tried a lot of things, but because of the nature of vue-multiselect, conventional jQuery doesn't work ie, you can't listen for a change on the multiselect__input because its value doesn't actually change.
There's a .multiselect__single element that is added\removed depending on the state, but I'd rather not listen\test for html changes.
The vue-multiselect events don't include change, but you're probably looking for input (emitted after the value changes) or searchChanged (emitted after the search query changes).
The idiomatic way to listen to an event is to use this syntax: #EVENTNAME="METHOD". Example:
<multiselect #input="onSelection">
new Vue({
el: '#app',
components: {
Multiselect: window.VueMultiselect.default
},
data() {
return {
value: '',
options: ['list', 'of', 'options']
};
},
methods: {
onSelection(newValue) {
console.log({newValue})
}
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<script src="https://unpkg.com/vue-multiselect#2.1.0"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect#2.1.0/dist/vue-multiselect.min.css">
<div id="app">
<multiselect :options="options" v-model="value" #input="onSelection"></multiselect>
<div>value: {{value}}</div>
</div>

How do I use <input type="date"> and then Date.prototype.getFullYear() in VueJS?

I simply want to ask the user to input a date and then take actions based on the day/month/year. I don't want to install more dependencies either.
I have:
<input type="date" v-model="dateOfBirth" />
and:
const vm = new Vue({
el: '#app',
data() {
return {
dateOfBirth: null,
};
},
...
When I make a selection I get:
typeof vm.dateOfBirth === object
and the result looks like:
2018-05-11
But how can I now get the day/month/year, where should the .getFullYear() go? It is not working how I expected, I have tried everything online I could find, please help!
The value of a date input is a string, so in order to call getFullYear you need to convert it into a date.
In Vue, you might do that with a computed property. Here is an example.
console.clear()
new Vue({
el: "#app",
data:{
dateOfBirth: new Date()
},
computed:{
year(){
return new Date(this.dateOfBirth).getFullYear()
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="app">
<input type="date" v-model="dateOfBirth">
<hr>
Year: {{year}}
</div>
This code doesn't handle all the edge cases, but should give you the idea.

Possible to use VueJS SFC components with template in rendered html?

I have experience with both single page apps and multi-page apps (classic websites). In the past I have used AngularJS 1.x on each page, it has been useful because all components can live in separate files and be executed as they appear on each page.
I'm now looking at VueJS to replace AngularJS, but not finding it easy to understand how to architect my multi-page app.
As expected I want to use some components on all the pages, and some on only a few pages.
Example:
I came across SFC - single file components using ES2015 which looked promising, but my backend is Java which outputs my html from JSPs. It appears that .vue files are precompiled by webpack, but if my templates are only ready when the page is rendered that won't be possible will it?
How would one architect a solution so that each component is modular but utilize either an x-template in the html and somehow attach it to a .vue SFC, or is there some other way to have components in separate files which can be imported using ES2015?
I hope this is making sense, can't seem to figure it out.
One possible approach would be to set the template for the Vue Component inline. So this would be to have a Component File like
Home.vue:
<script>
export default {
data() {
return {
msg: 'text',
}
}
}
</script>
import it as a global component for Vue (using require, import, etc.)
Vue.component('home', require('./components/Home.vue'));
and in your server generated HTML you'd have to use an inline template, which will have all the flexibility from normal templates
home.jsp:
<home inline-template>
<h2 v-text="msg"></h2>
</home>
Update
I've added an example on GitHub here
If I understand your question, you have want to make single file components out of HTML.
If this is the case, you should make use of the render() function and regular components.
The render function decides what to use as a template for a component:
<!DOCTYPE html>
<html>
<head>
<title>Vue</title>
</head>
<body>
<div id="app">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
render (createElement) {
return createElement({
template: '<div>Hello World</div>'
})
},
})
</script>
</body>
</html>
will render Hello World to the screen.
Now, let's see how this function is reactive:
<script type="text/javascript">
new Vue({
el: '#app',
data: {
count: 0
},
render (createElement) {
return createElement({
template: '<div>Hello World ' + this.count + '</div>'
})
},
created () {
setTimeout(() => {
this.count++
}, 2000)
}
})
</script>
Here, after 2 seconds, the counter in <div>Hello World ' + this.count + '</div> will increment from 0 to 1.
Now, what if we want to separate the template from the data?
<script type="text/javascript">
new Vue({
el: '#app',
render (createElement) {
return createElement({
template: '<div>Hello World {{ count }}</div>',
data () {
return {foo: 'bar'}
}
})
}
})
</script>
This code will display Hello World bar.
Now, let's see what happen if we try to load our template over http. We'll use the axios library to do so. Let's create a remote.html file to contain our html code:
<div>
I'm a remote component {{ foo }}
</div>
Now, let's try to load it via Ajax:
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.2/axios.min.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
template: null
},
render (createElement) {
return createElement({
template: this.template ? this.template : '<div>Hello World {{ foo }}</div>',
data () {
return {foo: 'bar'}
}
})
},
created () {
axios({
url: '/remote.html',
method: 'get'
}).then(response => {
this.template = response.data
})
}
})
</script>
This code will display I'm a remote component {{ foo }} as soon as remote.html has been loaded from the browser.
Note that the object passed to the createElement function is actually a component structure. You can use the same methods on it:
render (createElement) {
return createElement({
template: this.template ? this.template : '<div>Hello World {{ foo }}</div>',
data () {
return {foo: 'bar'}
},
mounted () {
alert('Hello from mounted')
}
})
}
will trigger an alert on the browser.
Anyway, here is a complete example with nested components:
Index.html
<!DOCTYPE html>
<html>
<head>
<title>Vue</title>
</head>
<body>
<div id="app">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.2/axios.min.js"></script>
<script type="text/javascript">
const headerComponent = {
data () {
return {
template: '<div>Loading...</div>'
}
},
render (createElement) {
return createElement({
template: this.template,
data () {
return {
search: ''
}
}
})
},
created () {
axios('/header.html').then(response => {
this.template = response.data
})
}
}
new Vue({
el: '#app',
data: {
template: null
},
render (createElement) {
return createElement({
template: this.template ? this.template : 'Loading...',
data () {
return {foo: 'bar'}
},
components: {
'my-header': headerComponent
}
})
},
created () {
axios({
url: '/remote.html',
method: 'get'
}).then(response => {
this.template = response.data
})
}
})
</script>
</body>
</html>
header.html
<div>
<label>Search</label>
<input v-model="search" name=""> The search is: {{ search }}
</div>
I'm not sure that this is really the best approach and if I'm really responding to the question, but it will at list give you some tips on how Vue handles rendering and components...

Vue.js2 - Child component is not being rendered

I'm new to vuejs and just started playing with it. While trying different tutorials I'm stuck at this code sample which is not working. Can anyone please explain why the second-component is not being rendered?
Vue.component('first-component', {
template: `<div>This is first component: {{val}}!</div>`,
data: function () {
return {
val: "FIRST <second-component></second-component>"
}
},
})
Vue.component('second-component', {
template: `<p>This is second component: {{val}}</p>`,
data: function () {
return {
val: 'SECOND'
}
},
})
new Vue({
el: '#example'
})
<script src="https://unpkg.com/vue#2.1.10/dist/vue.js"></script>
<div id="example">
<first-component></first-component>
</div>
The problem is you have put the <second-component> in the val variable, and trying to render it with Mustache syntax However as stated in docs The double mustaches interprets the data as plain text, not HTML
You can use v-html to insert the component as plain HTML but again it is stated: the contents are inserted as plain HTML - they will not be compiled as Vue templates.
The only way you can render second-component is by putting this in the template:
template: `<div>This is first component: {{val}}!<second-component></second-component></div>`,
That's because you are returning it as "data" in "val". So that's not evaluated to a component. If you put it in the template, it works.
Vue.component('first-component', {
template: `<div>This is first component: {{val}}! <second-component></second-component></div>`,
data: function () {
return {
val: "FIRST"
}
},
})
Vue.component('second-component', {
template: `<p>This is second component: {{val}}</p>`,
data: function () {
return {
val: 'SECOND'
}
},
})
new Vue({
el: '#example'
})
<script src="https://unpkg.com/vue#2.1.10/dist/vue.js"></script>
<div id="example">
<first-component></first-component>
</div>