Using file and array in bootstrap vue - vue.js

I have the following code on a form
<template>
<base-layout :layout-classes="layoutClasses">
<div class="container mt-3">
<div v-if="storing">
<h3>Please wait....</h3>
</div>
<div class="content">
<base-block rounded title="Create Center">
<b-form #submit.prevent="AddForm" class="mb-5">
<b-form-group label-cols-sm="2" label="English Name">
<b-form-input v-model="name.en" class="form-control-alt" type="text" placeholder="English name"></b-form-input>
</b-form-group>
<b-form-group label-cols-sm="2" label="French Name">
<b-form-input v-model="name.fr" class="form-control-alt" type="text" placeholder="French Name"></b-form-input>
</b-form-group>
<b-form-group label-cols-sm="2" label="Italian Name">
<b-form-input class="form-control-alt" v-model="name.it" type="text" placeholder="Italian Name"></b-form-input>
</b-form-group>
<b-form-group label="Image" label-cols-sm="2">
<b-form-file :state="Boolean(image)" plain v-model="image"></b-form-file>
</b-form-group>
<b-form-group label="" label-cols-sm="2">
<b-button type="submit" class="text-white" variant="dark">Submit</b-button>
<b-button type="reset" class="text-white" variant="danger" #click="ResetForm()">Reset</b-button>
</b-form-group>
</b-form>
</base-block>
</div>
</div>
</base-layout>
</template>
<script>
export default {
data () {
return {
name: [],
image: null,
storing: false,
}
},
methods: {
AddForm ()
{
this.submitted = true
this.storing = true
this.errors = {}
var self = this
axios.post('/form', this.form)
.then(function(response){
const status = response.status;
self.$router.push('/forms')
})
.catch(err => {
if (status == 401) {
self.$router.push('/login')
}
Object.assign(this.errors, {}, err.response.data.errors)
})
.finally(() => {
this.storing = false
})
},
}
}
</script>
Name field should come in array but when I console this.form all the values are empty. What am I doing wrong here? How should I give name to the field if the field should inside a same name attribute? How does the input file work when it come to vue?

You don't have "form" in data object and input's v-model don't have any binding with form. So:
// update v-model of all inputs
<b-form-input v-model="form.name.en" class="form-control-alt" type="text" placeholder="English name"></b-form-input>
// add form to data object:
form: {
name: {
en: "",
fr: ""
},
image: ""
}

Related

Pass data from component

I'm fairly new to Vue and I'm trying to pass data from a component to a view. I'm not sure if I'm using props right. I have a dialog and when I save, I want to insert the data to the database. I also want to reuse the addCustomer() function that's why I didn't place the function in the component.
pages/customers.vue
<template>
<div>
<div class="items-center justify-between md:flex">
<Heading
title="Customers"
desc="The list of customers or companies you work with."
/>
<button #click="openModal" class="btn-primary">Add New Customer</button>
</div>
<CustomerList class="mt-4" :customers="customers" />
</div>
<CustomerDialog
:is-open="isOpen"
:close-modal="closeModal"
:open-modal="openModal"
:name="name"
:address="address"
:email="email"
:add-customer="addCustomer"
/>
</template>
<script setup>
const client = useSupabaseClient();
const name = ref("");
const address = ref("");
const email = ref("");
const isOpen = ref(false);
function closeModal() {
isOpen.value = false;
}
function openModal() {
isOpen.value = true;
}
const { data: customers } = await useAsyncData("customers", async () => {
const { data } = await client.from("customers").select("*");
return data;
});
async function addCustomer() {
if (name.value == "" || address.value == "" || email.value == "") return;
const { data } = await client.from("customers").upsert({
name: name.value,
address: address.value,
email: email.value,
});
customers.value.push(data[0]);
name.value = "";
address.value = "";
email.value = "";
closeModal();
}
</script>
components/customer/Dialog.vue
<template>
<Dialog as="div" #close="closeModal" class="relative z-10">
<input type="text" id="name" v-model="name" />
<input type="text" id="address" v-model="address" />
<input type="email" id="email" v-model="email" />
<button type="button" #click="addCustomer">Save</button>
<button type="button" #click="closeModal">Cancel</button>
</Dialog>
</template>
<script setup>
defineProps([
"name",
"address",
"email",
"addCustomer",
"isOpen",
"closeModal",
"openModal",
]);
</script>
EDIT: The Cancel button in the Dialog works while Save button doesn't.
You cannot bind props directly to the v-model directive, in your case you've to use Multiple v-model bindings
<template>
<Dialog as="div" #close="closeModal" class="relative z-10">
<input type="text" id="name" :value="name" #input="$emit('update:name', $event.target.value)"/>
<input type="text" id="address" :value="adress" #input="$emit('update:address', $event.target.value)" />
<input type="email" id="email" :value="email" #input="$emit('update:email', $event.target.value)" />
<button type="button" #click="$emit('add-customer')">Save</button>
<button type="button" #click="closeModal">Cancel</button>
</Dialog>
</template>
<script setup>
defineProps([
"name",
"address",
"email",
"addCustomer",
"isOpen",
"closeModal",
"openModal",
]);
defineEmits(['update:name', 'update:email','update:address','add-customer'])
</script>
in parent component :
<CustomerDialog
:is-open="isOpen"
:close-modal="closeModal"
:open-modal="openModal"
v-model:name="name"
v-model:address="address"
v-model:email="email"
#add-customer="addCustomer"
/>
As addCustomer method is available in parent. What you can do is that emit an event on Save button click from the dialog component and then capture the event in parent and invoke addCustomer method.
I just created a below code snippet with Vue 2.* just for your understanding purpose.
Vue.component('customerdialog', {
data() {
return {
customerDetailObj: {}
}
},
props: ['name', 'address', 'email'],
mounted() {
this.customerDetailObj = {
name: this.name,
address: this.address,
email: this.email
}
},
template: `<div><input type="text" id="name" v-model="customerDetailObj.name" />
<input type="text" id="address" v-model="customerDetailObj.address" />
<input type="email" id="email" v-model="customerDetailObj.email" />
<button type="button" #click="$emit('add-customer', customerDetailObj)">Save</button></div>`
});
var app = new Vue({
el: '#app',
data: {
name: 'Alpha',
address: 'Street 1',
email: 'alpha#testmail.com',
customerList: []
},
methods: {
addCustomer(customerObj) {
// Created user details
this.customerList.push(customerObj);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<CustomerDialog :name="name"
:address="address"
:email="email" #add-customer="addCustomer($event)"></CustomerDialog>
<pre>{{ customerList }}</pre>
</div>
You can defineEmits
<script setup>
import {
TransitionRoot,
TransitionChild,
Dialog,
DialogPanel,
DialogTitle,
} from "#headlessui/vue";
defineProps([
"name",
"address",
"email",
"addCustomer",
"isOpen",
"closeModal",
"openModal",
]);
let emit = defineEmits(["add"])
</script>
Or better with typescript:
<script lang="ts" setup>
import {
TransitionRoot,
TransitionChild,
Dialog,
DialogPanel,
DialogTitle,
} from "#headlessui/vue";
defineProps([
"name",
"address",
"email",
"addCustomer",
"isOpen",
"closeModal",
"openModal",
]);
let emit = defineEmits<{ (name: "add"): void }>()
</script>
Now you can use it in your button:
<button
type="button"
class="inline-flex justify-center px-4 py-2 text-sm font-medium text-red-900 bg-red-100 border border-transparent rounded-md hover:bg-red-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-red-500 focus-visible:ring-offset-2"
#click="emit('add')"
>
Save
</button>
Now you can listen to this add event and trigger your addCustomer function
<CustomerDialog
:is-open="isOpen"
:close-modal="closeModal"
:open-modal="openModal"
:name="name"
:address="address"
:email="email"
#add="addCustomer"
/>
You'll want to use event emitters:
In the dialog:
<button #click="$emit('addCustomer')">save</button>
In customers.vue:
<CustomerDialog
:is-open="isOpen"
:close-modal="closeModal"
:open-modal="openModal"
:name="name"
:address="address"
:email="email"
#add-customer="addCustomer"
/>

I am unable to pass my v-model data to my backend for radio button type in vue.js ,How to pass that checked radio button value to my backend ??

I developed one page which is responsible for Registering the users previously i submitted the form without radio buttons, now i need to add radio buttons based on checked type button that value should be sent to the backend ,i am unable to figure out where did i mistaken please help me to fix this issue
Register.vue
<template>
<div class="main">
<div v-if="flag==true" class="container">
<img id="side-img" src="../assets/sideImg.png" alt="notFound" />
<p id="side-content">Online Book Shopping</p>
<div class="box">
<div class="headings">
<h5 class="signin" v-on:click="flip();" id="login" :class="{ active: isLogin }" #click="isLogin = true">Login</h5>
<h5 class="signup" id="signup" :class="{ active: !isLogin }" #click="isLogin = false">signup</h5>
</div>
<form ref="myForm" #submit.prevent="handlesubmit">
<div class="fullname">
<p>FullName</p>
<input type="name" id="name-input" class="namebox" required v-model="fullName" autocomplete="off" pattern="[A-Za-z]{3,12}">
</div>
<div class="username">
<p>EmailID</p>
<input type="email" id="Email-input" class="emailbox" autocomplete="off" required v-model="email" pattern="^[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$">
</div>
<div class="password-section">
<p>Password</p>
<input :type="password_type" class="password" :class="{'password-visible': isPasswordVisible }" id="passField" v-model="password" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$!%*?&])[A-Za-z\d#$!%*?&]{6,}$" required>
<i class="bi bi-eye-slash" id="togglePassword" #click="togglePassword();"></i>
</div>
<div class="mobile">
<p>MobileNumber</p>
<input type="tel" class="telephone" autocomplete="off" v-model="mobile" id="tel" pattern="^\d{10}$" required>
</div>
<div class="role-btns">
<input type="radio" id="user" value="user" name="role" v-model="roleUser" >
<label for="user" class="radio-label">user</label>
<input type="radio" id="admin" value="admin" name="role" v-model="roleUser">
<label for="admin">admin</label>
</div>
<button class="btn-section" id="btn" type="submit">Signup</button>
</form>
</div>
</div>
<Login v-if="flag==false" />
</div>
</template>
<script>
import service from '../service/User'
export default {
name: 'Register',
components: {
Login: () => import('./Login.vue')
},
data() {
return {
fullName: '',
email: '',
password: '',
mobile: '',
roleUser:'',
password_type: "password",
isLogin: false,
isPasswordVisible: false,
flag: true,
title: 'Online Book Shopping'
}
},
methods: {
flip() {
this.flag = !this.flag;
},
togglePassword() {
this.password_type = this.password_type === 'password' ? 'text' : 'password'
this.isPasswordVisible = !this.isPasswordVisible
},
handlesubmit() {
let userData = {
fullName: this.fullName,
email: this.email,
password: this.password,
mobile: this.mobile
}
service.userRegister(userData).then(response => {
if (response.status == 201) {
alert("user registered successfully");
this.$refs.myForm.reset();
this.$router.push('/login');
}
return response;
}).catch(error => {
alert("invalid credentials");
return error;
})
}
}
}
</script>
<style lang="scss" scoped>
#import "#/styles/Register.scss";
</style>
let userData = {
fullName: this.fullName,
email: this.email,
password: this.password,
mobile: this.mobile,
roleUser:this.roleUser
}

How to access prop by property name from in vuejs

I want to access the error message returned from my api if error exists for its corresponding input field. With what I have tried, all errors returned from the api shows below all input fields as in the image below.
Below are the parent and child vue components.
InputField.vue
<template>
<div class="form-group basic">
<div class="input-wrapper">
<label class="label" :for="name">{{label}}</label>
<input :type="type"
class="form-control"
:class="errorClassObject()"
:id="name" :placeholder="placeholder"
:v-model="value" #input="updateField">
<i class="clear-input">
<ion-icon name="close-circle" role="img" class="md hydrated" aria-label="close circle"></ion-icon>
</i>
</div>
<div v-text="errorMessage(name)" class="input-info text-danger">Error here</div>
</div>
</template>
<script>
export default {
name: "InputField",
props: [
'name', 'value', 'type', 'label', 'placeholder', 'errors'
],
data: function() {
return {
}
},
computed: {
hasError: function(){
return this.errors
//return this.errors.name throws an error name is undefined
}
},
methods: {
updateField (){
this.$emit('input', event.target.value)
},
errorMessage(name){
if(this.hasError){
return this.errors;
//return this.errors.name throws undefined name
}
},
errorClassObject (){
return{
'error-field': this.hasError
}
}
}
}
</script>
<style scoped>
</style>
ChangePassword.vue
<template>
<form #submit.prevent="onSubmit">
<form-input
required
name="current_password"
type="password"
label="Current Password"
:errors="errors"
placeholder="Enter current password"
v-model="passwordForm.current_password"
/>
<form-input .../>
<form-input.../>
<div class="form-button-group transparent">
<button type="submit" class="btn btn-primary btn-block btn-lg">Update Password</button>
</div>
</form>
</template>
Presently, if there are any errors from the request, the response is returned in the format below
You could get access to it using the square brackets like :
errorMessage(name){
if(this.hasError){
return this.errors[name];
}
},

error while I am data:{} at nuxt js is it solvable?

this is the template I want to make a password input and checkbox while box is checked I want to type inside input to turn into the text instead of password
<!--template-->
<template>
<div>
<div id="login">
<h1 style="font-size:30px; color:black;">Login</h1>
<input type="text" placeholder="Username...">
<input :type="inputtype" placeholder="Password...">
<input type="checkbox" name="" id="" :checked="totext">
<button class="button is-link">Submit</button>
Register
Forgot the password..?!
</div>
</div>
</template>
17:5 error Unexpected labeled statement no-labels
17:16 error Expected an assignment or function call and instead saw an expression
<script>
export default {
data () {
inputtype: 'password'
},
methods: {
totext () {
this.inputtype = this.inputtype === 'password' ? 'text' : 'password'
}
}
}
</script>
Please try this code instead:
:type="totext ? 'password': 'text' "
<template>
<div>
<div id="login">
<h1 style="font-size:30px; color:black;">Login</h1>
<input type="text" placeholder="Username...">
<input :type="totext ? 'password': 'text' " placeholder="Password...">
<input type="checkbox" name="" id="" :checked="totext">
<button class="button is-link">Submit</button>
Register
Forgot the password..?!
</div>
</div>
</template>
And this script:
<script>
export default {
data () {
return {
totext : false
}
}
}
</script>
Or this one (the better one)
<template>
<div>
<div id="login">
<h1 style="font-size:30px; color:black;">Login</h1>
<input type="text" placeholder="Username...">
<input :type="isText" placeholder="Password...">
<input type="checkbox" name="" id="" :checked="totext">
<button class="button is-link">Submit</button>
Register
Forgot the password..?!
</div>
</div>
</template>
And
<script>
export default {
data () {
return {
totext : false
}
},
computed: {
isText(){
return totext ? 'password': 'text'
}
}
}
</script>
Please try this code :
data: () => ({
inputtype: 'password'
)}
You've merged the two sets of braces.
This:
data () {
inputtype: 'password'
},
should be this:
data () {
return {
inputtype: 'password'
}
},

How to show success message in vue js after inserting the date into database

I have a perfectly working form I can insert data into database using axios after form validation. I am just struggling to show a success message after inserting the data into the database. how to hide the form and display a succcess message in the same section after sending the data into the database??
here's my perfectly working code
<template>
<b-container>
<div class="update-info">
<div class="feature-text myinv-title">
<h5 class="title title-sm">Update your information</h5>
</div>
<div>
<form #submit.prevent="submit">
<p v-if="errors.length">
<b>Please fill in all the fields</b>
<ul>
<li v-for="error in errors" class="alert alert-danger">{{ error }}</li>
</ul>
</p>
<div class="form-row">
<div class="form-group col-md-3">
<label for="trx number">TRX No</label>
<input
type="text"
name="trx Number"
v-model="newUser.trx"
class="form-control trx-address-nooverflow"
placeholder="Copy paste your TRX no"
/>
<b-form-text id="input-formatter-help">
<a class="text-success">Your TRX address: {{trxNo}}</a>
</b-form-text>
</div>
<div class="form-group col-md-3">
<label for="name">Name</label>
<input
type="text"
name="name"
v-model="newUser.name"
class="form-control"
placeholder="Enter you name"
/>
</div>
<div class="form-group col-md-3">
<label for="email">Email</label>
<input
type="text"
name="email"
v-model="newUser.email"
class="form-control"
placeholder="Enter valid email address"
/>
</div>
<div class="form-group col-md-3">
<label for="country">Country</label>
<country-select
id="Country"
v-model="newUser.country"
:country="newUser.country"
topCountry="US"
class="form-control"
/>
</div>
<div class="form-group col-md-3">
<label for="mobile">Mobile No</label>
<input
id="mobile"
class="form-control"
v-model="newUser.mobile_no"
type="text"
placeholder="Enter your mobile no."
/>
<b-form-text id="input-formatter-help">
Please enter valid phone number
</b-form-text>
</div>
<div class="form-group col-md-3">
<div class="top-30">
<input type="submit" class="btn btn-btn btn-grad btn-submit" />
</div>
</div>
</div>
</form>
</div>
</div>
</b-container>
</template>
here's my vue js code
<script>
import axios from 'axios'
export default{
data(){
return{
errorMessage: "",
successMessage: "",
text: "success",
errors: [],
users: [],
newUser: {trx: "", name: "", country: "", email: "", mobile_no: ""}
}
},
computed: {
trxNo: function() {
return this.$store.state.myAddress;
}
},
mounted: function(){
this.getAllUsers();
},
methods:{
getAllUsers: function(){
axios.get('https://onex.tronpayer.com/api/update-info-form.php?action=read', { crossdomain: true })
.then((response) => {
if(response.data.error){
this.errorMessage = response.data.message;
}else{
this.users = response.data.users;
}
});
},
submit(){
this.checkForm()
if(!this.errors.length) {
var formData = this.toFormData(this.newUser);
axios.post('https://onex.tronpayer.com/api/update-info-form.php?action=update', formData, { crossdomain: true })
.then((response) => {
this.newUser = {trx: "", name: "", country: "", email: "", mobile_no: ""};
if(response.data.error){
this.errorMessage = response.data.message;
}else{
this.getAllUsers();
}
});
}
},
toFormData: function(obj){
var form_data = new FormData();
for(var key in obj){
form_data.append(key, obj[key]);
}
return form_data;
},
clearMessage: function(){
this.errorMessage = "";
this.successMessage = "";
},
//validation
checkForm: function (e) {
this.errors = [];
if (!this.newUser.trx) {
this.errors.push("Trx Number Required.");
}
if (!this.newUser.name) {
this.errors.push("Name Required.");
}
if (!this.newUser.country) {
this.errors.push("Country Required.");
}
if (!this.newUser.email) {
this.errors.push('Email Required.');
} else if (!this.validEmail(this.newUser.email)) {
this.errors.push('Valid Email Address Required.');
}
if (!this.newUser.mobile_no) {
this.errors.push("Mobile Number Required.");
}
if (!this.errors.length) {
return true;
}
},
validEmail: function (email) {
var re = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
}
}
</script>
You can use the v-if conditional rendering for disabling the form and showing the message.
https://v2.vuejs.org/v2/guide/conditional.html
Just create a variable like savingSuccessful: false and set it to true when your ajax request was successful.
Use it now in your form like
<form #submit.prevent="submit" v-if="!savingSuccessful">
This means your form will be displayed until your variable is true.
For a success-message you can create something like this:
<div class="success" v-if="savingSuccessful">
{{ this.text }}
</div>
Your message will be rendered when the variable is true.
Here a JSFiddle:
https://jsfiddle.net/MichelleFuchs/nydruxzw/2/