I am creating an alert component for a CRUD app using Vue.js. I want a message to be passed to another component once data has been saved. Currently I am trying to pass this data in $router.push like this this.$router.push({path: '/', query: {alert: 'Customer Added'}}) Then access this data in another component. However this is not working as expected, instead the data is passed into the url.
This is the component which saves the data, Add.vue
<template>
<div class="add container">
<Alert v-if="alert" v-bind:message="alert" />
<h1 class="page-header">Add Customer</h1>
<form v-on:submit="addCustomer">
<div class="well">
<h4>Customer Info</h4>
<div class="form-group">
<label>First Name</label>
<input type="text" class="form-control" placeholder="First Name"
v-model="customer.first_name">
</div>
<div class="form-group">
<label>Last Name</label>
<input type="text" class="form-control" placeholder="Last Name"
v-model="customer.last_name">
</div>
</div>
<div class="well">
<h4>Customer Contact</h4>
<div class="form-group">
<label>Email</label>
<input type="text" class="form-control" placeholder="Email" v-model="customer.email">
</div>
<div class="form-group">
<label>Phone</label>
<input type="text" class="form-control" placeholder="Phone" v-model="customer.phone">
</div>
</div>
<div class="well">
<h4>Customer Location</h4>
<div class="form-group">
<label>Address</label>
<input type="text" class="form-control" placeholder="Address" v-model="customer.address">
</div>
<div class="form-group">
<label>City</label>
<input type="text" class="form-control" placeholder="City" v-model="customer.city">
</div>
<div class="form-group">
<label>State</label>
<input type="text" class="form-control" placeholder="State" v-model="customer.state">
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</template>
<script>
import Alert from './Alert'
export default {
name: 'add',
data () {
return {
customer: {},
alert:''
}
},
methods: {
addCustomer(e){
if(!this.customer.first_name || !this.customer.last_name ||
!this.customer.email){
this.alert = 'Please fill in all required fields';
} else {
let newCustomer = {
first_name: this.customer.first_name,
last_name: this.customer.last_name,
phone: this.customer.phone,
email: this.customer.email,
address: this.customer.address,
city: this.customer.city,
state: this.customer.state
}
this.$http.post('http://slimapp.dev/api/customer/add',
newCustomer)
.then(function(response){
this.$router.push({path: '/', query: {alert: 'Customer
Added'}})
});
e.preventDefault();
}
e.preventDefault();
}
},
components: {
Alert
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only
-->
<style scoped>
</style>
This the alert component, Alert.vue
<template>
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span></button>
{{message}}
</div>
</template>
<script>
export default {
name: 'alert',
props: ['message'],
data () {
return {
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
And this is the component where the alert is to be viewed, Customers.vue
<template>
<div class="customers container">
<Alert v-if="alert" v-bind:message="alert" />
<h1 class="page-header">Manage Customers</h1>
<table class="table table-striped">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="customer in customers">
<td>{{customer.first_name}}</td>
<td>{{customer.last_name}}</td>
<td>{{customer.email}}</td>
<td></td></tr>
</tbody>
</table>
</div>
</template>
<script>
import Alert from './Alert';
export default {
name: 'customers',
data () {
return {
customers: [],
alert: ''
}
},
methods: {
fetchCustomers(){
this.$http.get('http://slimapp.dev/api/customers')
.then(function(response){
this.customers = (response.body);
});
}
},
created: function(){
if (this.$route.params.alert) {
this.alert = $route.params.alert
}
this.fetchCustomers();
},
updated: function(){
this.fetchCustomers();
},
components: {
Alert
}
}
How do I solve this?
It is not possible to pass data through vue-router the way you want to. You only can pass parameters like this:
Route definition:
{ path: '/products/:id/edit', name: 'products.edit', component: ProductForm },
And then you can get the parameter with this.$route.params.id
Or you can do:
this.$router.push({name: 'products.index', params: { id: 1 }})
I suggest you to add a GET parameter like ?success=true or show an alert with sweetalert for example before pushing the new route.
A weird solution is to set the value to store/local_storage and retrieve and destroy it from the store/local_storage when the destination page loads.
Related
i have two components Register.vue [my_reg-page]1and Login.vue [my-signin_page ]2, if the user opens register page in the browser (by using /register url), if the user clicks on the Login heading that user will be toggled into the login page(/login),similarly if the user opens login page over the chrome , if the user clicks on signup heading that user will be toggled into the registration-page, How to do toggling between two components,please help me to fix this issue.
Register.vue
<template>
<div class="main">
<div 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" 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" 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" v-model="mobile" id="tel" pattern="^\d{10}$" required>
</div>
<button class="btn-section" id="btn" type="submit">Signup</button>
</form>
</div>
</div>
</div>
</template>
<script>
import service from '../service/User'
export default {
name: 'Register',
data() {
return {
fullName: '',
email: '',
password: '',
mobile: '',
password_type: "password",
isLogin:false,
isPasswordVisible: false,
title:'Online Book Shopping'
}
},
methods: {
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();
}
return response;
}).catch(error => {
alert("invalid credentials");
return error;
})
}
}
}
</script>
<style lang="scss" scoped>
#import "#/styles/Register.scss";
</style>
Login.vue
<template>
<div class="main">
<div 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" id="login" #click="isLogin = true">Login</h5>
<h5 class="signup" id="signup" #click="isLogin = false">signup</h5>
</div>
<form ref="myForm">
<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="forget-section">
Forgot-password
</div>
<div class="btn-section">
<button type="submit" class="login-btn">Login</button>
</div>
<div class="seperator">
<h5><span>OR</span></h5>
</div>
<div class="btn-groups">
<button type="button" class="btn btn-primary">Facebook</button>
<button type="button" class="btn btn-light">Google</button>
</div>
</form>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'Register',
data() {
return {
password_type: "password",
isPasswordVisible: false,
}
},
methods: {
togglePassword() {
this.password_type = this.password_type === 'password' ? 'text' : 'password'
this.isPasswordVisible = !this.isPasswordVisible
}
}
}
</script>
<style lang="scss" scoped>
#import "#/styles/Login.scss";
</style>
Maybe I understood the question wrong. But you just want the user to be able to go to the registration page when on /login and the other way around.
You could just add add link in case you are using regular router.
<router-link to="/login">
<h5 class="signin" id="login" #click="isLogin = true">Login</h5>
</router-link>
<router-link to="/register">
<h5 class="signup" id="signup" :class="{ active: !isLogin }" #click="isLogin = false">signup</h5>
</router-link>
Use vue router https://router.vuejs.org/
Create a parent component LoginRegister.vue and include both of them in it
<template>
<div>
<login-form v-if="tab === 'login'" />
<register-form v-if="tab === 'register'" />
<button #click="tab = tab === 'register' ? 'login' : 'register'">Login/Register</button?
</div>
</template>
<script>
import LoginForm from "#/LoginForm";
import RegisterForm from "#/RegisterForm";
export default {
components: {
LoginForm,
RegisterForm,
},
data() {
return {
tab: 'login',
}
}
You could also have the buttons in the child components and use $emit to change the tab
There is a form on angular 8
my-form.component.html
<div class="container">
<form novalidate [formGroup]="registrationForm">
<div class="form-group">
<label for="firstName">Имя:</label>
<input #spy required pattern=[A-Za-zА-Яа-яЁё]{2,} name="firstName" id="firstName" type="text" class="form-control" formControlName="firstName">
</div>
<div class="form-group">
<label for="lastName">Фамилия:</label>
<input #spy required pattern=[A-Za-zА-Яа-яЁё]{2,} name="lastName" id="lastName" type="text" class="form-control" formControlName="lastName">
</div>
<div class="form-group">
<label for="email">E-mail:</label>
<input #spy required email name="email" id="email" type="email" class="form-control" formControlName="email">
</div>
<!--{{ spy.className }}-->
<button type="submit" class="btn btn-succes" (click)="submit(myForm)">Отправить</button>
</form>
When the user writes data, the submit button should send data to the API using the POST method.
If you need any code, leave a comment
ts code:
import { FormGroup, FormControl } from '#angular/forms';
import {HttpClient} from '#angular/common/http';
#Component({
selector: 'app-my-form',
templateUrl: './my-form.component.html',
styleUrls: ['./my-form.component.css']
})
export class MyFormComponent implements OnInit {
registrationForm: FormGroup;
constructor() { }
ngOnInit() {
this.registrationForm = new FormGroup({
firstName: new FormControl(),
lastName: new FormControl(),
email: new FormControl()
});
}
}```
i have simple example for you....
reference
----html----
<header class="masthead">
<div class="container h-100">
<div class="row h-100 align-items-center justify-content-center">
<div class="col-6">
<div class="text-center">
<hello name="{{ name }}"></hello>
<hr>
</div>
<form #send="ngForm" (ngSubmit)="sendFRMData(send.value)">
<div class="form-group">
<label for="title" class="text-muted">Title</label>
<input type="text" class="form-control" id="title"
name="titlefrm" ngModel #title='ngModel' required>
<span class="help-block text-danger" *ngIf="!title.valid &&
title.touched">Please give Title!!</span>
</div>
<div class="form-group">
<label for="body" class="text-muted">Body</label>
<input type="text" class="form-control" id="body" name="bodyfrm" ngModel
#body='ngModel' required>
<span class="help-block text-danger" *ngIf="!body.valid &&
body.touched">Please
give Body!!</span>
</div>
<div class="form-group">
<label for="userId" class="text-muted">UserID</label>
<input type="text" class="form-control" id="userId" name="userIdfrm" ngModel
#userid='ngModel' required>
<span class="help-block text-danger" *ngIf="!userid.valid &&
userid.touched">Please give UserID!!</span>
</div>
<div class="row">
<div class="col-sm-6">
<input class="form-control btn btn-success" type="submit"
[disabled]='!send.valid'>
</div>
<div class="col-sm-6">
<input class="form-control btn btn-info" type="button" value="EDIT"
(click) = 'onEdit()'>
</div>
</div>
</form>
</div>
</div>
</div>
</header>
----ts----
import { NgForm } from '#angular/forms';
#ViewChild('send') send: NgForm;
constructor(private sendData: HttpService) {
}
sendFRMData(data: any) {
const payload = {
title: data.titlefrm,
body: data.bodyfrm,
userId: data.userIdfrm
}
this.sendData.try(payload).subscribe(
(data: any) => {
this.respondedData = JSON.stringify(data);
this.alert = true;
}
);
}
----service----
try(data){
return
this.http.post('https://jsonplaceholder.typicode.com/posts',data,{
headers: {
"Content-type": "application/json; charset=UTF-8"
}
});
}
hope you get your answer...
Seems like you are not able to get form values in your submit function.
change your click event from (click)="submit(myForm)" to (click)="submit(myForm.value)" then in your submit function you can call post method
submit(formValueObject) {
console.log(formValueObject);
this.httpService.post(url, formValueObject).subscribe((res:any)=> {
//your response
})
}
I hope it helps
Im trying to pass some data from a parent component to a child component which is a modal. For some reason, the error thrown to me is "Uncaught TypeError: Cannot set property 'domain' of undefined". I am trying to pass through the parent component item with its key and then finding this element in the parent and then to a data variable in the child component. Can someone give me a clue on what im missing? Thank you!
This is my parent component Domain.vue
<template>
<div class="container">
<div class="form-group">
<input type="text" class="form-control" id="filter" placeholder="Filter the Domains">
</div>
<div class="row content-holder">
<table>
<thead>
<tr>
<th class="client-name">Domain</th>
<th class="client-pm">Client</th>
<th class="client-pm">Add Log on Domain</th>
</tr>
</thead>
<tbody>
<tr v-for="domain in domains" :key="domain.id" :domain="domain" class="tr-table">
<td class="client-name">{{ domain.url }}</td>
<td class="client-pm">{{ domain.client }}</td>
<td class="client-pm center"><i class="fas fa-plus jobs-page" data-toggle="modal" #click="openAdd(domain)"></i></td>
</tr>
</tbody>
</table>
</div>
<Add :openmodal="addActive" #closeRequest='close'></Add>
</div>
</template>
<script>
import axios from 'axios';
let Add = require('./Add.vue');
export default {
name:'Domain',
data(){
return {
addActive:'',
domains: [],
domain: {id:'', url:'', client: ''},
errors:{}
}
},
methods:{
getDomains(){
window.axios.get('/develogger-app/public/api/domains').then(({data})=>{
data.forEach(domain =>{
this.domains.push(domain)
});
});
},
openAdd(key){
this.$children[1].domain = this.domains[key];
this.addActive = 'is-active';
},
save(){
},
close(){
this.addActive = '';
},
},
created(){
this.getDomains();
},
components:{
Add
}
}
</script>
This is Child component Add.vue
<template>
<!-- Modal -->
<div :class="openmodal" class="modal fade" id="exampleModalCenter" tabindex="-1" >
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Create new Log</h5>
<button type="button" class="close">
<i class="fas fa-times" #click="close"></i>
</button>
</div>
<div class="modal-body">
<form method="post">
<input type="hidden" name="_token" :value="csrf">
<input name="website" type="text" id="website" class="form-control" placeholder="Log Title"><br>
<select id="type" class="form-control" name="type"><br>
<option></option>
</select>
<br>
<select id="type" class="form-control" name="type"><br>
<option value="" disabled selected>Type</option>
<option>Client Update</option>
<option>Dev Update</option>
<option>Bug</option>
<option>Style Fix</option>
</select>
<br>
<label class="left" for="description">Log Description:</label>
<textarea class="form-control" rows="5" id="description" name="description"></textarea>
<br>
<div class="left">
<input type="checkbox" name="tell-everyone" id="tell-everyone">
<label for="description">Tell Everyone?</label>
<br>
<input type="checkbox" name="status" id="status" value="checked">
<label for="checked">Resolved and Tested?</label>
</div>
</form>
</div>
<div class="modal-footer">
<button id="log-it" type="button" class="btn btn-circle btn-xl" data-dismiss="modal">
<span id="button-content"><b>LOG IT</b></span>
<span id="button-content"><b>FIX IT</b></span>
</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
// checked:false,
name:'Add',
props:['openmodal'],
data(){
return{
domain:'',
csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
}
},
methods:{
close(){
this.$emit('closeRequest');
}
},
// computed: {
// isComplete () {
// return this.log.title && this.log.domain_id && this.log.type && this.log.description;
// }
// },
}
</script>
You are specifying your data as a function in the main Vue instance. It should be
an object in the main Vue instance:
data: {
....
}
while a function in the component:
data() {
return {...}
}
See the official reference.
You have data as function for both.
In my Vue.js frontend app I wanted to create form to POST json data to REST API. The form has one part where I GET json data from API which is list of possible to add groups.
Vue.js code looks like
<script>
export default {
data () {
return {
line: {
name: '',
buttons: [{
name: '',
state: false,
is_reported: '',
assignmentGroups: [{
name: ''
}]
}]
},
assignmentGroupsList: []
}
},
methods: {
addButton () {
this.line.buttons.push({
name: '',
state: false,
is_reported: ''
})
},
deleteButton (index) {
this.line.buttons.splice(index, 1)
},
saveLine () {
// this.$http.post('http://127.0.0.1:8001/api/line')
// .then(response => response.json())
// .then(result => this.lines = result)
console.log(JSON.stringify(this.line))
},
fetchAssignmentGroups() {
this.$http.get('http://127.0.0.1:8001/api/agroup')
.then(response => response.json())
.then(result => this.assignmentGroupsList = result)
.then(result => console.log(result))
}
},
created: function () {
this.fetchAssignmentGroups();
//this.fetchLines();
}
}
</script>
and template
<template>
<div>
<div id="page-wrapper">
<div class="row">
<div class="col-lg-12">
<div class="form">
<div class="form-group">
<label for="name">Line name</label>
<input v-model="line.name" class="form-control" type="text" id="name" name="name"/>
</div>
<label for="">Buttons</label>
<div class="" v-for="(button, index ) in line.buttons">
<div class="form-group">
<label for="btn">Przycisk nr {{ index }}</label>
<input v-model="button.name" class="form-control col-lg-3" type="text" id="btn" name="btn" />
<input type="radio" id="'one' + index" :value="false" v-model="button.is_reported">
<label for="one">No</label>
<input type="radio" id="'two' + index" :value="true" v-model="button.is_reported">
<label for="two">Yes</label>
</div>
<div class="form-group">
<div class="" v-for="(agroup, index2) in assignmentGroupsList">
<input type="checkbox" :name="'agroup'+index2" :value=" agroup.name " v-model="button.assignmentGroups">
<label for="">{{ agroup.name }}</label>
</div>
</div>
<button class="btn btn-danger"
#click="deleteButton(index)">
Remove
</button>
</div>
<div class="form-group">
<button class="btn btn-success"
#click="addButton">
Add
</button>
<button class="btn btn-primary"
#click="saveLine">
Save
</button>
</div>
</div>
<!-- /.col-lg-12 -->
</div>
<!-- /.row -->
</div>
</div>
</div>
</template>
In browser I can see correctly list of groups in every added button but its all. It doesn't get data.
I am getting up the details in a form for a hotel entry with basic details and viewing it in Room.vue. The created values were displayed here but here i need to give edit option for the filled details. When i click the edit, the page should redirect to RoomsEdit.vue and i should get the filled up contents in that page with form inputs. For that i have tried the following codes but nothing solves my issue.. Kindly have a go through and help me in solving the issue.
Room.vue:
<table class="table table-striped table-hover rooms-table">
<thead>
<tr>
<td>Title<i class="fa fa-sort"></i></td>
<td>Sub Title<i class="fa fa-sort"></i></td>
<td> Edit </td>
<td> Delete </td>
</tr>
</thead>
<tbody>
<tr v-for="room in items">
<td>{{ room.title }}</td>
<td>{{ room.subtitle }}</td>
<td>
<router-link class="btn btn-primary" v-bind:to="'rooms/edit/'+id">Edit</router-link>
</td>
<td>
<button class="btn btn-primary" v-on:click="deleteRoom(room)">Delete</button>
</td>
</tr>
</tbody>
</table>
Here i am giving edit option and making a redirect to edit page..
Script of Rooms.vue:
<script>
import config from '../../../config';
export default {
data(){
return{
items: [],
itemsData:{
title : '',
subtitle : '',
}
}
},
methods: {
deleteRoom: function (room) {
var index = this.items.indexOf(room);
this.items.splice(index, 1);
}
},
mounted() {
axios.get(config.apiDomain+'/Rooms').then((response)=>this.items = response.data);
}
}
</script>
RoomsEdit.vue:
<form #submit.prevent="updateItems" class="form-horizontal" enctype="multipart/form-data">
<div class="form-group">
<label for="title" class="col-sm-2 control-label">Title<span class="red">*</span></label>
<div class="col-sm-6">
<input type="text" name="title" class="form-control" id="title" v-model="itemsData.title">
<span class="text-danger">{{ errors.title?errors.title[0]:"" }}</span>
</div>
</div>
<div class="form-group">
<label for="subtitle" class="col-sm-2 control-label">Subtitle<span class="red">*</span></label>
<div class="col-sm-6">
<input type="text" name="subtitle" class="form-control" id="subtitle" v-model="itemsData.subtitle">
<span class="text-danger">{{ errors.subtitle?errors.subtitle[0]:"" }}</span>
</div>
</div>
</form>
Script of RoomsEdit:
<script>
import config from '../../../config';
export default {
data(){
return{
items: [],
itemsData:{
title : '',
subtitle : '',
},
errors: {
}
}
},
methods:{
fetchRoom(id){
axios.get(config.apiDomain+'/Rooms').then((response)=>this.items = response.data);
},
updateItems(e){
axios.put(config.apiDomain+'/Rooms/edit'+this.$route.params.id,this.itemsData).then(response=>{
this.this.itemsData = "";
this.$router.push('/admin/rooms');
}).catch(error=>{
this.errors = error.response.data;
});
}
},
created: function() {
this.fetchRoom(this.$route.params.id);
}
}
</script>
RoomsCreate.vue:
<form #submit.prevent="addItems" class="form-horizontal" enctype="multipart/form-data">
<div class="form-group">
<label for="title" class="col-sm-2 control-label">Title<span class="red">*</span></label>
<div class="col-sm-6">
<input type="text" name="title" class="form-control" id="title" v-model="itemsData.title">
<span class="text-danger">{{ errors.title?errors.title[0]:"" }}</span>
</div>
</div>
<div class="form-group">
<label for="subtitle" class="col-sm-2 control-label">Subtitle<span class="red">*</span></label>
<div class="col-sm-6">
<input type="text" name="subtitle" class="form-control" id="subtitle" v-model="itemsData.subtitle">
<span class="text-danger">{{ errors.subtitle?errors.subtitle[0]:"" }}</span>
</div>
</div>
Script of RoomsCreate.vue:
<script>
import config from '../../../config';
export default {
data(){
return{
items: [],
itemsData:{
title : '',
subtitle : '',
},
errors: {
}
}
},
methods:{
addItems(){
axios.post(config.apiDomain+'/Rooms',this.itemsData).then(response=>{
this.this.itemsData = "";
this.$router.push('/admin/rooms');
}).catch(error=>{
this.errors = error.response.data;
});
}
}
</script>
The issue i am facing is when i click the edit in Room.vue, it redirects to the RoomsEdit.vue where i am not getting the values that was already created, i need to get those value when i go to RoomsEdit.vue there i should edit and update the content.