I want to implement Save and Edit at same page. Of course, i have alot of field input so, i can Input a few input field and save Without Rediect to another page.
What i want is get current id after POST Request so, i can use That ID to PATCH request.
Vuejs Code
<v-btn
color="primary"
v-if="isEdit === false"
small
:loading="loading"
#click="save"
>save</v-btn
>
<v-btn
color="primary"
small
:loading="loading"
#click="edit"
v-if="isEdit === true"
>edit</v-btn
>
In script
<script>
export default {
data() {
return {
form: {},
isEdit: false
}
},
save() {
this.loading = true;
axios
.post(`api/v1/partner/`, this.form)
.then((res) => {
console.log(res);
this.isEdit = true;
})
.catch((err) => {
console.log(err.response);
this.loading = false;
this.snackbar.value = true;
this.$refs.form.validate(err.response.data);
});
},
edit() {
this.isEdit = true;
axios
.patch(`api/v1/partner/${this.form.id}/`, {
})
.then((res) => {
console.log(res);
// this.$router.push(`/partner/`);
this.loading = false;
})
.catch((err) => {
console.log(err.response);
this.loading = false;
});
},
}
</script>
I'll appreciate of all ur Help. Thanks...
Assuming your API responds from the POST request with the new ID, you can simply set it to your form object
axios.post("api/v1/partner/", this.form)
.then(res => {
console.log(res)
this.isEdit = true
this.form.id = res.data.id // assuming that's the right property name
})
Related
I have a page in NextJS for editing an sql row and sending it back. I have fetched all the rows from the table and then have set the state to be the single row which matches the query parameter in the useRouter hook. Now, after I have edited the data in the row, what is a good way to POST it back to the backend?
Below is my React code:
import { React, useEffect, useState } from "react";
import { useRouter } from "next/dist/client/router";
const axios = require("axios");
export default function Edit() {
const [data, setData] = useState([]);
const router = useRouter();
const onSubmitHandler = (e) => {
e.preventDefault();
axios.post("/api/cards", data);
};
useEffect(() => {
const fetchData = async () => {
await axios
.get("/api/cards")
.then((res) => {
if (res.data) {
res.data.map((element) => {
if (element.ID == router.query.card) {
setData(element);
return;
}
return;
});
}
})
.catch((err) => {
console.log(err);
});
};
if (router.isReady) {
fetchData();
}
}, [router.isReady, router.query.card]);
return (
<form onSubmit={onSubmitHandler}>
<label htmlFor="front">Front</label>
<input
defaultValue={data.Front}
id="front"
onChange={(e) => setData({ ...data, Front: e.target.value })}
></input>
<label htmlFor="back">Back</label>
<input
defaultValue={data.Back}
id="back"
onChange={(e) => setData({ ...data, Back: e.target.value })}
></input>
<button type="submit">Add Word</button>
</form>
);
}
Below is my backend code
if (req.method === "POST") {
const { front, back, type } = req.body.data;
const id = uuidv4();
db.query(
`INSERT INTO deck VALUES('${front}', '${back}', '${type}', '${id}')`,
(err, rows, fields) => {
if (!err) {
res.json(rows);
} else {
console.log(err);
}
}
);
}
Its good to post the edited data after submiting the form..
const onSubmitHandler = async (e) => {
e.preventDefault();
try {
await axios.post("/api/cards", data);
// react-toast or something like that to indicate the ui the form is updated
// then the control flow of the application
} catch (error){
console.error(error)
}
};
One thing I notice over here is you're using POST for the update. Try HTTP PUT instead of POST.
And regarding your answer: You can send modified data in your API call like you're already maintaining the state of the updated data. Then you can just send that row to the API call and handled that in your backend code.
const onSubmitHandler = (e) => {
e.preventDefault();
axios.put("/api/cards/:id", data); // modify the API URL and append dynamic ID of the record.
};
This is my code in App.js, and its always returning an "Unhandeled Rejection Type error saying that ipfs.add(...). then is not a function.
import React, { Component } from 'react';
import './App.css';
var ipfsAPI = require('ipfs-http-client')
var ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol:'http'})
class App extends Component {
saveTestBlobOnIpfs = (blob) => {
return new Promise(function(resolve, reject) {
const descBuffer = Buffer.from(blob, 'utf-8');
ipfs.add(descBuffer).then((response) => {
console.log(response)
resolve(response[0].hash);
}).catch((err) => {
console.error(err)
reject(err);
})
})
}
render() {
return (
<div className="App">
<h1>IPFS Pool</h1>
<input
ref = "ipfs"
style = {{width: 200, height: 50}}/>
<button
onClick = {() => {
console.log("Upload Data to IPFS");
let content = this.refs.ipfs.value;
console.log(content);
this.saveTestBlobOnIpfs(content).then((hash) => {
console.log("Hash of uploaded data: " + hash)
});
}}
style = {{height: 50}}>Upload Data to IPFS</button>
</div>
);
}
}
export default App;
Do I need to add an async function or something, I'm fairly new to js so any help would greatly appreciated. I just don't know how to change the ipfs.add to make my code work.
I have also followed the same tutorial and ran into the same problem. The ipfs.add function does not accept a call function anymore. More information on that here: https://blog.ipfs.io/2020-02-01-async-await-refactor/
The solution is turn your saveTestBlobOnIpfs function into an async/await function. Like this:
saveTestBlobOnIpfs = async (event) => {
event.preventDefault();
console.log('The file will be Submitted!');
let data = this.state.buffer;
console.log('Submit this: ', data);
if (data){
try{
const postResponse = await ipfs.add(data)
console.log("postResponse", postResponse);
} catch(e){
console.log("Error: ", e)
}
} else{
alert("No files submitted. Please try again.");
console.log('ERROR: No data to submit');
}
}
So I am making a ToDo app but so far I can just create a task, or delete it. Right now I am trying to make another feature where I can edit the specific task by clicking the edit button and then it will change the task into an input area where i can edit the task name. Can someone help me with this? How it looks right now is displayed below.
My Code right now is below:
import React, { Component } from 'react';
import axios from "axios";
export default class TaskInput extends Component {
constructor(props) {
super(props)
this.state = {
task: " ",
allTasks: [],
strikeThrough: {textDecoration:""}
}
}
changeHandler = (event) => {
console.log(event.target.value)
this.setState({
task: event.target.value,
})
}
handleStrikethrough = (completed, id) => {
// !completed ? this.setState({strikeThrough:{textDecoration: "line-through"}}) : this.setState({strikeThrough:{textDecoration:""}})
// if (!completed) {
// console.log("not completed", !completed)
// this.setState({strikeThrough:{textDecoration: "line-through"}});
// axios.put("/api/task", {
// completed: !completed
// }, id).then(response => console.log(response))
// } else {
// this.setState({strikeThrough:{textDecoration:""}})
// axios.put("/api/task", {
// completed: !completed
// }, id).then(response => console.log(response))
// }
}
handleDelete = (taskId) => {
axios.delete("/api/task/" + taskId).then(data => {
console.log("You deleted the task with an id of ", data)
})
window.location.reload();
}
handleTaskEdit = () => {
console.log("edit button worked")
}
submitHandler = (event) => {
event.preventDefault() //to prevent page refresh
console.log()
fetch("/api/task", {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(this.state),
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.log(err))
this.setState({
task: ""
})
window.location.reload()
}
componentDidMount() {
console.log("component did mount")
const self = this;
axios.get("/api/tasks").then(function (data) {
self.setState({
allTasks: data.data
})
// console.log(self.state.allTasks[0].task)
})
}
render() {
const {strikeThrough, task, allTasks} = this.state; //destructuring the state
return (
<div>
<form onSubmit={this.submitHandler} >
<label style={{ margin: "5px 0px" }}>Create a Task:</label>
<input value={this.state.task} onChange={this.changeHandler} style={{ width: "100%" }}></input>
<input style={{ padding: "5px", marginTop: "5px" }} type="submit"></input>
</form>
<hr></hr>
<br></br>
<ul>
{this.state.allTasks.map(task => (
<li style={strikeThrough} onClick={()=>this.handleStrikethrough(task.completed, task.id)} className="tasks">{task.task}
<button onClick = {() => this.handleDelete(task.id)}>x</button>
<button onClick={this.handleTaskEdit}>edit</button>
</li>
)
)}
</ul>
</div>
)
}
}
You could set task ID on its corresponding Edit button, then when clicking Edit button get the task using ID and sending that task to an edit component.
First of all handleTaskEdit, here you set task name to the task property and set ID of editable task:
handleTaskEdit = id =>
this.setState({ task: this.state.allTasks.find(el => el.id === id).task })
secondly, create two new methods, createTask and updateTask:
createTask = () => {
fetch("/api/task", {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({task: this.state.task}),
})
.then(res => res.json())
.then(data => this.setState({
task: '',
allTasks: [...this.state.allTasks, data]}))
.catch(err => console.log(err))
}
updateTask = () => {
fetch("/api/task", {
method: "PATCH",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({task: this.state.task, id: this.state.editableTaskId}),
})
.then(res => res.json())
.then(data => this.setState({
task: '',
editableTaskId: null,
allTasks: this.state.allTasks.map(el =>
el.id === data.id ? data : el)})) // Or take new name and id from state
.catch(err => console.log(err))
}
and finally you need to update submitHandler and handleDelete:
submitHandler = () => {
if (this.state.editableTaskId) {
this.updateTask();
} else {
this.createTask()
}
}
handleDelete = (taskId) => {
axios.delete("/api/task/" + taskId).then(data => {
this.setState({allTasks: this.state.allTasks.filter(el =>
el.id !== data.id
)})
})
}
Here's the approach:
Have a state variable called editTaskID and keep the default value as null. On the edit button set the functionality of handleTaskEdit in such a way that it sets the editTaskID to that particular task ID on which edit button was clicked.
In the map function where you are rendering the list items for tasks, add a condition such as:
{this.state.allTasks.map(task =>
(
<li style={strikeThrough}
onClick={()=>this.handleStrikethrough(task.completed, task.id)}
className="tasks">
{
this.editTaskID
?<input
value={this.state.editTaskName}
/*supposing editTaskName to be state variable that stores
the edit textfield content.*/
onChange={this.changeEditHandler} style={{ width: "80%" }}>
</input>
:task.task
}
<button onClick = {() => this.handleDelete(task.id)}>x</button>
<button onClick={this.handleTaskEdit}>edit</button>
</li>
)
)
}
This will now check the condition whether the editTaskID has been set to null or not while rendering. In case if it is null, all your tasks will come as a plain text else it will come in form of a text box. You can also add the value to the edit task input field with the help of allTasks[editTaskID].
On the handleTaskEdit function of the edit button, make sure to set the allTasks[editTaskID] to the value editTaskName and also to set the state variable editTaskID to null.
Call the necessary backend endpoint to reflect the changes in your database as well.
I hope it helps. Thanks.
I have been able to change the activation status of companies in database on onClick event of the checkbox. Now I am not able to toggle the status of the checkbox, What I am missing Here?
I have looked on various sites, but could not find the solution.
Here is my code in which i am printing the companies.
{this.state.allCompanies.map(com => (
<tr>
<td>{com.cname} </td>
<td>
<a>
<input
type="checkbox"
name="active"
checked={com.is_active == 1 ? "true" : ""}
onClick={
(() => {
this.setState({ cked: !this.state.cked });
},
e => this.handleActivated(e, com.cid))
}
/>
</a>
</td>
</tr>
))}
Here is my function.
handleActivated(e, id) {
const comid = id;
var data = {
comid: id
};
console.log(data);
fetch("http://localhost:5000/edit/company", {
method: "POST",
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(function(response) {
if (response.status >= 400) {
throw new Error("Bad Response from server");
}
return response.json();
})
.then(function(data) {
console.log(data);
if (data === "success") {
// e.target.checked : !e.target.checked;
this.setState({ msg: "Company Edited", active: !e.target.checked });
}
})
.catch(function(err) {
console.log(err);
});
// this.setState({ });
}
You are passing two functions to the onClick and as far as I know (though I am not able to give a source for this or tell you why) react will only use the last value you give to props. This is why setting the state of cked probably did not work.
I would suggest giving it only 1 function like so:
onClick={
(e) => {
this.setState({ cked: !this.state.cked });
this.handleActivated(e, com.cid)
}
}
If you want to only execute the second one after the setState is done(since it is async), you should use the callback function of setState.
onClick={
(e) => {
this.setState({ cked: !this.state.cked }, () => {
this.handleActivated(e, com.cid)
});
}
}
I tried to create POST request in ReactJS however it does not work I keep getting
POST http://localhost:3000/ 404 (Not Found)
error,
Can someone help me please what I am doing wrong I have been trying to do it for more than 4 hours now and it is getting annoying :/
Here is my app.jsx File
import React from 'react';
import ReactDOM from 'react-dom';
import "./main.css";
import $ from 'jquery';
class ContactForm extends React.Component{
componentDidMount(){
var $form = $('.send_JSON');
var $inputName = $('.get_name');
var $inputAge = $('.get_age');
var $inputPrefix = $('.get_prefix');
var $inputEmail = $('.get_email');
var url = 'http://localhost:3000/'; //Configurable endpoint
function loadJSON(){
$.ajax({
url: url,
dataType: 'json'
}).done(function(res){
console.log(res);
console.log("DONE!")
}).fail(function(error){
console.log(error);
console.log("NOT DONE!")
});
}
function sendForm(send_name, send_age, send_prefix, send_email){
$.ajax({
url: url,
method: 'post',
dataType: 'json',
data : {
name : send_name,
age : send_age,
prefix : send_prefix,
email : send_email
}
}).done(function(res){
loadJSON();
console.log(res);
}).fail(function(error){
console.log('Error while sending Form');
readyToSubmit : '0';
});
}
$form.on('submit', function(e){
e.preventDefault();
var name = $inputName.val();
var age = $inputAge.val();
var prefix = $inputPrefix.val();
var email = $inputEmail.val();
if(name !== '' && age > 0 && email !== ''){
sendForm(name, age, prefix, email);
$inputName.val('');
$inputAge.val(0);
$inputPrefix.val('');
$inputEmail.val('');
}
});
}
state = {
name: 'Name',
age: '',
prefix: '-',
email : 'E-mail address',
nameCheck: '',
ageCheck: '',
emailCheck: '',
readyToSubmit: ''
}
handleSubmit = (e)=>{
e.preventDefault()
sendForm();
this.setState({
nameCheck: this.state.name.length <= 0 && 'Name field has to be filled.',
ageCheck: this.state.age.length <= 0 && 'Age has to be more than 0',
emailCheck: this.state.email.search('#') <= 0 && 'Email field has to be filled and consist #',
readyToSubmit: this.state.name.length > 0 && this.state.age.length > 0 && this.state.email.search('#') > 0 ? `Success ${this.state.name}` : '',
})
}
handleChange = e =>{
this.setState({
name: e.target.value,
})
}
handleChange2 = e =>{
this.setState({
age: e.target.value
})
}
handleChange3 = e =>{
this.setState({
prefix: e.target.value
})
}
handleChange4 = e =>{
this.setState({
email: e.target.value
})
}
clearForm = () => {
document.getElementById("sendForm").reset();
this.setState({
name: "",
age: "",
prefix: "Mr",
email: " "
})
}
render(){
return(
<div>
<span className="tooltip">{this.state.readyToSubmit}</span>
<form onSubmit = {this.handleSubmit} id="sendForm" className="send_JSON">
<h2>Sii Application</h2>
<img src="../img/logo.png"/>
<p>Your Name</p>
<span className="tooltip">{this.state.nameCheck}</span>
<input onChange = {this.handleChange} value ={this.state.name} className="get_name"/>
<p>Your Age</p>
<span className="tooltip">{this.state.ageCheck}</span>
<input onChange = {this.handleChange2} value ={this.state.age} type="number" min="10" max="100" className="get_age"/>
<p>Your Prefix</p>
<select onChange = {this.handleChange3} value = {this.state.prefix} className="get_prefix">
<option value = 'Mr'>Mr</option>
<option value = 'Ms'>Ms</option>
<option value = 'Mrs'>Mrs</option>
</select>
<p>Your Email</p>
<span className="tooltip">{this.state.emailCheck}</span>
<input onChange = {this.handleChange4} value ={this.state.email} type="email" className="get_email"/>
<button type="reset" onClick = {this.clearForm} name="clear">Clear</button>
<button type="submit" name="send">Send</button>
</form>
</div>
)
}
}
class App extends React.Component {
render(){
return <ContactForm/>
}
}
document.addEventListener('DOMContentLoaded', function(){
ReactDOM.render(
<App/>,
document.getElementById('app')
);
});
I dont know if there is other way to do so, I tried Axio - which didnt work for me at all.
I suggest you looking at fetch() API instead of using jQuery Ajax to make HttpRequest. It is more lightweight and will make your code looks much simpler. Here is a link to the blog from Jake Archibald and was suggested by Google to learn how to use fetch():
https://jakearchibald.com/2015/thats-so-fetch/
Also, you can find some useful examples here from Google official documents:
https://developers.google.com/web/updates/2015/03/introduction-to-fetch
I hope it helps.
Adding to the fetch() API, you can also use axios for making HttpRequest.
It is promise based HTTP client for the browser and node.js.
Documentation is simple and available here.
Here is the example for GET request:
// Make a request for a user with a given ID
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// Optionally the request above could also be done as
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// Want to use async/await? Add the `async` keyword to your outer
function/method.
async function getUser() {
try {
const response = await axios.get('/user?ID=12345');
console.log(response);
} catch (error) {
console.error(error);
}
}