I made the form a component, it disappeared with Vue.js - vue.js

overview
Currently, the created new.vue and edit.vue have similar form parts, so I would like to make them common and componentized.
Therefore, I would like to create a new form.vue and display the page in the form of calling it.
However, when I made it into a component, the page disappeared.
(There is no such description in the log, and there is no error display in Console)
I think the data transfer isn't working, but I'm not sure where to fix it.
I would appreciate it if you could tell me how to fix it.
Original code before componentization
New.vue
<template>
<main>
<form>
<section>
<div>
<div>
<fieldset>
<div class="form-row">
<div class="form-group col-3">
<label>タイトル</label>
<input v-model="latest_information.title" type="text">
</div>
<div class="form-group col-3">
<label>詳細</label>
<input v-model="latest_information.detail" type="text">
</div>
</div>
</fieldset>
</div>
</div>
</section>
<div class="btn-container d-flex justify-content-center">
<button class="button-square btn-send" type="button" #click="createLatestInformation">保存する</button>
</div>
</form>
</main>
</template>
<script>
export default {
data() {
return {
latest_information: {
title: '',
detail: '',
},
}
},
methods: {
createLatestInformation() {
this.$loading.load(this.$auth.api.post('admin/latest_informations/', {
latest_information: this.latest_information
})
.then(response => {
this.$router.push({name: 'AdminLatestInformationIndex'})
}))}
},
}
</script>
Code after componentization (not behaving well)
New.vue
<template>
<form :latest_information="latest_information" #click="createLatestInformation"></form>
</template>
<script>
import Form from './Form.vue';
export default {
components:{
Form
},
data() {
return {
latest_information: {
title: '',
detail: '',
},
}
},
methods: {
createLatestInformation() {
this.$loading.load(this.$auth.api.post('admin/latest_informations/', {
latest_information: this.latest_information
})
.then(response => {
this.$router.push({name: 'AdminLatestInformationIndex'})
}))}
},
}
</script>
Form.vue
<template>
<main>
<form>
<section>
<div>
<div>
<fieldset>
<div class="form-row">
<div class="form-group col-3">
<label>タイトル</label>
<input v-model="latest_information.title" type="text">
</div>
<div class="form-group col-3">
<label>詳細</label>
<input v-model="latest_information.detail" type="text">
</div>
</div>
</fieldset>
</div>
</div>
</section>
<div class="btn-container d-flex justify-content-center">
<button class="button-square btn-send" type="button" #click="$emit('click')">保存する</button>
</div>
</form>
</main>
</template>
<script>
export default {
props: {
latest_information: {
title: '',
detail: '',
},
}
}
</script>
<style>
</style>
Environment
rails 6
vue#2.6.10

form was a reserved word.Changed to tform.
<template>
<tform :latest_information="latest_information" #click="createLatestInformation"></form>
</template>
<script>
import Form from './Form.vue';
export default {
components:{
Tform: Form
},

Related

Cloning div with vue

<template>
<b-form #submit.prevent="Submit" class="mb-5">
<div class="inputArea" v-for="input in inputs" :key="input.id">
<b-form-group label-cols-sm="2" label="Solution (EN)">
<ckeditor :editor="ckeditor" v-model="form.body.en" :config="ckeditorConfig"></ckeditor>
<div v-if="errors['body.en']">
<div v-for="err in errors['body.en']" :key="err">
<small class="text-danger">{{ err }}</small>
</div>
</div>
</b-form-group>
<b-form-group label-cols-sm="2" label="Body (FR)">
<ckeditor :editor="ckeditor" v-model="form.body.np" :config="ckeditorConfig"></ckeditor>
<div v-if="errors['body.np']">
<div v-for="err in errors['body.np']" :key="err">
<small class="text-danger">{{ err }}</small>
</div>
</div>
</b-form-group>
<b-form-group label-cols-sm="2" label="Body (IT)">
<ckeditor :editor="ckeditor" v-model="form.body.in" :config="ckeditorConfig"></ckeditor>
<div v-if="errors['body.in']">
<div v-for="err in errors['body.in']" :key="err">
<small class="text-danger">{{ err }}</small>
</div>
</div>
</b-form-group>
</div>
<b-form-group label="" label-cols-sm="2">
<b-button type="button" class="text-white" variant="dark" #click="addRow">Add row</b-button>
</b-form-group>
<b-form-group label="" label-cols-sm="2">
<b-button type="submit" class="text-white" variant="dark">Submit</b-button>
</b-form-group>
</b-form>
</template>
<style lang="scss">
</style>
<script>
import CKEditor from '#ckeditor/ckeditor5-vue2'
import ClassicEditor from '#ckeditor/ckeditor5-build-classic'
export default {
name: 'Interaction',
components: {
ckeditor: CKEditor.component
},
data(){
return{
counter: 0,
inputs: [
{
en: '',
np: '',
in: '',
}],
form: {
body: [
{
en: '',
np: '',
in: '',
}
],
},
errors: {},
ckeditorData: '<p></p>',
ckeditorConfig: {
// The configuration of the editor
},
ckeditor: ClassicEditor
}
},
methods: {
Submit(){
this.storing = true
this.errors = {}
var self = this
axios.post('/this-is-a-post-url', this.form)
.then(function(response){
console.log(response)
})
},
addRow() {
this.inputs.push({
en: '',
it: '',
fr: '',
id: `${++this.counter}`,
value: '',
});
}
}
}
</script>
I will have array coming in the body name so I am trying to to clone the clone body on a click of a button which has a function AddRow. I want to clone the three fields en,np,in and I want it work like normal html works in this. Example when we clone html form it create input field like so <input name="body['en'][0]"> and when we clone another time it creates something like this <input name="body['en'][1]">.
I have the above code, it clones the body but it also clones the added text before cloning. I want to add an empty field while cloning and also want to update v-model. How can I do that?
Refer below example:
https://codepen.io/telen/pen/OeNZVV
<main class="container">
<form id="app" data-apartments='[{ "price": "23000", "rooms": "12" }, { "price": "42000", "rooms": "32" }]'>
<h1>
Dynamic apartment forms
</h1>
<hr>
<div class="row">
<div class="col-xs-2">
<button type="button" v-on:click="addNewApartment" class="btn btn-block btn-success">
Add +
</button>
</div>
<div class="col-xs-10">
Would you like add more apartments?
</div>
</div>
<div v-for="(apartment, index) in apartments">
<div class="row">
<div class="col-xs-2">
<label> </label>
<button type="button" v-on:click="removeApartment(index)" class="btn btn-block btn-danger">
Rem -
</button>
</div>
<div class="form-group col-xs-5">
<label>Price (HUF)</label>
<input v-model="apartment.price" type="number"
name="apartments[][price]" class="form-control" placeholder="Price">
</div>
<div class="form-group col-xs-5">
<label>Rooms (PCS)</label>
<input v-model="apartment.rooms" type="number"
name="apartments[][rooms]" class="form-control" placeholder="Rooms">
</div>
</div>
</div>
<div class="row">
<div class="col-xs-2">
<button type="submit" v-on:click.prevent="sumbitForm" class="btn btn-block btn-primary">
Submit
</button>
</div>
<div class="col-xs-10">
Open the console (F12) and see the result
</div>
</div>
<hr>
<pre>{{ $data }}</pre>
</form>
JS:
window.app = new Vue({
el: '#app',
data: {
apartment: {
price: '',
rooms: ''
},
apartments: [],
},
mounted: function () {
/*
* The "data-apartments" could come from serverside (already saved apartments)
*/
this.apartments = JSON.parse(this.$el.dataset.apartments)
},
methods: {
addNewApartment: function () {
this.apartments.push(Vue.util.extend({}, this.apartment))
},
removeApartment: function (index) {
Vue.delete(this.apartments, index);
},
sumbitForm: function () {
/*
* You can remove or replace the "submitForm" method.
* Remove: if you handle form sumission on server side.
* Replace: for example you need an AJAX submission.
*/
console.info('<< Form Submitted >>')
console.info('Vue.js apartments object:', this.apartments)
window.testSumbit()
}
}
})
/*
* This is not Vue.js code, just a bit of jQuery to test what data would be submitted.
*/
window.testSumbit = function () {
if (!window.jQuery) {
console.warn('jQuery not present!')
return false
}
console.info('Submitted (serverside) array:', jQuery('form').serializeJSON())
}

How to pass data which is coming as response from backend to the another component in vue.js?

I am developing one page which is responsible for placing order Cart.vue which contains two api calls, handleMail() method is sending email and generating a orderID and i am getting response from backend in network section like this.
{
"message":"order created successfully",
"orderID":87450588
}
i am catching that orderID and stored as a orderNumber,Now i want to pass that orderNumber to another component called orderPlace.vue and i want to display that orderNumber inside template section.for this i am creating Event bus it's not working ,please help me to pass orderNumber to another component ...
Cart.vue
<template>
<div class="main">
<div class="first-section">
<div class="content">
<h5>My Cart({{books.length}})</h5>
</div>
<div v-for="book in books" :key="book.id" class="container">
<div class="mid-section">
<img class="img-section" v-bind:src="book.file" alt="not found">
<p class="title-section">{{book.name}}</p>
</div>
<div class="author-section">
<p class="author-name">by {{book.author}}</p>
</div>
<div class="price-section">
<h6>Rs.{{book.price}}</h6>
</div>
<div class="icons">
<i class="fas fa-minus-circle"></i>
<input class="rectangle" value=1>
<i class="fas fa-plus-circle"></i>
</div>
</div>
<div class="btn-grps">
<button class="btn" v-on:click="flip()" v-if="hide==true" type="submit">Place Order</button>
</div>
</div>
<div class="second -section">
<div class="details-box">
<input type="text" v-if="hide==true" class="initial-btn" placeholder="Customer Details" />
</div>
<div v-if="hide==false" class="fill-details">
<form #submit.prevent="" class="address">
<h4 class="heading">Customer Details</h4>
<div class="name">
<input type="name" required pattern="[A-Za-z]{3,10}" v-model="name">
<label class="label">Name</label>
</div>
<div class="name">
<input type="text" required v-model="phoneNumber">
<label class="label">Phone Number</label>
</div>
<div class="pin">
<input type="text" required v-model="pincode">
<label class="label">PinCode</label>
</div>
<div class="pin">
<input type="text" required v-model="locality">
<label class="label">Locality</label>
</div>
<div class="address-block">
<input class="address" type="text" required v-model="address">
<label id="Add" class="label">Address</label>
</div>
<div class="city-landMark">
<input type="text" required v-model="city">
<label class="label">City/Town</label>
</div>
<div class="city-landMark">
<input type="text" required v-model="landmark">
<label class="label">LandMark</label>
</div>
<div class="Radio-Buttons">
<p>Type</p>
<div class="radio-btns flex-container">
<div>
<input type="radio" id="Home" value="Home" name="type" v-model="type">
<div class="first-radio"> <label class="home" for="Home">Home</label></div>
</div>
<div>
<input class="work-round" type="radio" id="Work" value="Work" name="type" v-model="type">
<div class="second-radio"> <label for="Work" class="work-label">Work</label></div>
</div>
<div>
<input class="other-round" type="radio" id="Other" value="Other" name="type" v-model="type">
<div class="third-radio"><label class="other-label" for="Other">Other</label></div>
</div>
</div>
<div class="btn-continue">
<button type="submit" #click="handlesubmit();handleMail();" class="continue">continue</button>
</div>
</div>
</form>
</div>
</div>
</div>
</template>
<script>
import service from '../service/User';
import { EventBus } from "./event-bus.js";
export default {
created() {
if (localStorage.getItem("reloaded")) {
localStorage.removeItem("reloaded");
} else {
localStorage.setItem("reloaded", "1");
location.reload();
}
service.userDisplayCart().then(response => {
this.books = response.data;
})
},
data() {
return {
flag: true,
hide: true,
booksCount: 0,
name: '',
phoneNumber: '',
pincode: '',
locality: '',
city: '',
address: '',
landmark: '',
type: '',
books: [],
cart:'MyCart',
nameField:'Name',
phoneField:'Phone Number',
pincodeField:'PinCode',
AddressField:'Address',
localityField:'Locality',
cityField:'CityTown',
landmarkField:'LandMark',
orderNumber:''
}
},
methods: {
flip() {
this.hide = !this.hide;
},
Togglebtn() {
this.flag = !this.flag;
},
handlesubmit() {
let userData = {
name: this.name,
phoneNumber: this.phoneNumber,
pincode: this.pincode,
locality: this.locality,
city: this.city,
address: this.address,
landmark: this.landmark,
type: this.type,
}
service.customerRegister(userData).then(response => {
return response;
}).catch(error=>{
alert("invalid customer address");
return error;
})
},
// handleMail(){
// service.confirmMail().then(response=>{
// alert("order placed successfully");
// let orderNumber= response.data.orderID;
// this.$router.push({path: '/ordersuccess'});
// console.log(response);
// return orderNumber;
// }).catch(error=>{
// alert("Error in sending email");
// return error;
// })
// }
handleMail(){
service.confirmMail().then(response=>{
alert("order placed successfully");
let orderNumber= response.data.orderID;
console.log("my num",orderNumber);
EventBus.$emit("emitting-order", orderNumber);
this.$router.push({path: '/ordersuccess'});
console(response);
return orderNumber;
})
},
}
}
</script>
<style lang="scss" scoped>
#import "#/styles/Cart.scss";
</style>
OrderPlace.vue
<template>
<div class="order-place">
<div class="image-container">
<img src="../assets/success.png" alt="not found" />
</div>
<div class="title-container">
<p>Order placed Successfully</p>
</div>
<div class="message-section">
<p>Hurray!!!your order is confirmed {{orderNumber}} and placed successfully contact us in below details
for further communication..</p>
</div>
<div class="title-section">
<div class="email-us">
<p>Email-us</p>
</div>
<div class="contact-us">
<p>Contact-us</p>
</div>
<div class="address">
<p>Address</p>
</div>
</div>
<div class="email-sec">
<p>admin#bookstore.com</p>
</div>
<div class="contact-sec">
<p>+918163475881</p>
</div>
<div class="address-sec">
42, 14th Main, 15th Cross, Sector 4 ,opp to BDA complex, near Kumarakom restaurant, HSR Layout, Bangalore 560034
</div>
<div class="button">
<router-link to="/dashboard" class="btn">Continue Shopping</router-link>
</div>
</div>
</template>
<script>
import { EventBus } from "./event-bus.js";
export default {
name: 'OrderPlace',
data(){
return{
successTitle:'Order placed Successfully',
adminEmailSection:'Email-us',
adminContactSection:'Contact-us',
adminAddressSection:'Address',
adminEmail:'admin#bookstore.com',
adminMobNum:'+918163475881',
orderNumber: ''
}
},
mounted() {
EventBus.$on("emitting-order", orderNo=> {
this.orderNumber = orderNo;
console.log(`Oh, that's great ${orderNo})`);
return orderNo;
});
}
}
</script>
<style lang="scss" scoped>
#import "#/styles/OrderPlace.scss";
</style>
event-bus.js
import Vue from 'vue';
export const EventBus = new Vue();
If the orderPlace.vue component is not active when you do the emit. It cannot receive the element.
You can try to register your order number, in the localStorage. Or call orderPlace.vue as a child component and pass the order number to the props

Vue.JS: Communication with component

I have two component Header and AddUser component. Inside Header component I have a button that has function to show modal. And the modal is inside AddUser component like below.
Header.vue
<template>
<header>
<h2>{{title}}</h2>
<p>{{description}}</p>
<div class="text-center btn-class">
<button #click="showModal = true">Add Vehicle</button>
</div>
</header>
</template>
<script>
export default{
name: 'Header',
props: {
title: {
type: String,
default: 'Title!!',
},
description: {
type: String,
default: 'Description!!',
}
}
}
</script>
AddUser.vue
<template>
<div>
<transition name="fade" appear>
<div class="modal-overlay" v-if="showModal" #click="showModal = false"></div>
</transition>
<transition name="slide" appear>
<div class="modal" v-if="showModal">
<h3>Enter your vehicle detail</h3>
<div class="body">
<form #submit="onSubmit">
<div class="form-group">
<input type="text" v-model="name" name="name" class="form-control" placeholder="Enter your name">
</div>
<br><br>
<div class="form-btn form-group text-center">
<Button type="submit" text="Add" color="#2BA0A3" />
</div>
</form>
</div>
</div>
</transition>
</div>
</template>
<script>
import Button from './Button'
export default {
name: 'AddUser',
data(){
return {
showModal: false,
name: ''
}
},
components: {
Button
},
methods: {
onSubmit(e){
e.preventDefault()
if(!this.name){
alert('Please enter name.')
}
},
}
}
</script>
And this is my App.vue
<template>
<div class="container">
<Header />
<AddUser />
</div>
</template>
<script>
import Header from './components/Header'
import AddUser from './components/AddUser'
export default {
name: 'App',
components: {
Header,
AddUser,
}
}
</script>
The code works perfectly if I put button inside AddUser.vue but I want to keep the button on Header.vue and want it work also. How can I make it both component to communicate?
Move your showModal variable to your App.vue and pass it to your AddUser component as a prop. Inside your Header and AddUser components you will need to update the showModal value by emitting a show-modal-event with the value true or false depending on if you want to show or hide the modal. Listen for the event in App.vue and update it's local data showModal value with the $events value.
Here is an example. ** FYI this code isn't tested so there might be typos.
Header.vue
<template>
<header>
<h2>{{title}}</h2>
<p>{{description}}</p>
<div class="text-center btn-class">
<button #click="$emit('show-modal-event', true)">Add Vehicle</button>
</div>
</header>
</template>
<script>
export default{
name: 'Header',
props: {
title: {
type: String,
default: 'Title!!',
},
description: {
type: String,
default: 'Description!!',
}
}
}
</script>
AddUser.vue
<template>
<div>
<transition name="fade" appear>
<div class="modal-overlay" v-if="showModal" #click="$emit('show-modal-event', false)"></div>
</transition>
<transition name="slide" appear>
<div class="modal" v-if="showModal">
<h3>Enter your vehicle detail</h3>
<div class="body">
<form #submit="onSubmit">
<div class="form-group">
<input type="text" v-model="name" name="name" class="form-control" placeholder="Enter your name">
</div>
<br><br>
<div class="form-btn form-group text-center">
<Button type="submit" text="Add" color="#2BA0A3" />
</div>
</form>
</div>
</div>
</transition>
</div>
</template>
<script>
import Button from './Button'
export default {
name: 'AddUser',
data(){
return {
name: ''
}
},
props: {
showModal: {
type: Boolean,
default: false
}
},
components: {
Button
},
methods: {
onSubmit(e){
e.preventDefault()
if(!this.name){
alert('Please enter name.')
}
},
}
}
</script>
App.vue
<template>
<div class="container">
<Header #show-modal-event="showModal=$event" />
<AddUser #show-modal-event="showModal=$event" :showModal="showModal" />
</div>
</template>
<script>
import Header from './components/Header'
import AddUser from './components/AddUser'
export default {
name: 'App',
components: {
Header,
AddUser,
},
data(){
return {
showModal: false,
}
},
}
</script>

Is it possible to use Vue-sweetalert2 html as vue component?

I use this package https://www.npmjs.com/package/vue-sweetalert2 and I want to past vue component in Vue.swal as html.
<template>
<div class="w-full">
<div class="py-6 w-full">
<button
type="button"
class="btn btn-default btn-primary"
#click="openTeamsModal"
>
Teams
</button>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import TeamTable from "./TeamTable";
import VueSweetalert2 from 'vue-sweetalert2';
Vue.use(VueSweetalert2);
export default {
components: {TeamTable},
props: [
'resourceName',
'resourceId',
'field'
],
data: () => ({
teams: [],
}),
methods: {
openTeamsModal() {
Nova.request().get(`/api/competitors/${this.field.seasonId}/${this.field.championshipId}`).then( responce => {
console.log(responce)
});
Vue.swal({
title: 'Test',
html: '<team-table></team-table>',
});
}
},
}
</script>
but there is nothing. I am new to VueJs and I still don’t fully understand how to insert my components as html.
Yes! is possible! ... after hours of research, I have succeeded.
this is the way:
you need to include all the logic of the template between this characters ` `
you will also need edit the vue.config.js file and add inside the configurewebpack object add this: 'vue$':'vue/dist/vue.esm.js'
configureWebpack: {
resolve: {
alias: {
'src': resolveSrc('src'),
'chart.js': 'chart.js/dist/Chart.js',
// add this line for include components inside swal alert
'vue$':'vue/dist/vue.esm.js'
}
Once this is done you must relaunch the project "npm run dev"
This is my complete example, tested and working
openSweet() {
Vue.component('my-comp', {
template: `
<div class="card-content">
<div class="span2">
<div class="col-sm-6 col-md-2 col-lg-3">
<div class="row">
<div style="margin-top: 6px;" >
<p-switch v-model="switchTrip.state" type="primary" on-text="ON" off-text="OFF" style="justify-content:center"></p-switch>
<h5 class="card-title" style="margin-left: 25px;">Recorridos</h5>
</div>
</div>
<div class="row">
<div style="margin-top: 6px;" >
<p-switch v-model="switchVel.state" type="primary" on-text="ON" off-text="OFF" style="justify-content:center"></p-switch>
<h5 class="card-title" style="margin-left: 25px;">Velocidad</h5>
</div>
</div>
</div>
</div>
<div class="span2">
<div class="col-sm-6 col-md-4 col-lg-3">
<div class="row">
<div >
<input type="search" class="form-control input-sm" placeholder="km / h" v-model="vmax">
<h5 class="card-title">Vel. Max</h5>
</div>
</div>
<div class="row">
<div>
<input type="search" class="form-control input-sm" placeholder="minutos" v-model="tol">
<h5 class="card-title">Tolerancia</h5>
</div>
</div>
</div>
</div>
</div>
`,
data () {
return {
switchVel: {
state: false
},
switchEvent: {
state: false
},
switchTrip: {
state: false
},
search: '',
vmax: '',
tol: ''
}
},
components: {
[Button.name]: Button,
Card,
PSwitch
}
})
new Vue({
el: '#modal',
beforeCreate: () => {
swal({
titleText: "Descarga de Reportes",
showCancelButton: true,
cancelButtonText: 'Cancelar',
confirmButtonText: 'Descargar',
// confirmButtonAriaLabel: 'glyphicon glyphicon-ok-sign',
// cancelButtonAriaLabel: 'glyphicon glyphicon-remove-sign',
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
width: 800,
html: '<div id="modal"><my-comp></my-comp></div>'
})
}
})
}
I hope it helps you
Greetings from Argentina
https://github.com/aledc7

Vue: Data 'undefind' when component render

I would like to set a class to one of my elements when current language I equal to element id. But when method is fired to do this check then I have log "undefined".
Why? How to set that class properly?
Is data object loaded latter then component render?
<template>
<div>
<div class="star-box">
<div class="head">
<img :src="'images/flags/en.png'"
id="en"
class="student-img"
v-bind:class="{'activeLanguage': checkActiveLanguage('en')}"
alt=""
>
</div>
<div class="body">
<h5 class="heading">English</h5>
</div>
</div>
<div class="star-box">
<div class="head">
<img :src="'images/flags/de.png'"
id="de"
class="student-img"
v-bind:class="{'activeLanguage': checkActiveLanguage('de')}"
alt=""
>
</div>
<div class="body">
<h5 class="heading">Deutsch</h5>
</div>
</div>
</div>
</template>
JS
<script>
import {mapActions,mapGetters} from 'vuex';
export default {
name: 'Language',
data() {
return {
language: ''
}
},
methods: {
checkActiveLanguage: (lang)=> {
console.log(this.language);
if(lang==this.language) return true;
},
...mapGetters(['getCurrentLanguage']),
},
beforeMount(){
this.language = this.getCurrentLanguage();
}
}
</script>