How to pass raw html from jsx to Api2pdf REST API - javascript

I'm trying to find the best way to pass my html table data (React JSX) to the api2pdf REST API https://www.api2pdf.com/
I was unable to do so, which led me to reconstruct my whole html data separately then upload it
const fetchReportPdf = async () => {
await fetch("https://v2018.api2pdf.com/chrome/html", {
method: "post",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "*Auth key placed here*",
},
body: JSON.stringify({
html: `
<html style="color: green" lang="en">
<head>
<title>Daily Report for ${newDate}</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous"
/>
</head>
<body>
<div className="DailyReportTable_Container ">
<table
class="table table-bordered border-dark table-sm"
style="width: 900px"
>
<tbody>
<tr>
<th colspan="6" class="text-center">
CIVIL WORKS FOR CONSTRUCTION OF THWAKE DAM EMBARKMENT AND
ASSOCIATED WORKS
</th>
</tr>
<tr>
<th>INSPECTOR</th>
<td colspan="1">${report.User}</td>
<th>SECTION:</th>
<td colspan="4" style="padding-left: 10px">${
report.Section
}</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
`,
fileName: `${newDate} ${report.Section} ${report.Shift}.pdf`,
options: {
textAlign: "left",
height: "11in",
},
}),
})
.then((res) => res.json())
.then((res) => {
document.getElementById(
"Download_Button"
).innerHTML = `<a className="Download_Button" href="${res.pdf}" >Download PDF</a>`;
});
};
This is the table, combined with fetched data from MongoDB which is stored in state then used in the html code above. Example is the ${report.User}
Placing this fetchReportPdf function in an onClick button generates a response with a download link which i can then access and save the pdf file
Using this method has been useful so far, but now i need to map data from an array in my state.
Mapping it directly inside the html code does not work. So i tried to place a script tag and execute the code from here
<script type="module">
${function rocktripFn() {
const rockTripArray = report.rocktrip;
const newArr = rockTripArray.map((item, index) => {
return `${item.Number_Of_Trips} trips made for Rock Type ${item.RockType}`;
});
const rocktrip = document.querySelector("#rockTripUL");
newArr.forEach((sub) => {
const item = document.createElement("li");
item.innerHTML = sub;
rocktrip.appendChild(item);
});
}}
rocktripFn();
</script>
report.rocktrip is the state holding the array that i want to map. But the pdf is blank in that section. The script only returns an output when i replace report.rocktrip with the actual array e.g.
{Number_Of_Trips: '45', RockType: '3A'},
{Number_Of_Trips: '32', RockType: '3B'}
But it can't map data directly from my state
I'm probably going about all this the wrong way when i'm certain there is a simpler way of doing this, how can i simplify this process with cleaner code?
Posting the jsx code directly from my component would definitely be ideal, but i don't know how.

Solution was to actually use useRef hook to obtain the innerHTML of the targeted div.
import useRef from "react";
const reportRef = useRef();
const fetchReportPdf = async () => {
const reportHTML = reportRef.current.innerHTML;
await fetch("https://v2018.api2pdf.com/chrome/html", {
method: "post",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Auth key placed here",
},
body: JSON.stringify({
html: `
<html style="color: green" lang="en">
<head>
<title>Daily Report for ${newDate}</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous"
/>
</head>
<body>
<div className="DailyReportTable_Container ">
${reportHTML}
</div>
</body>
</html>
`,
fileName: `${newDate} ${report.Section} ${report.Shift}.pdf`,
options: {
textAlign: "left",
height: "11in",
},
}),
})
.then((res) => res.json())
.then((res) => {
document.getElementById(
"Download_Button"
).innerHTML = `<a className="Download_Button" href="${res.pdf}" >Download PDF</a>`;
});
};
<table className="table-responsive" ref={reportRef}>

Related

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?

inline javascript callback onclick using mustache templating

Screenshot of UI
I'm having an issue invoking the inline javascript inside the mustache template file (.hjs).
when I click "Verify", the script tag and console logs do not run. It is not pulling the input code I type into the input box either.
For context: I am sending the mustache template (html) from my node server to an iFrame on the front end (React). I want the template to interact with the user and send an API call to my server and verify the 2FA.
I am sending variables to the javascript through {{ var }}, which is standard for mustache.
My thoughts: this code works in a regular index.html file.
any help or tips appreciated! I can try any suggestions locally to debug further.
<!DOCTYPE html>
<html>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<body>
<div id="inline-widget" style="margin:0 auto;width: 360px;padding:5px">
<p style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Roboto','Oxygen','Ubuntu','Cantarell','Fira Sans','Droid Sans','Helvetica Neue',sans-serif;color:#48545d;font-size:14px;line-height:125%;margin:10px auto 20px;text-align:center">
Please complete your purchase by entering the 4 character code at the end of your recent charge description.
</p>
<img style="width: 350px;text-align:center;border:1px solid black" src="https://d2xxy1rwbjzckp.cloudfront.net/verification.jpeg" alt="Example"></img>
<p style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Roboto','Oxygen','Ubuntu','Cantarell','Fira Sans','Droid Sans','Helvetica Neue',sans-serif;color:#48545d;font-size:11px;line-height:125%;margin-bottom:10px auto 20px;text-align:left">
Code = 3122 in this example
</p>
<p id="error-message" style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Roboto','Oxygen','Ubuntu','Cantarell','Fira Sans','Droid Sans','Helvetica Neue',sans-serif;color:#48545d;font-size:11px;line-height:125%;margin-bottom:10px auto 20px;text-align:center;color:red"></p>
<div class="input-group mb-3">
<input id="2faCode" type="text" class="form-control" placeholder="4 digit code" aria-describedby="basic-addon2"/>
<div class="input-group-append">
<button class="btn btn-outline-secondary" id="verifyButton" type="button">Verify</button>
</div>
</div>
</div>
<script>
const button = document.getElementById('verifyButton');
button.addEventListener('click', async _ => {
try {
const verifyCode = document.getElementById('2faCode').value;
console.log('start!: ', verifyCode);
const response = await fetch({{ callbackUrl }}, {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
orderId: {{ orderId }},
verificationCode: {{ verifyCode }}
})
});
const contentType = response.headers.get("content-type");
if (contentType === 'text/html; charset=utf-8') {
const textResponse = await response.text();
document.getElementById("inline-widget").innerHTML = textResponse;
} else {
const parsedResponse = await response.json();
document.getElementById("error-message").innerHTML = parsedResponse.message;
}
} catch(err) {
document.getElementById("error-message").innerHTML = err;
console.error(`Error: ${err}`);
}
});
</script>
</body>
</html>

LoopBack v3 PUT request responding with HTTP 400

I want to display the list of record into webpage . I am using vuejs for front end development and mysql for backend .I created this applications by using LoopBack. I have some list of records inside the mysql database but the problem is when i run the web page , its does not display the records and when i want to insert new records , i am getting errors on this line ..
**(index):96 PUT http://localhost:3000/api/Account/ 400 (Bad Request)
storeAccount # (index):96
submit # VM346:3
invokeWithErrorHandling # vue.js:1863
invoker # vue.js:2188
original._wrapper # vue.js:7541**
When i clicked the index.js ,its showing error in this line
fetch(API, {...
Here is code for server.js file.
// Copyright IBM Corp. 2016. All Rights Reserved.
// Node module: loopback-workspace
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
'use strict';
var loopback = require('loopback');
var boot = require('loopback-boot');
var app = module.exports = loopback();
app.start = function() {
// start the web server
return app.listen(function() {
app.emit('started');
var baseUrl = app.get('url').replace(/\/$/, '');
console.log('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
var explorerPath = app.get('loopback-component-explorer').mountPath;
console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
}
});
};
// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname, function(err) {
if (err) throw err;
// start the server if `$ node server.js`
if (require.main === module)
app.start();
});
Here is my html code .
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
</head>
<body>
<div id="AccountApp">
<h1>Account List</h1>
<table>
<thead>
<tr>
<th>Id</th>
<th>Email Address</th>
<th>Created Date</th>
<th>Updated Date</th>
<td> </td>
</tr>
</thead>
<tbody>
<tr v-for="account in accounts">
<td #click="editAccount(account)" class="accountItem" title="Click to Edit">{{account.id}}</td>
<td>{{account.email}}</td>
<td>{{account.createdAt}}</td>
<td>{{account.lastModifiedAt}}</td>
<td #click="deleteAccount(account)" class="deleteAccount" title="Click to Delete">Delete</td>
</tr>
</tbody>
</table>
<form #submit.prevent="storeAccount">
<p>
<label for="email">Email</label>
<input type="text" id="email" v-model="account.email">
</p>
<p>
<label for="createdAt">Created At</label>
<input type="text" id="createdAt" v-model="account.createdAt">
</p>
<p>
<label for="lastModifiedAt">Last Modified At</label>
<input type="text" id="lastModifiedAt" v-model="account.lastModifiedAt">
</p>
<input type="reset" value="Clear" #click="reset">
<input type="submit" value="Save User 🐱">
</form>
</div>
</body>
</html>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.10/dist/vue.js"></script>
<script>
const API = 'http://localhost:3000/api/Account/';
let AccountApp = new Vue({
el: '#AccountApp',
data: {
accounts: [],
account: {
id: '',
email: '',
createdAt: '',
lastModifiedAt: ''
}
},
created: function () {
this.getAccounts();
},
methods: {
getAccounts: function () {
fetch(API)
.then(res => res.json())
.then(res => this.account = res);
},
storeAccount: function () {
let method;
console.log('storeAccount', this.account);
// Handle new vs old
if (this.account.id === '') {
delete this.account.id;
method = 'POST';
} else {
method = 'PUT';
}
fetch(API, {
headers: {
'Content-Type': 'application/json'
},
method: method,
body: JSON.stringify(this.account)
})
.then(res => res.json())
.then(res => {
this.getAccounts();
this.reset();
});
},
deleteAccount: function (c) {
fetch(API + c.id, {
headers: {
'Content-Type': 'application/json'
},
method: 'DELETE'
})
.then(res => res.json())
.then(res => {
this.getAccounts();
});
// call reset cuz the cat could be 'active'
this.reset();
},
editAccount: function (c) {
/*
This line was bad as it made a reference, and as you typed, it updated
the list. A user may think they don't need to click save.
this.cat = c;
*/
this.account.id = c.id;
this.account.email = c.email;
this.account.createdAt = c.createdAt;
this.account.lastModifiedAt = c.lastModifiedAt;
},
reset: function () {
this.account.id = '';
this.account.email = '';
this.account.createdAt = '';
this.account.lastModifiedAt = '';
}
}
});
</script>
Here is the screenshot when i run the applications .
Here is the screenshot on Networks tab ..

Trying to add a 2 character state code to my National Parks project

In my search, when I add states such as Michigan or Ohio it returns back National State Parks this part works fine. My problem is that when you just add the State abbreviation it doesn't work so well.
In the API documentation, I can add 'stateCode A comma delimited list of 2 character state codes.' at which I have. In turn it spits out a CURL at which I am not familiar with at all. This is the curl: curl -X GET "https://developer.nps.gov/api/v1/parks?stateCode=AK%2C%20AL%2C%20AR%2C%20AZ%2C%20CA%2C%20CO%2C%20CT%2C%20DC%2C%20DE%2C%20FL%2C%20GA%2C%20HI%2C%20IA%2C%20ID%2C%20IL%2C%20IN%2C%20KS%2C%20KY%2C%20LA%2C%20MA%2C%20MD%2C%20ME%2C%20MI%2C%20MN%2C%20MO%2C%20MS%2C%20MT%2C%20NC%2C%20ND%2C%20NE%2C%20NH%2C%20NJ%2C%20NM%2C%20NV%2C%20NY%2C%20OH%2C%20OK%2C%20OR%2C%20PA%2C%20RI%2C%20SC%2C%20SD%2C%20TN%2C%20TX%2C%20UT%2C%20VA%2C%20VT%2C%20WA%2C%20WI%2C%20WV%2C%20WY&api_key=VBJvAbqe0D9w3pyhaHcw4p4MB2dNgSgxMjvCbyEH" -H "accept: application/json"
How can I add this to my javascript to make this work when I just want to put in the 2 character state abbreviation?
"use strict";
const apiKey = "VBJvAbqe0D9w3pyhaHcw4p4MB2dNgSgxMjvCbyEH";
const searchURL = "https://api.nps.gov/api/v1/parks";
function formatQueryParams(params) {
const queryItems = Object.keys(params).map(
key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`
);
return queryItems.join("&");
}
function displayResults(responseJson) {
// if there are previous results, remove them
console.log(responseJson);
$("#results-list").empty();
// iterate through the items array
for (let i = 0; i < responseJson.data.length; i++) {
// for each park object in the items
//array, add a list item to the results
//list with the park title, description,
//and thumbnail
$("#results-list").append(
`<li><h3>${responseJson.data[i].fullName}</h3>
<p>${responseJson.data[i].description}</p>
<a href='${responseJson.data[i].url}'>${responseJson.data[i].url}</a>
</li>`
);
}
//display the results section
$("#results").removeClass("hidden");
}
function getNationalParksInfo(query, maxResults = 10) {
const params = {
key: apiKey,
q: query,
limit: maxResults - 1
};
const queryString = formatQueryParams(params);
const url = searchURL + "?" + queryString;
console.log(url);
fetch(url)
.then(response => {
if (response.ok) {
return response.json();
}
throw new Error(response.statusText);
})
.then(responseJson => displayResults(responseJson))
.catch(err => {
$("#js-error-message").text(`Something went wrong: ${err.message}`);
});
}
function watchForm() {
$("form").submit(event => {
event.preventDefault();
const searchTerm = $("#js-search-term").val();
const maxResults = $("#js-max-results").val();
getNationalParksInfo(searchTerm, maxResults);
});
}
$(watchForm);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>National Parks by Location</title>
<link rel="stylesheet" href="style.css" />
<script
src="https://code.jquery.com/jquery-3.3.1.js"
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
crossorigin="anonymous"
></script>
</head>
<body>
<div class="container">
<h1>Your National Parks</h1>
<form id="js-form">
<label for="search-term">Search term</label>
<input type="text" name="search-term" id="js-search-term" required />
<label for="max-results">Maximum results to return</label>
<input
type="number"
name="max-results"
id="js-max-results"
value="10"
/>
<input type="submit" value="Go!" />
</form>
<p id="js-error-message" class="error-message"></p>
<section id="results" class="hidden">
<h2>Search results</h2>
<ul id="results-list"></ul>
</section>
</div>
<script src="app.js"></script>
</body>
</html>
The desired outcome is for me to either type the full state name of the state abbreviation and I get the same search results.

Can't delete newly created list item without refreshing the page and trying again ES6

Some context: I'm trying to finish building out the delete functionality of my minimal note-taking app.
Every time I create a new note, it will appear at the end of my list of notes. However, if I try to delete the newly created note, it won't work. I have to refresh the page and try again for it to work.
I keep getting these two errors:
"Uncaught TypeError: Cannot read property 'parentNode' of null at HTMLUListElement."
"DELETE http://localhost:3000/api/v1/notes/undefined 404 (Not Found)"
Otherwise, I'm able to delete any other note with no problem.
Here is my js code:
// display list of notes on the side
const noteContainer = document.querySelector(".column is-one-quarter")
const noteList = document.querySelector(".menu-list")
fetch('http://localhost:3000/api/v1/notes')
.then(function(response) {
return response.json();
})
.then(function(notes) {
notes.forEach(function(note) {
noteList.innerHTML += `<li id="list-item" data-id=${note.id}><a id="note" data-id=${note.id} class="menu-item">${note.title}</a><i id="delete" data-id=${note.id} class="fas fa-minus-circle has-text-grey-light hvr-grow"></i></li>`
})
})
// display details of each note
const noteDetail = document.querySelector(".note-detail")
noteList.addEventListener('click', function(event) {
if (event.target.className === "menu-item") {
fetch(`http://localhost:3000/api/v1/notes/${event.target.dataset.id}`)
.then(function(response) {
return response.json()
})
.then(function(note) {
noteDetail.innerHTML = `<h1 contenteditable="true" id="title" data-id=${note.id} class="subtitle is-2">${note.title}</h1><p contenteditable="true" id="body" data-id=${note.id} class="subtitle is-6">${note.body}</p><a id="save" data-id=${note.id} class="button is-small">Save</a>`
})
}
})
// i should be able to edit the title and body of a note when i click
// on it and it should save when i click on the button.
noteDetail.addEventListener('click', function(event) {
if (event.target.id === "save") {
const noteId = event.target.dataset.id
const editTitleInput = document.querySelector(`h1[data-id="${noteId}"]`)
const editBodyInput = document.querySelector(`p[data-id="${noteId}"]`)
const singleNote = document.querySelector(`a[data-id="${noteId}"]`)
fetch(`http://localhost:3000/api/v1/notes/${noteId}`, {
method: "PATCH",
headers: {
'Content-Type': 'application/json',
'Accepts': 'application/json'
},
body: JSON.stringify({
title: editTitleInput.innerText,
body: editBodyInput.innerText
})
}).then(function(response) {
return response.json()
}).then(function(note) {
singleNote.innerText = editTitleInput.innerText
})
}
})
// when i click on the button, a form with a title and body input
// should display on the right.
const newNoteButton = document.querySelector("#create")
newNoteButton.addEventListener('click', function(event) {
fetch("http://localhost:3000/api/v1/notes")
.then(function(response) {
return response.json()
})
.then(function(note) {
noteDetail.innerHTML = `<input id="title" class="input subtitle is-5" type="text" placeholder="Title">
<textarea id="body" class="textarea subtitle is-5" placeholder="Body" rows="10"></textarea><a id="add" class="button has-text-black" style="margin-left: 594px;">Add Note</a>`
// when i click on 'add button', a new note with a title and body
// should be created and added to the list of notes.
const noteTitleInput = document.querySelector("#title")
const noteBodyInput = document.querySelector("#body")
const addNoteButton = document.querySelector("#add")
addNoteButton.addEventListener('click', function(event) {
// event.preventDefault()
fetch('http://localhost:3000/api/v1/notes', {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Accepts': 'application/json'
},
body: JSON.stringify({
title: noteTitleInput.value,
body: noteBodyInput.value
})
}).then(function(response) {
return response.json()
}).then(function(note) {
noteList.innerHTML += `<li data-id=${note.id}><a id="note" data-id=${note.id} class="menu-item">${note.title}</a><i id="delete" class="fas fa-minus-circle has-text-grey-light hvr-grow"></i></li>`
})
})
})
})
// i should be able to delete a note when i click on the button.
noteList.addEventListener('click', function(event) {
// event.preventDefault()
if (event.target.id === "delete") {
const noteId = event.target.dataset.id
// const noteListItem = document.querySelector("#list-item")
const noteListItem = document.querySelector(`li[data-id="${noteId}"]`)
const singleNote = document.querySelector(`a[data-id="${noteId}"]`)
fetch(`http://localhost:3000/api/v1/notes/${noteId}`, {
method: "DELETE",
})
// debugger
// lastNote = noteList.lastElementChild
// noteList.removeChild(lastNote)
// singleNote.parentElement.remove()
noteListItem.parentNode.removeChild(noteListItem)
noteDetail.innerHTML = ""
}
})
Here is my html code:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css">
<link href="css/hover.css" rel="stylesheet" media="all">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">
<link rel="stylesheet" href="css/note.css">
<meta charset="utf-8">
<title></title>
</head>
<body>
<h1 class="title is-1">Jot</h1>
<div class="columns">
<div class="column is-one-quarter">
<p class="menu-label" style="font-size:15px;">
Notes <i id="create" class="fas fa-plus-circle has-text-grey-light hvr-grow" style="margin-left: 10px; width: 20px; height: 30px; font-size: 24px;"></i>
</p>
<ul class="menu-list">
</ul>
</div>
<div class="column is-three-fifths">
<div class="note-detail">
</div>
</div>
<div class="column">
</div>
</div>
<script src="index.js"></script>
</body>
</html>
Any help would be greatly appreciated. :)
You're nesting strings on these two lines:
const noteListItem = document.querySelector(`li[data-id="${noteId}"]`)
const singleNote = document.querySelector(`a[data-id="${noteId}"]`)
Your template literal is creating a string and you're putting that inside of quotes. For example, if your noteId is say 12. your code is ending up like this:
const noteListItem = document.querySelector("li[data-id="'12'"]")
const singleNote = document.querySelector("a[data-id="'12'"]")
I'm not 100% sure that's your issue but it's the first thing that popped out to me.
You can check out MDN to brush up on your Template literals (Template strings).

Categories

Resources