How send REST calls and will get json back with the results? - javascript

When someone write name and click on the search button then I want to show the search result into unordered list from external result.json file.I am just having a issue how to fetch result and show into the list.Please help me. I ll appreciate it.Below is my code.
index.html file
<form method="POST">
<label>Search</label>
<input type="text" id="Search" />
<input type="submit">
</form>
<!-----Show result here-->
<ul>
<li>
</li>
</ul>
<script>
const userAction = async () => {
const response = await fetch('test.json', {
method: 'POST',
body: myBody, // string or object
headers: {
'Content-Type': 'application/json'
}
});
const myJson = await response.json(); //extract JSON from the http response
// do something with myJson
}
</script>
result.json file
[
{
"id":1,
"name":"John",
"City":"Melbourne",
"state":"VIC"
}
]

For demonstration it was necessary to replace your source with placeholder.
const list = document.getElementById('list');
const userAction = async (event) => {
event.preventDefault();
fetch('https://jsonplaceholder.typicode.com/todos')
.then(response => response.json())
.then(todos => {
todos.forEach((todo) => {
const li = document.createElement('li');
li.innerHTML = `${todo.userId} ${todo.id} ${todo.title} ${todo.completed}`;
list.appendChild(li);
});
})
}
<form method="POST" onsubmit="userAction(event);">
<label>Search</label>
<input type="text" id="Search" />
<input type="submit">
</form>
<!-----Show result here-->
<ul id="list"></ul>

Just after the " // do something with myJson"
you can do:
var myListElement = document.getElementById("myList");
myListElement.innerHTML = '<li>Id: '+ item.id +'</li>' + '<li>Name: '+ item.name +'</li>' + '<li> City: '+ item.City +'</li>' + '<li>State: '+ item.state +'</li>';
And Just After the:
You can edit your element like this:
<ul id="myList">

Related

Calling a javascript function with parameters in innerHTML

I'm trying to build my own comment system.
Here's the code that show a comment box when clicking on the "Reply" button:
function postComment(i, parentId) {
let content;
if (parentId === undefined) {
content = commentBox.value
} else {
content = eval("subCommentBox"+i).value
}
const body = JSON.stringify({
"post_slug": location.pathname.slice(1),
"username": "quantong",
"parent_id": parentId,
"content": content,
})
fetch("http://localhost:8080/comments", {
method: "post",
headers: { "Content-Type": "application/json" },
body: body
})
.then(resp => {
if (resp.status === 200) {
return resp.json()
} else {
console.log("Status: " + resp.status)
}
})
commentBox.value = "";
window.location.reload();
}
let allElements = document.body.getElementsByClassName("replybtn");
let addCommentField = function () {
for (let i = 0; i < allElements.length; i++) {
if (allElements[i] === this) {
if (document.getElementsByClassName("replyform")[i].innerHTML.length === 0) {
document.getElementsByClassName("replyform")[i].innerHTML = `
<div class="form-group">
<textarea class="form-control" id="subCommentBox`+i+`" rows="3"></textarea>
</div>
<div class="d-flex flex-row-reverse">
<button type="button" class="btn btn-success" onclick="postComment(` + i + `, ` + allElements[i].id + `)">Comment</button>
</div>
`
}
}
}
};
window.onload = function() {
for (let i = 0; i < allElements.length; i++) {
allElements[i].addEventListener('click', addCommentField, false)
}
}
It worked fine if I put in a .js file.
The thing is after user is logged in, I want to pass username and profile picture as a body to the backend side, so I moved it to App.svelte file:
let commentBox;
function postComment(i, parentId) {
let content;
if (parentId === undefined) {
content = commentBox
} else {
content = eval("subCommentBox"+i).value
}
const body = JSON.stringify({
"post_slug": location.pathname.slice(1),
"image_url": responsePayload.picture,
"username": responsePayload.name,
"parent_id": parentId,
"content": content},
)
fetch("http://localhost:8090/comments", {
method: "post",
headers: { "Content-Type": "application/json" },
body: body
})
.then(resp => {
if (resp.status === 200) {
return resp.json()
} else {
console.log("Status: " + resp.status)
}
})
commentBox = "";
window.location.reload();
}
If I leave the innerHTML text as it is, it caused:
Uncaught ReferenceError: postComment is not defined
If I change it from:
<button type="button" class="btn btn-success" onclick="postComment(` + i + `, ` + allElements[i].id + `)">Comment</button>
to:
<button type="button" class="btn btn-success" on:click={() => postComment(i, allElements[i].id)}>Comment</button>
it will be rendered as:
So, in a .svelte file, how can I call a javascript function with parameters in innerHTML?
If you want to make this in Svelte you should try doing it the 'Svelte' way as well, that means dropping all this constructing html in javascript and injecting it.
Instead consider your markup as a reflection of 'state' and also use components to make your life easier.
Your state would be for example an array of comments and if a user clicked 'reply'.
<!-- This will render a 'Comment' component for each item in the comments -->
{#each comment as comment}
<Comment {...comment} />
{/each}
<!-- Comment.svelte -->
<script>
export let id = "";
export let children = [];
export let text = "";
let isReplying = false;
let reply = ""
async function postComment() {
// Hide comment box
isReplying = false;
// Send to server, the inputted text is available in 'reply'
const res = await fetch(...).then(res => res.json();
// Append to children so it appears 'live'
children = [...children, res]
}
</script>
<!-- The post itself -->
<div>{text}</div>
<!-- Each child is a comment of it's own so render it with this component -->
{#each children as child}
<svelte:self {...child} />
{/each}
<!-- The reply button simply toggles a state -->
<button on:click={() => isReplying = !isReplying}>Reply</button>
<!-- Show this based on state -->
{#if isReplying}
<textarea bind:value={reply}>Blabla</textarea>
<button on:click={postComment}>Send</button>
{/if isReplying}
This should give you a fair idea of what direction to go in.
Remember that your UI is a reflection of your state. So just changed the state and Svelte will take care of the rest (inserting, removing, updating domelements)

Unable to redirect to homepage after posting a form - Express,EJS and JS

I have a view which contains a form and looks like this,
<form class="flex-form" id="form" method="">
<div class="form-component">
<label>Type</label>
<input type="text" id="type" name="type">
</div>
<div class="form-component">
<div class="form-component"><label><b>Contents</b></label></div>
<label>Savoury</label><input type="text" name="savoury" id="savoury">
<label>Fillings</label><input type="text" name="fillings" id="fillings">
<label>Amount</label><input type="text" name="amount" id="amount">
<div class="flex-component">
<button class="set-button" type="button" id="set">Set Item</button>
</div>
</div>
<div class="form-component">
<label class="description-label">Description</label>
<textarea class="fixed-textarea" id="description" name="description" cols="15" rows="10"></textarea>
</div>
<div class="form-component">
<label >Unit Price</label>
<input type="text" id="price" name="unit_price">
</div>
<div class="flex-component">
<button class="form-button" type="submit">Add</button>
</div>
</form>
I have a JavaScript that allows me to capture some intermediary information (via the Set Item button) from the form before the form gets submitted (via the Add Button). I want to handle the form's submission from the script since I need to capture the intermediary data.
let collectedItems = [];
let setter = document.getElementById('set');
let form = document.getElementById('form');
setter.addEventListener('click',getSetContent);
function getSetContent() {
let type = document.getElementById('savoury');
let fillings = document.getElementById('fillings');
let amount = document.getElementById('amount');
const content = {
type: type.value,
fillings: fillings.value.split(','),
amount: Number(amount.value)
};
collectedItems.push(content);
clearInputFields([type,fillings,amount]);
}
function clearInputFields(inputFields) {
inputFields.forEach(field => {
field.value = ''
});
console.log(collectedItems);
}
form.addEventListener('submit',submitForm);
function submitForm() {
const type = document.getElementById('type').value;
const desc = document.getElementById('description').value;
const price = Number(document.getElementById('price').value);
const content = collectedItems;
const data = {
type: type,
contents: content,
description: desc,
unit_price: price
};
post('http://localhost:8001/add/box',
{ 'Content-Type': 'application/json' },
JSON.stringify(data)
);
}
function post(endpoint,header,body) {
const response = fetch(endpoint,{ method: 'POST',headers: header,body: body });
response.then(
resp => {
if (resp.ok) {
console.log('form submitted');
} else {
console.log('form not submitted');
}
}
)
}
I then make a POST request using fetch() to an endpoint I have setup in Express which looks like this,
app.post('/add/box',(req,res) => {
const box: any = req.body;
console.log(box);
// DO SOME DB STUFF
res.redirect('/');
});
The form submission works as intended (logs to terminal using nodemon), however I am unable to redirect to the homepage. Instead I stay on the form page after the submission has occurred and I can't figure out why. Any help with this issue is much appreciated.

Get selected values in a multi-select drop-down and insert them in a JSON

I have input to insert data for a book like this
<div class="form-group">
<label for="Id">Id</label>
<input type="text" class="form-control" id="Id" placeholder="Id" required>
</div>
<div class="form-group">
<label for="Title">Titre du livre</label>
<input type="text" class="form-control" id="Title" placeholder="Titre du livre" required>
</div>
<div class="form-group">
<label for="Contenu">Contenu</label>
<textarea class="form-control" id="Contenu" rows="5" required></textarea>
</div>
<div class="form-group">
<label for="Prix">Prix</label>
<input type="text" class="form-control" id="Prix" placeholder="Prix" required>
</div>
<select multiple="" class="form-control" id="selectGenre" required="">
<option value="">Choisissez un genre</option>
<option value="1">Roman</option><option value="2">Biographie</option><option value="3">Comédie</option><option value="4">Encyclique</option><option value="5">Médicale</option><option value="6">Science</option><option value="7">Culture</option><option value="8">Politique</option></select>
A book has an id/title/content/price and it can have one or several genres
I recover each value to insert it in JSON to launch a POST request.
JSON example of a book with only one genre
{"Id":1,"Title":"FluconazoleE","Contenu":"nonummy ultricies ...","Prix":19,"Genre":[{"Id":6,"Nom":"Science"}]}
JSON example of a book with several genres
{"Id":1500,"Title":"FluconazoleE","Contenu":"nsenectus et ...","Prix":19,"Genre":[{"Id":6,"Nom":"Science"},{"Id":2,"Nom":"Biographie"}]}
My function to send a POST request
function addItem() {
const addIdTextbox = document.getElementById('Id');
const addTitleTextbox = document.getElementById('Title');
const addContenuTextbox = document.getElementById('Contenu');
const addPrixTextbox = document.getElementById('Prix');
const addGenreTextbox = document.getElementById('selectGenre');
const item = {
id: Number(addIdTextbox.value.trim()),
title: addTitleTextbox.value.trim(),
contenu: addContenuTextbox.value.trim(),
prix: Number(addPrixTextbox.value.trim()),
Genre: [{ "Id": Number(addGenreTextbox.value.trim()), "Nom": addGenreTextbox.options[addGenreTextbox.selectedIndex].text.trim() }]
};
fetch(uriBook, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(item)
})
.then(response => response.json())
.then(() => {
getItems();
addNameTextbox.value = '';
})
.catch(error => console.error('Unable to add item.', error));
alert('Votre livre a bien ete ajoute !');
window.location.href = 'liste-livres.html';
}
The problem is to send multiple choices in the genres, I can retrieve them with this code
const addGenreTextbox = document.getElementById('selectGenre');
var idGenre = [];
var nomGenre = [];
for (var option of addGenreTextbox.options) {
if (option.selected) {
idGenre.push(addGenreTextbox.value.trim());
nomGenre.push(option[addGenreTextbox.selectedIndex].text.trim());
}
}
But my question is how to process the tables to insert them in the const item to have a JSON of a book with one or several genre
So, you're successfully getting the values from your input elements, so we'll start by modifying your code to retrieve them:
const addGenreTextbox = document.getElementById('selectGenre');
let result = {};
for (var option of addGenreTextbox.options) {
if (option.selected) {
result[id] = addGenreTextbox.value.trim();
result[Nom] = option[addGenreTextBox.selectedIndex].text.trim();
}
}
item.Genre.push(result);
That should work for you. Let me know if you have any questions or if I missed something.
This is the right solution :
const addGenreTextbox = document.getElementById('selectGenre');
let GenreChoix = []
for (var i = 0; i < addGenreTextbox.options.length; i++) {
if (addGenreTextbox.options[i].selected) {
let result = {};
result["id"] = addGenreTextbox.options[i].value;
result["Nom"] = addGenreTextbox.options[i].text.trim();
GenreChoix.push(result);
}
}

Uncaught ReferenceError: updateIngredient is not defined at HTMLButtonElement.editIngredient

Not sure what I am doing wrong here but I am trying to create a simple update/edit function to be able to edit ingredients that exist with the dataset. I am getting the above error when doing so.
Here is my code:
deleteIngredient(){
const ingredientId = this.parentElement.dataset.id
fetch(`${recipeUrl}/${ingredientId}`, {
method: "DELETE"
})
this.parentElement.remove()
}
updateIngredient(){
var editForm = document.getElementById("ingredient-input")
console.log(editForm)
}
editIngredient(){
var editForm =
`<form id="edit-form">
<input type="text" id="edit-input">
<input type="submit" value="Edit Ingredient">
</form>`
this.parentElement.insertAdjacentHTML('beforeend', editForm)
console.log(this.parentElement)
document.getElementById('edit-form')
editForm.addEventListener("click", updateIngredient)
}
const editBtn = document.createElement('button')
editBtn.addEventListener("click", this.editIngredient)
editBtn.innerText = "Edit"
li.appendChild(editBtn)
ingredientList.appendChild(li)
What am I doing wrong here? This should at least not be throwing this error. Please Help!
Edit: Updated code using onclick got rid of the error!
const editForm =
`<form id="edit-form">
<input type="text" id="edit-input">
<input type="submit" value="Edit Ingredient" onclick="updateIngredient">
</form>`
this.parentElement.insertAdjacentHTML('beforeend', editForm)
console.log(this.parentElement)
document.getElementById('edit-form')
//editForm.addEventListener("click", updateIngredient)
}
updateIngredient(){
document.querySelector("data-id")
}
I could still use help with updateIngredient which will take the ingredient and edit it using the edit form. Any other advice would be so appreciated!
Edit 2: Still feeling a bit lost so here is my full Ingredient class and index.html file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles/styles.css">
<title>Recipe App</title>
</head>
<body>
<h1>Easy Recipe and Ingredient Saver</h1>
<br>
<h2>Instructions:</h2>
<h3>Enter the name of your recipe below in the top form.</h3>
<h3>After creation add all the ingredients for that recipe separately and hit enter to save to the recipe.</h3>
<div id="container">
<h4>Create a Recipe:</h4>
<form id="recipe-form">
<input type="text" id="recipe-input">
<input type="submit" value="Create Recipe">
</form>
<ul id="recipe-list">
</ul>
</div>
<script src='./src/ingredient.js'></script>
<script src='./src/recipe.js'></script>
<script src='./src/index.js'></script>
</body>
</html>
class Ingredient {
constructor(ingredient) {
this.recipe_id = ingredient.recipe_id
this.name = ingredient.name
this.id = ingredient.id
}
static createIngredient(e){
e.preventDefault()
const ingredientInput = e.target.children[0].value
const ingredientList = e.target.nextElementSibling
const recipeId = e.target.parentElement.dataset.id
Ingredient.submitIngredient(ingredientInput, ingredientList, recipeId)
e.target.reset()
}
renderIngredient(ingredientList){
const li = document.createElement('li')
li.dataset.id = this.recipe_id
li.innerText = this.name
const deleteBtn = document.createElement('button')
deleteBtn.addEventListener("click", this.deleteIngredient)
deleteBtn.innerText = "X"
li.appendChild(deleteBtn)
ingredientList.appendChild(li)
const editBtn = document.createElement('button')
editBtn.addEventListener("click", this.editIngredient)
editBtn.innerText = "Edit"
li.appendChild(editBtn)
ingredientList.appendChild(li)
}
static submitIngredient(ingredient, ingredientList, recipeId){
fetch(ingredientUrl, {
method: "POST",
headers: {
"Content-type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({
name: ingredient,
recipe_id: recipeId
})
}).then(res => res.json())
.then(ingredient => {
let newIngredient = new Ingredient(ingredient)
newIngredient.renderIngredient(ingredientList)
})
}
deleteIngredient(){
const ingredientId = this.parentElement.dataset.id
fetch(`${recipeUrl}/${ingredientId}`, {
method: "DELETE"
})
this.parentElement.remove()
}
editIngredient(){
const editForm =
`<form id="edit-form">
<input type="text" id="edit-input">
<input type="submit" value="Edit Ingredient" onclick="updateIngredient">
</form>`
this.parentElement.insertAdjacentHTML('beforeend', editForm)
console.log(this.parentElement)
document.getElementById('edit-form')
//editForm.addEventListener("click", updateIngredient)
}
updateIngredient(){
const ingredientId = this.parentElement.dataset.id
ingredientId.innerText("")
}
}

Page reload on a form submit! Rails API backend Javascript frontend

I'm having trouble figuring out my javascript. The e.preventDefault() is not working. I've tried changing the submit input to a button as well. I know with a form and using rails that it has an automatic rage reload but I thought e.preventDefault was suppose to stop that. Is there some hidden feature in the backend that I need to turn off? I set my project up to be an api by using an api flag. It also has all the right info for cors. My server is showing my data correctly ...it's just the frontend I cant get up.
I'm going to post a sample code I followed.
<html lang="en" dir="ltr">
<head>
<title>Problems</title>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
<script type="application/javascript" src="src/user.js" charset="UTF-8"></script>
<script type="application/javascript" src="src/problem.js" charset="UTF-8"></script>
</head>
<body>
<div class="container" id="container">
<h1>Everyone Has Problems</h1>
<div id="new-user-and-new-problem-container">
<form id="new-user-form">
<label>Your name:</label>
<input type="text" id="new-user-body"/>
<input type="submit"/>
</form>
</div>
</div>
<div id="problems-container" class="problems-container">
</div>
</body>
</html>```
src/user.js
```document.addEventListener('DOMContentLoaded', function(){
User.createUser()
})
class User {
constructor(user){
this.id = user.id
this.name = user.name
this.problems = user.problems
}
static createUser(){
let newUserForm = document.getElementById('new-user-form')
newUserForm.addEventListener('submit', function(e){
e.preventDefault()
console.log(e);
fetch('http://localhost:3000/api/v1/users', {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify(
{
user: {
name: e.target.children[1].value
}
})
})
.then(resp => {
return resp.json()
})
.then(user => {
let newUser = new User(user)
newUser.displayUser()
})
})
}
displayUser() {
let body = document.getElementById('container')
body.innerHTML = ''
let userGreeting = document.createElement('p')
userGreeting.setAttribute('data-id', this.id)
let id = userGreeting.dataset.id
userGreeting.innerHTML = `<h1>Hey, ${this.name}!</h1>`
body.append(userGreeting)
if (this.problems) {
this.problems.forEach(function(problem){
let newProblem = new Problem(problem)
newProblem.appendProblem()
})
}
Problem.newProblemForm(this.id)
}
}```
src/problem.js
```class Problem {
constructor(problem){
this.id = problem.id
this.name = problem.name
this.description = problem.description
}
static newProblemForm(user_id) {
let body = document.getElementById('container')
let form =
`
<form id="new-problem-form">
<label>What's your problem?:</label>
<input type="text" id="problem-name"/>
<label>Describe it:</label>
<input type="text" id="problem-description"/>
<input type="submit"/>
<h4>Your current problems:</h4>
</form>
`
body.insertAdjacentHTML('beforeend', form)
Problem.postProblem(user_id)
}
//is it appropriate for this to be a static method?
static postProblem(user_id) {
let newForm = document.getElementById('new-problem-form')
newForm.addEventListener('submit', function(e){
e.preventDefault()
fetch('http://localhost:3000/api/v1/problems', {
method: "POST",
headers:{
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify(
{
problem: {
name: e.target.children[1].value,
description: e.target.children[3].value,
user_id: user_id
}
}
)
})
.then(resp => resp.json())
.then(json => {
let newProblem = new Problem(json)
newForm.reset()
newProblem.appendProblem()
})
})
}
appendProblem(){
let problems = document.getElementsByClassName('problems-container')
let li = document.createElement('li')
li.setAttribute('data-id', this.id)
li.setAttribute('style', "list-style-type:none")
li.innerHTML = `${this.name} ~~ ${this.description}`
let solveForm = `<button type="button" id="${this.id}" class="solve-problem"> Solve </button>`
li.insertAdjacentHTML('beforeend', solveForm)
problems[0].append(li)
let button = document.getElementById(`${this.id}`)
this.solve(button)
}
solve(button){
button.addEventListener('click', function(e){
e.preventDefault()
fetch(`http://localhost:3000/api/v1/problems/${e.target.parentNode.dataset.id}`, {
method: "DELETE"
})
e.target.parentElement.remove();
})
}
}```
Try not splitting the element up.
document.getElementById('new-problem-form').
addEventListener('submit', function(e){
e.preventDefault()
}
even Jquery
$('#new-problem-form').addEventListener('submit', function(e){
e.preventDefault()
});
The preventDefault is working on the event..
Take this for example:
$('#message').keydown(function (e) {
if (e.keyCode == 13) {
e.preventDefault();
return false;
}
});
This is preventing the enter key from defaulting the submit based on the keydown function. Is this option the actual 'default' you're trying to stop?

Categories

Resources