How to style vue-datetime picker in laravel vue? - laravel

I am trying to use the vue-datetime component inside an other component here is the vue
<template>
<div class="container p-3 bg-gray-100 flex flex-col">
<div>{{ current_post.title }}</div>
<div v-if="edit == false" id="mode-diplay">
<div v-html="current_post.body" class="text-gray-700"></div>
</div>
<div v-else id="mode-edit">
<form class="flex flex-col" action>
<datetime type="datetime" v-model="datetime"></datetime>
<input type="text" val="details.body" />
<textarea
class="markdown"
name="editor"
id="editor"
v-model="raw_post.body"
rows="50"
></textarea>
</form>
</div>
</div>
</template>
<script>
import { Datetime } from "vue-datetime";
export default {
name: "PostDetails",
props: ["current_post", "raw_post", "edit"],
components: {
datetime: Datetime,
},
data() {
return {
datetime:this.raw_post.beg_date
};
},
};
</script>
The vue-date time is displayed but when I click into the field input, the picker shows up vertically with very huge images of the < char.
I followed the example given here https://mariomka.github.io/vue-datetime/ and I don't know what else to do. The trouble is the same on Firefox and Chromium.

You need a specific loader for CSS files
Import in your parent component the style for the datepicker
import 'vue-datetime/dist/vue-datetime.css';
import { Datetime } from "vue-datetime";
import 'vue-datetime/dist/vue-datetime.css';
export default {
name: "PostDetails",
props: ["current_post", "raw_post", "edit"],
components: {
datetime: Datetime,
},
data() {
return {
datetime:this.raw_post.beg_date
};
},
};

Related

Get all values of custom input inside v-for vuejs

I created a vuejs custom input that I wanted to use to dynamically display inputs by using props within the custom input. I haven't shown them here because it would be too long.
By clicking on the submit button, which is also part of the custom input, I wanna be able to get the values of each input, but for some reason, I have only been able to get the value of the last input.
What am I doing wrong?
Custom input:
<template>
<div class="form-input">
<label :label="label" :for="name" v-if="label && type !='submit' ">{{label}} <span v-if="required">*</span></label>
<a v-if="multiple" href="#" class="btn">Upload</a>
<input v-model="inputVal" :multiple="multiple" v-if="type != 'textarea' && type != 'submit'" class="form-control" :required="required" :class="classes" :type="type" :name="name" :placeholder="placeHolder">
<textarea v-model="inputVal" :multiple="multiple" v-else-if="type != 'submit'" class="form-control" :required="required" :class="classes" :type="type" :name="name" :placeholder="placeHolder"></textarea>
<button :multiple="multiple" :name="name" v-else type="submit">{{label}}</button>
</div>
</template>
<script>
export default {
name: "Input",
data () {
return {
inputVal: null
}
},
watch: {
inputVal: {
handler: function(newValue, oldValue) {
this.$emit('input', newValue);
},
deep: true,
}
}
}
</script>
Form where custom input is used:
<template>
<div class="form container">
<form v-on:submit.prevent="sendMail" method="post" class="d-flex row shadow bg-dark border-right border-dark">
<h3 class="col-12">Contact me</h3>
<Input v-model="formInput" v-for="input in inputs" v-bind:key="input.name" :label="input.label" :multiple="input.multiple" :type="input.type" :name="input.name" :class="input.classes" :required="input.required"></Input>
</form>
</div>
</template>
<script>
import Input from "../components/Input";
export default {
name: "Contact",
components: {Input},
data() {
return {
formInput: null,
}
},
methods: {
sendMail () {
console.log(this.formInput);
}
}
}
</script>
The issue I see in your code is, you are using only one variable "formInput" ( in case of Contact component ) and "inputVal" ( in case of Input component ) but you have number of input fields from where you need data right.
The simplest way to deal with these kind of cases is to create a datastructure and loop through that.
For eg.
// Contact component ( i am making it simple to make you understand the scenario )
<template>
<div class="form container">
<form v-on:submit.prevent="sendMail" method="post" class="d-flex row shadow bg-dark border-right border-dark">
<h3 class="col-12">Contact me</h3>
<!-- we are looping through our data structure and binding each inputVal to this input -->
<input v-for="(input, i) in formInputs" :key="i" v-model="input.inputVal">
</form>
</div>
</template>
<script>
import Input from "../components/Input";
export default {
name: "Contact",
components: {Input},
data() {
return {
formInputs: [
{inputVal: ''},
{inputVal: ''},
{inputVal: ''},
],
}
},
methods: {
sendMail () {
// You can extract the data from formInputs as per your need
}
}
}
</script>

[Vue warn]: Error in mounted hook: "Error: viewType "" is not available. Please make sure you've loaded all neccessary plugins

Im trying to use FullCalendar as a vue component in Laravel. I've loaded the plugins correctly as per the documentation but for whatever reason, they are not loading https://fullcalendar.io/docs/vue
Component:
template>
<div class="container">
<div class="row justify-contnet-center">
<div class="col-lg-8">
<form #submit.prevent>
<div class="form-group">
<label for="event_name">event Name</label>
<input
type="text"
id="event_name"
class="form-control"
v-model="newevent.event_name"
>
</div>
<div class="row">
<div class="cold-lg-8">
<div class="form-group">
<label for="date">Date</label>
<input
type="date"
id="date"
class="form-control"
v-model="newevent.date"
>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<div class="form-group">
<label for="time">Time</label>
<input
type="time"
id="time"
class="form-control"
v-model="newevent.time"
>
</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-4" v-if="addingMode">
<button class="btn btn-custom" #click="addNewevent">Book event</button>
</div>
<template>
<div class="col-lg-6 mb-4">
<button class="btn btn-success" #click="updateevent">Update</button>
<button class="btn btn-danger" #click="deleteevent">Delete</button>
<button class="btn btn-warning" #click="addingMode = !addingMode">Cancel</button>
</div>
</template>
</form>
</div>
<div class="col-lg-8 full-calendar" id="calendar">
<FullCalendar #eventClick="showevent" defaultView:="dayGridMonth" :plugins="calendarPlugins" :events="events"/>
</div>
</div>
</div>
</template>
<script>
import { Calendar } from '#fullcalendar/core'
import FullCalendar from '#fullcalendar/vue'
import dayGridPlugin from '#fullcalendar/daygrid'
import interactionPlugin from '#fullcalendar/interaction'
import axios from 'axios'
export default {
components:{
FullCalendar // make custom tag avaliable
},
data() {
return {
calendarPlugins: [ dayGridPlugin, interactionPlugin],
events: "",
newevent: {
event_name: "",
date: "",
time: ""
},
addingMode: true,
indexToUpdate: ""
};
},
created() {
this.getevents();
},
methods: {
addNewevent() {
axios.post('/api/event', {
...this.newevent
})
.then(data=> {
this.getevents(); //update list of getevents
this.resetForm();
})
.catch(err =>
// alert("Unable to add event")
console.log(err.response.data)
);
},
showevent(arg) {
console.logt(arg);
this.addingMode = false;
const {id, event, date, time} = this.events.find (
event => event.id === +arg.event.id
);
this.indexToUpdate = id;
this.newevent = {
event_name: event, // comeback to and see if inserts into db as event_name
date: date,
time: time
};
},
updateevent() {
axios.put('/app/event/' + this.indexToUpdate, {
...this.newevent
})
.then(resp => {
this.resetForm();
this.getevents();
this.addingMode = !this.addingMode;
})
.catch(err =>
// alert('Unable to update event!')
console.log(err.response.data)
);
},
deleteevent() {
axios.delete('/api/event/' + this.indexToUpdate)
.then(resp => {
this.resetForm();
this.getevents();
this.addingMode = !this.addingMode;
})
.catch(err =>
// alert('Unable to delete event')
console.log(err.response.data)
);
},
getevents(){
axios.get('/api/event')
.then(resp => (this.events = resp.data.data))
.catch(err => console.log(err.response.data));
},
resetForm() {
Object.keys(this.newevent).forEach(key=> {
return (this.newevent[key] = "");
});
}
},
watch: {
indexToUpdate() {
return this.indexToUpdate
}
}
};
Then also I have initialized the component with es6 as per this part of the doc https://fullcalendar.io/docs/initialize-es6
import { Calendar } from '#fullcalendar/core';
import dayGridPlugin from '#fullcalendar/daygrid';
import interactionPlugin from '#fullcalendar/interaction';
document.addEventListener('DOMContentLoaded', function() {
let calendarEl = document.getElementById('calendar');
let calendar = new Calendar(calendarEl, {
plugins: [ dayGridPlugin , interactionPlugin ]
});
calendar.render();
});
This is my app.js
Vue.component('calendar-component', require('./components/CalendarComponent.vue').default);
<FullCalendar #eventClick="showevent" defaultView:="dayGridMonth" :plugins="calendarPlugins" :events="events"/>
should become
<FullCalendar :options="calendarOptions" />
I saw the FullCalendar code in github and it doesn't support props defaultView and plugins. Instead it uses prop with name "options"
<script>
import FullCalendar from '#fullcalendar/vue'
import dayGridPlugin from '#fullcalendar/daygrid'
import interactionPlugin from '#fullcalendar/interaction'
export default {
components: {
FullCalendar // make the <FullCalendar> tag available
},
data() {
return {
calendarOptions: {
plugins: [ dayGridPlugin, interactionPlugin ],
initialView: 'dayGridMonth'
}
}
}
}
</script>
<template>
<FullCalendar :options="calendarOptions" />
</template>
Please check the plugin documentation

Vue select onchange prop to child component not working

I have two components. Component 1:
<template>
<div>
<div class="form-group">
<label for="group">Category</label>
<select name="category" v-model="category" #change="setCategory(category)" class="form-control select-group" id="category">
<option value="1">Category 1</option>
<option value="2">Category 2</option>
</select>
</div>
<tags-multiselect :categoryId="category"></tags-multiselect>
</div>
</template>
<script>
export default {
data () {
return {
category: 1,
}
},
methods: {
setCategory(selected) {
this.category = selected;
},
},
}
</script>
Component 2:
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card card-default">
<div class="card-header">Example Component</div>
<div class="card-body">
I'm an example component.
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['categoryId'],
data () {
return {
category_ids: this.categoryId
}
},
created() {
axios.post('/tags', { category_id: this.categoryId })
.then((response) => {
//
})
.catch((err) => {
})
}
}
</script>
When I select option from first component, I not update category_id on second component with other id I get only 1 id. And when I send axios request with category_id I send always only first param 1. How I can resolve this? How I can refresh the second component with new selected data from select field?
props need to be kebab case in the template.
Try <tags-multiselect :category-id="category"></tags-multiselect>
Also, you don't need to redefine props in the data. Get rid of category_ids in component 2, it will just confuse things.
Then, Vue makes it very easy to extract your state from your components. Shared state (categoryId) and operations on shared state ( axios.post(...) ) would be much happier in global scope, according to me !

vuejs loop over in data results not on how many fields i have

v-for is iterating over on my fields not to the data that i selected, example i have 3 fields in my database(name,email,username) it will loop 3 times
Result
Profile.vue
<template>
<div>
<h3>Profile</h3>
<user-profile v-for="user in users" :user="user" :key="user.id"></user-profile>
</div>
</template>
<script>
import UserProfile from '../partials/UserProfile.vue'
import User from '../models/User'
import Form from '../core/Form'
export default {
components: {
UserProfile
},
data() {
return {
users: [
users:[],
],
}
},
created() {
axios.get('/user/profile').then(res => this.users = res);
}
};
</script>
UserProfile.vue
<template>
<div class="row">
<form class="col s12" method="POST" #submit.prevent="onSubmit">
<div class="input-field col s12">
<input type="text" id="name" name="name" v-model="form.name" class="validate" autofocus>
<label for="name" class="active">Name</label>
</div>
<div class="input-field col s12">
<input id="email" type="email" name="email" v-model="form.email" class="validate" autofocus>
<label for="email" class="active">Email</label>
</div>
<div class="right-align">
<button class="btn waves-effect waves-light" type="submit" name="action">Update
<i class="material-icons right">send</i>
</button>
</div>
</form>
</div>
</template>
<script>
import Form from '../core/Form'
export default {
props: ['user'],
data() {
return {
form: new Form({
name: this.user.name,
})
}
},
computed: {
//
},
mounted() {
},
methods: {
//
onSubmit() {
axios.post('/user/update', {
name: this.user.name
})
.then(console.log('yeahh'))
.catch(console.log('failed'))
}
}
};
</script>
Your users inside Data looks wrong.
Here is an edited version
Profile
<script>
import UserProfile from '../partials/UserProfile.vue'
import User from '../models/User'
import Form from '../core/Form'
export default {
components: {
UserProfile
},
data() {
return {
users: [
{
name: 'FirstName LastName',
email: 'firstname.lastname#gmail.com'
}
],
}
},
created() {
// User.all(users => this.users = users)
}
};
</script>
Since you're only returning the currently logged in user, you'll have to edit your Profile component a bit:
<template>
<div>
<h3>Profile</h3>
<user-profile :user="user" :key="user.id"></user-profile>
</div>
</template>
<script>
import UserProfile from '../partials/UserProfile.vue'
import User from '../models/User'
import Form from '../core/Form'
export default {
components: {
UserProfile
},
data() {
return {
user: {},
}
},
created() {
axios.get('/user/profile').then(res => this.user = res);
}
};
</script>

How can I dynamically nest vue components?

I want to add one component inside other when user clicks a button. but how can we render the component in the virtual dom.
I tried using v-html but its not working.
Whats the best way to solve this issue?
export default {
data(){
return{
elements : {
hotel : '<hotel-form></hotel-form>'
},
}
},
methods:{
addHotel(){
console.log('add');
}
}
}
<template>
<div class="container" style="margin-top:300px;">
<div class="row" id="mainform">
<div v-for="item in elements">
<div v-html="item"></div>
</div>
</div>
<button #click="addHotel()">add hotel</button>
</div>
</template>
I would bind an array (hotels) to a <hotel-form> component tag via v-for. This way, no hotel-form components will be initially rendered, and then you can push an object (with any data to want bound to the hotel-form component) to the hotels array and the DOM will automatically render a new corresponding hotel-form component.
Here's a simple example:
Vue.component('hotel-form', {
template: '#hotel-form',
props: { id: Number, name: String },
});
new Vue({
el: '#app',
data() {
return { hotels: [], count: 0 }
},
methods: {
addHotel() {
this.hotels.push({ name: 'foo', id: this.count++ })
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="app">
<div id="mainform">
<hotel-form v-for="hotel in hotels" :key="hotel.id" v-bind="hotel">
</hotel-form>
</div>
<button #click="addHotel">add hotel</button>
</div>
<template id="hotel-form">
<div>
<h4>Hotel Form #{{ id }}</h4>
<div>{{ name }}</div>
</div>
</template>

Resources