Hi everyone :wave:
I'm implementing Staticman on my GatsbyJS site, and it's looking great!
The only thing is that I want my comment submission event to adapt to React (no page reload for starters), so I'm turning action="https://dev.staticman.net/..." method="POST" into a handleSubmit function that POSTs the event via fetch():
async handleSubmit(event) {
event.preventDefault() // stop the form from submitting
const request = await fetch("https://dev.staticman.net/v3/entry/github/robinmetral/eaudepoisson/master/comments", {
method: "POST",
body: event,
})
const response = await request.json()
console.log(response)
}
However I get this error as a response:
errorCode: "MISSING_PARAMS"
data: [fields]
success: false
Staticman doesn't recognize the required fields in my event object. I've also tried to turn the object into a JSON string, but I've had the same error.
Is the API endpoint only allowing the x-www-form-urlencoded POST format? Has anyone been using fetch() to POST to Staticman?
After some research I've found a solution. Here's my handleSubmit function:
handleSubmit = async (event) => {
event.preventDefault()
// extract form data
const formdata = new FormData(event.target)
// convert FormData to json object
// SOURCE: https://stackoverflow.com/a/46774073
const json = {}
formdata.forEach(function(value, prop){
json[prop] = value
})
// convert json to urlencoded query string
// SOURCE: https://stackoverflow.com/a/37562814 (comments)
const formBody = Object.keys(json).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(json[key])).join('&')
// POST the request to Staticman's API endpoint
const response = await fetch("https://dev.staticman.net/v3/entry/github/robinmetral/eaudepoisson/master/comments", {
method: "POST",
headers: {"Content-Type": "application/x-www-form-urlencoded"},
body: formBody,
})
.then(response => {
// reset form
document.getElementById("comment-form").reset()
// display success message
document.getElementById("success").style.display = "block"
})
.catch(error => {
console.log(error)
document.getElementById("failure").style.display = "block"
})
}
This is what it does:
application/x-www-form-urlencoded content-type or "query string", using another SO snippetIt's probably not the only solution, and if you see something that I could improve, please let me know below or send me a PR!
This worked for me! Thanks @robinmetral for this solution
Glad to see that posting solutions in here is useful @kyrelldixon :slightly_smiling_face: Happy commenting!
@robinmetral thanks a lot, it's worked for me, but, what was driving me nuts was this
Step 3. Hook up your forms
Forms should POST to:
https://api.staticman.net/v2/entry/{GITHUB USERNAME}/{GITHUB REPOSITORY}/{BRANCH}/{PROPERTY (optional)}
But looking at your code (apart from dev and v3), at the end it seems that should post there:
https://dev.staticman.net/v3/entry/github/{GITHUB USERNAME}/{GITHUB REPOSITORY}/{BRANCH}/{PROPERTY (optional)}
So, in my hands, this has worked for me (with semantic-ui):
<Form onSubmit={onSubmit}>
<Form.Input name="name" onChange={changeUserName} placeholder="what" />
<Form.TextArea name="message" onChange={changeuserMessage} placeholder="what2" />
<Form.Button>Submit</Form.Button>
</Form>
and
const [userName, setUserName] = useState(() => '')
const [userMessage, setUserMessage] = useState(() => '')
const wait = ms => new Promise((r, j) => setTimeout(r, ms))
let changing = 0 // to create a buffer to avoid changing state always, the browser gets slow otherwise
const changeUserName = async (e, { value }) => {
changing++
let prev_changing = changing
await wait(100)
if (prev_changing === changing) setUserName(value)
}
const changeuserMessage = async (e, { value }) => {
changing++
let prev_changing = changing
await wait(100)
if (prev_changing === changing) setUserMessage(value)
}
const onSubmit = async e => {
e.preventDefault()
const formdata = new FormData()
formdata.set('fields[name]', userName)
formdata.set('fields[message]', userMessage)
const json = {}
formdata.forEach((value, prop) => (json[prop] = value))
const formBody = Object.keys(json)
.map(key => encodeURIComponent(key) + '=' + encodeURIComponent(json[key]))
.join('&')
// in the repo, create a folder named 'comments'
const response = await fetch(
'https://dev.staticman.net/v3/entry/github/{my github user}/{my repo}/master/comments/',
{
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: formBody,
}
)
console.log(response)
}
The fetch method doesn't support IE. It can be rewritten with the send method in xmlHttpRequest.
Most helpful comment
After some research I've found a solution. Here's my
handleSubmitfunction:This is what it does:
application/x-www-form-urlencodedcontent-type or "query string", using another SO snippetIt's probably not the only solution, and if you see something that I could improve, please let me know below or send me a PR!