How To Submit Form Data From B-modal In Vue - forms

So I am having a issue trying to submit form data from a b-modal in my Vue component. I can see in my dev tools that the data object is being populated with the data however when I submit my form It doesn't send my data.
here is the form
<b-modal v-model="modalShow" id="myModal">
<form>
<div>
<br>
<input type="text" placeholder="Name" v-model="user.name">
<br>
<input type="text" placeholder="Email" v-model="user.email">
<br>
<input type="text" placeholder="Password" v-model="user.password">
<br>
</div>
<div>
<b-btn #click="modalShow = false">Cancel</b-btn>
<b-btn variant="outline-primary" #click="addUser">Create</b-btn>
</div>
</form>
</b-modal>
Here is the data object and method from the component
data() {
return {
modalShow: false,
user: {
name: '',
email: '',
password: '',
}
}
},
components:{
'b-modal': bModal,
},
directives: {
'b-modal': bModalDirective
},
computed: {
...mapGetters(['users']),
},
methods: {
addUser() {
this.$store.dispatch('addUser', {
name: this.user.name,
email: this.user.email,
password: this.user.password,
})
}
},
and here is the store method being dispatched
addUser(user) {
return new Promise((resolve, reject) => {
axios.post('/register', {
name: user.name,
email: user.email,
password: user.password,
})
.then(response => {
console.log(response)
resolve(response)
})
.catch(error => {
reject(error.response.data)
})
})
},
if I do a return response before processing the data on my back end it shows a empty data object. any ideas why?

The first argument in vuex action is context object, the payload is passed as the second argument
addUser(context, user) {
return new Promise((resolve, reject) => {
axios.post('/register', {
name: user.name,
email: user.email,
password: user.password,
})
.then(response => {
console.log(response)
resolve(response)
})
.catch(error => {
reject(error.response.data)
})
})
}

Related

Preset input values of the form with Vuex

In my project (laravel/vue spa) I have a form opened in a modal window, the form shall display the initial values from the object kept in the vuex store. The problem is the input doesn't see objet property that I set through value, so with my code now when the modal is opened, no data is displayed inside the input, although if i output the section object in the markup it generally sees it.
How can I make the input work with the preset values?
Here's my code:
ModalForm.vue markup
<template>
<app-modal>
<Form #submit="submitSectionForm">
<div class="form-group">
<label for="title" class="control-label">Title</label>
//<p>{{ section }}</p>
<Field
:value="sectionTitle" #input="handleUpdateTitle"
:rules="isRequired"
type="text"
name="section_title"
class="form-control"
/>
<ErrorMessage
name="section_title"
class="pr-1 display-block color-red"
/>
</div>
<button class="btn btn-default" #click="closeModal">Cancel</button>
<button class="btn btn-primary ml-1">Ok</button>
</Form>
</app-modal>
</template>
ModalForm.vue functionality
<script>
import AppModal from "../../components/Modals/Modal.vue";
import { Field, ErrorMessage } from "vee-validate";
import { mapGetters, mapActions, mapState, mapMutations } from "vuex";
export default {
props: {
menu_type_id: Number,
menu_id: Number,
},
components: {
AppModal,
Field,
ErrorMessage,
},
methods: {
...mapActions("menu_sections", ["saveSection"]),
...mapMutations("menu_sections", ['updateTitle']),
isRequired(value) {
if (value && value.trim()) {
return true;
}
handleUpdateTitle(e) {
this.updateTitle(e.target.value);
}
submitSectionForm(value) {
console.log(value);
this.saveSection(value);
this.closeModal();
},
computed: {
...mapGetters("menu_sections", { section: "getSection" } ),
...mapGetters("menu_sections", { sectionTitle: "getSectionTitle" }),
},
};
</script>
section_store.js
import axios from "axios";
export default {
namespaced: true,
state: {
section: {},
message: "",
},
getters: {
indexById: (state) => (id) =>
state.sections.findIndex((item) => item.id == id),
sectionById: (state) => (id) =>
state.sections.filter((item) => item.id == id),
getSection: (state) => state.section,
getSectionTitle: (state )=>state.section.title
},
mutations: {
setSection(state, section) {
state.section = { ...section };
},
saveSection(state, data) {
state.message = data.message;
},
updateTitle(state, title) {
state.section.title = title;
console.log(state.section.title);
},
},
actions: {
saveSection({ commit }, section_object) {
axios
.post("/api/menu-sections/" + section_object)
.then((response) => {
commit("saveSection", response.data);
})
.catch((e) => {
console.log("Section save error");
});
}
},
};

Clear form after submitting with vuex

I am trying to clear a form after I submit it, in this case creating a simple user. I am resetting the state with vuex (see below). But the form stays with data.
this is how the form looks like
<form #submit.prevent="onSubmit" v-if="!loading">
<div class="form-group">
<input placeholder="Name" v-model="user.name" type="text" name="name" class="form-control">
<span class="invalid-feedback" v-if="errors.name">{{ errors.name }}</span>
</div>
<div class="form-group">
<input v-bind:class="{ harError: errors.email }" placeholder="Email" v-model="user.email" type="email" name="email" class="form-control" id="validationCustom03">
<span class="invalid-feedback" v-if="errors.email">{{ errors.email }}</span>
</div>
...
the onSubmit method
/**
* on submitting the form update or crete a user
*/
onSubmit() {
let action = this.id ? 'UPDATE_USER' : 'CREATE_USER';
this.inProgress = true;
this.$store
.dispatch(action)
.then(() => {
console.log('reset or not?');
this.inProgress = false;
// navigate to user
this.$router.push('users');
})
.catch( ({ response }) => {
this.inProgress = false;
this.errors = response.data.errors;
console.log('you have an error on creating an user')
});
},
Resetting the
RESET_STATE({state}) {
console.log('reset state');
for (let f in state) {
Vue.set(state, f, initialState[f]);
}
},
the state like this
const initialState = {
users: [],
user: {
name: '',
email: '',
password: '',
type: '',
bio: '',
photo: '',
active: '1',
},
loading: false,
};
export const store = new Vuex.Store({
namespaced: true,
state: { ...initialState },
...
The input types stais with data
Ok At least I figured out myself, Insead of a const I used a function to set the initialtState like so
function initialState () {
return {
users: [],
user: {
name: '',
email: '',
password: '',
type: '',
bio: '',
photo: '',
active: '1',
},
loading: false,
}
}
export const store = new Vuex.Store({
namespaced: true,
state: { ...initialState() },
then in the mutations i assigned the intitialState to the state
mutations: {
/**
*
* #param state
* #constructor
*/
RESET_STATE: (state) => {
Object.assign(state, initialState())
},
in my user component I dispached it like so
...mapActions(['RESET_STATE']),
...
this.$store.dispatch("RESET_STATE");

The API request from the Vuejs component is executed twice

I am creating To-do Application using Vuejs, Expressjs, and Mongodb.
I have already written through the New Component with a separate link. This is normal, but I am currently using the New Component by importing it into the Root Component without any additional links.
This works, but the API request is executed twice. (Two articles are written.)
I just imported the component, what's the problem?
I have only sent one request but strangely two responses are flying. (id is different, title and content are the same.)
frontend/components/TodoForm.vue
<template>
<form #submit.prevent="create">
title : <input v-model="todo.title">
content : <input v-model="todo.content">
<button v-on:click="create" >Create</button>
</form>
</template>
<script>
export default {
data: function () {
return {
todo: {}
}
},
methods: {
create: function() {
this.$http.post('/api/todos/create', this.todo)
.then(
(response) => {
console.log(response.data)
this.$router.push({name: 'Todo', params: { id: response.data._id }})
},
(err) => {
alert('Error')
}
)
.catch(function (error) {
alert('error')
})
}
}
}
</script>
fromtend/components/TodoList.vue
<template>
<todo-form/>
<div class="todos">
<h1>Todos</h1>
<div v-for="todo in todos" v-bind:key="todo" class="todo">
<div>
<strong>{{todo.title}}</strong>
<router-link :to="{ name: 'Todo', params: { id: todo._id }}">detail</router-link>
<router-link :to="{ name: 'Edit', params: { id: todo._id }}">edit</router-link>
<button type="submit" #click="deleteTodo(todo._id)">Delete</button>
</div>
</div>
</div>
</template>
<script>
import TodoForm from './TodoForm';
export default {
data () {
return {
todos: {}
}
},
created () {
this.$http.get('/api/todos')
.then((response) => {
this.todos= response.data
})
},
components: {
TodoForm
},
methods: {
deleteTodo (id) {
const targetIndex = this.todos.findIndex(v => v._id === id)
this.$http.delete(`/api/todos/${id}`)
.then((response) => {
this.todos.splice(targetIndex, 1)
})
}
}
}
</script>
backend/api
router.post ('/create', (req, res) => {
let todo = new Todo({
title: req.body.title || req.body.todo.title,
content: req.body.content || req.body.todo.content
});
todo.save((err) => {
if (err) {
res.status(500).send('Something broke!');
}
res.json(todo)
});
});
Try to change the following code :
<template>
<form>
title : <input v-model="todo.title">
content : <input v-model="todo.content">
<button v-on:click.once="create" >Create</button>
</form>
</template>

How do I clear the input values in a react form?

In my code I have mention preventDefault method on onSubmit event and due to that my page is not getting reload when user enter data in form...
Can you tell me any way by which I can export data to firebase and also reload my page automatically!
Here is the code:
import React, { Component } from 'react';
const firebase = require('firebase');
const uuid = require('uuid');
var config = {
apiKey: "AIzaSyAtpOSiCqFy43ZTE-7CJdcHrIGNN1GrsSk",
authDomain: "electronic-health-record-a795c.firebaseapp.com",
databaseURL: "https://electronic-health-record-a795c.firebaseio.com",
projectId: "electronic-health-record-a795c",
storageBucket: "electronic-health-record-a795c.appspot.com",
messagingSenderId: "545743770560"
};
firebase.initializeApp(config);
class Usurvey extends Component {
constructor(props) {
super(props);
this.state = {
uid: uuid.v1(),
firstName: '',
lastName: '',
};
this.submitData = this.submitData.bind(this);
this.inputData = this.inputData.bind(this);
}
componentDidMount() {
firebase
.database()
.ref(`Newdata/${this.state.uid}`)
.on('value', snap => console.log('from db', snap.val()));
}
submitData(event) {
event.preventDefault();
firebase
.database()
.ref(`Newdata/${this.state.uid}`)
.set({
firstName: this.state.firstName,
lastName: this.state.lastName,
})
.catch(error => console.log(error));
}
inputData(event) {
const firstName = this.refs.name1.value;
const lastName = this.refs.name2.value;
this.setState({ firstName, lastName });
}
render() {
return (
<div>
<form onSubmit={this.submitData}>
<input type="text" onChange={this.inputData} ref="name1" />
<input type="text" onChange={this.inputData} ref="name2" />
<input type="submit" />Submit
</form>
</div>
);
}
}
export default Usurvey;
This is how it should be
class Usurvey extends Component {
constructor(props) {
super(props);
this.state = {
uid: uuid.v1(),
firstName: '',
lastName: '',
};
this.submitData = this.submitData.bind(this);
this.inputData = this.inputData.bind(this);
}
componentDidMount() {
firebase
.database()
.ref(`Newdata/${this.state.uid}`)
.on('value', snap => console.log('from db', snap.val()));
}
submitData(e) {
const { firstName, lastName } = this.state;
e.preventDefault();
firebase
.database()
.ref(`Newdata/${this.state.uid}`)
.set({
firstName: firstName,
lastName: lastName,
})
.catch(error => console.log(error));
this.setState({
firstName: '', lastName: ''
});
}
inputData(e) {
this.setState({ [e.target.name]: e.target.value });
}
render() {
return (
<div>
<form onSubmit={this.submitData}>
<input type="text" value={this.state.firstName} onChange={this.inputData} name="firstName" />
<input type="text" value={this.state.lastName} onChange={this.inputData} name="lastName" />
<button type="submit">Submit</button>
</form>
</div>
);
}
}
export default Usurvey;
You directly update your state as the user inputs in the form, also on your submission you reset your form, so the user can add more information in the form.
If you want to upload your data and reload after it has finished you can do sth like this:
submitData(event) {
event.preventDefault();
firebase
.database()
.ref(`Newdata/${this.state.uid}`)
.set({
firstName: this.state.firstName,
lastName: this.state.lastName,
})
.then(() => {
location.reload();
// or window.location.reload() if location is undefined
})
.catch(error => console.log(error));
}

react.js - show a message on and after form submission

On submitting the form, I want to show 'Please wait ..' and on successful submission the data returned from server. Using jQuery , it is easy to do. But there should be a React way as React does not like such kind of direct DOM manipulation - I think . 1) Am I right ? 2) How to show the message on (not after ) form submission?
var FormComp = React.createClass({
handleSubmit:function(){
var userName=this.refs.userName.getDOMNode().value.trim();
var userEmail= this.refs.userEmail.getDOMNode().value.trim();
if(!userName || !userEmail){
return;
}
this.props.onFormSubmit({userName:userName, userEmail:userEmail,url:"/api/submit"});
this.refs.userName.getDOMNode().value='';
this.refs.userEmail.getDOMNode().value='';
return;
},
render: function() {
var result=this.props.data;
return (
<div className={result}>{result.message}</div>
<form className="formElem" onSubmit={this.handleSubmit}>
Name: <input type="text" className="userName" name="userName" ref="userName" /><br/>
Email: <input type="text" className="userEmail" name="userEmail" ref="userEmail" /><br/>
<input type="submit" value="Submit" />
<form >
</div>
);
}
});
var RC= React.createClass({
getInitialState: function() {
return {data: ""};
},
onFormSubmit:function(data){
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'POST',
data: data,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
render:function(){
return <FormComp onFormSubmit={this.onFormSubmit} data={this.state.data}/>
}
});
React.render(
<RC/>,
document.getElementById('content')
);
This is definitely something React can handle, no direct DOM manipulation is needed. You're almost there, just need to reorganize a little. Here's one way to approach this (with comments around important changes):
var FormComp = React.createClass({
// To get rid of those input refs I'm moving those values
// and the form message into the state
getInitialState: function() {
return {
name: '',
email: '',
message: ''
};
},
handleSubmit: function(e) {
e.preventDefault();
var userName = this.state.name.trim();
var userEmail = this.state.email.trim();
if(!userName || !userEmail) return;
this.setState({
name: '',
email: '',
message: 'Please wait...'
});
// I'm adding a callback to the form submit handler, so you can
// keep all the state changes in the component.
this.props.onFormSubmit({
userName: userName,
userEmail: userEmail,
url: "/api/submit"
}, function(data) {
this.setState({ message: data });
});
},
changeName: function(e) {
this.setState({
name: e.target.value
});
},
changeEmail: function(e) {
this.setState({
email: e.target.value
});
},
render: function() {
// the message and the input values are all component state now
return (
<div>
<div className="result">{ this.state.message }</div>
<form className="formElem" onSubmit={ this.handleSubmit }>
Name: <input type="text" className="userName" name="userName" value={ this.state.name } onChange={ this.changeName } /><br />
Email: <input type="text" className="userEmail" name="userEmail" value={ this.state.email } onChange={ this.changeEmail } /><br />
<input type="submit" value="Submit" />
</form>
</div>
);
}
});
var RC = React.createClass({
onFormSubmit: function(data, callback){
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'POST',
data: data,
success: callback,
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
render: function() {
return <FormComp onFormSubmit={this.onFormSubmit} />
}
});
React.render(
<RC />,
document.getElementById('content')
);