Skip to content

Instantly share code, notes, and snippets.

@tjkhara
Last active November 9, 2020 16:50
Show Gist options
  • Select an option

  • Save tjkhara/4d9d0544dadeb02f5dbdd045e937038f to your computer and use it in GitHub Desktop.

Select an option

Save tjkhara/4d9d0544dadeb02f5dbdd045e937038f to your computer and use it in GitHub Desktop.
Update item part 2

Update item part 2

Write node code to talk to the mongodb

Start work on this function in server.js

app.post('/update-item', function(req, res){
	// This is where the db communication will happen
	console.log(req.body.text)
	res.send("Success")
})

This is the function for update

app.post('/update-item', function(req, res){
	// This is where the db communication will happen
	// console.log(req.body.text)
	// res.send("Success")
	db.collection('items').findOneAndUpdate(a, b, c)
})

a is where we tell mongodb which document we want to update b is what we want to update on that document

db.collection('items').findOneAndUpdate(a, {$set: {text: req.body.text}}, c)

See the format of b text is the name set in browser.js

document.addEventListener("click", function(e){
	if(e.target.classList.contains("edit-me")){
		let userInput = prompt("Enter your desired new text")
		axios.post("/update-item", {text: userInput}).then(function(){
			// Do something interesting here in the next video
		}).catch(function(){
			console.log("Please try again later.")
		})
		console.log(userInput)
	}
})

---

db.collection('items').findOneAndUpdate(a, b, c)

c is where we tell the function what to do after the db action is complete.

For now we are just sending a success message.

app.post('/update-item', function(req, res){
	// This is where the db communication will happen
	// console.log(req.body.text)
	// res.send("Success")
	db.collection('items').findOneAndUpdate(a, {$set: {text: req.body.text}}, function(){
		// send response to browser
		res.send("success")
	})
})

Back to a - where we tell mongodb which document we want to update.

The issue we need to solve here is that when a user clicks the edit button we need to keep track of the text they type in

but also which edit button they clicked

This is where the id of a mongo db document will help us.

We will adjust the HTML template that gets sent for the home page to include the id value for each document.

Go to server.js

We will now work in this area:

<ul class="list-group pb-5">
		${items.map(function(item) {
			return `<li class="list-group-item list-group-item-action d-flex align-items-center justify-content-between">
			<span class="item-text">${item.text}</span>
			<div>
			<button class="edit-me btn btn-secondary btn-sm mr-1">Edit</button>
			<button class="delete-me btn btn-danger btn-sm">Delete</button>
			</div>
			</li>`
		}).join('')}
	</ul>

We will change this line like this:

<button data-id="${item._id}" class="edit-me btn btn-secondary btn-sm mr-1">Edit</button>

Now we go to browser.js to tell the function to send the _id along with the text.

This is the function we need to edit:

document.addEventListener("click", function(e){
  if(e.target.classList.contains("edit-me")){
    let userInput = prompt("Enter your desired new text")
    axios.post("/update-item", {text: userInput}).then(function(){
      // Do something interesting here in the next video
    }).catch(function(){
      console.log("Please try again later.")
    })
    console.log(userInput)
  }
})

This is what we added:

id: e.target.getAttribute("data-id")

This is what the function looks like now:

document.addEventListener("click", function(e){
  if(e.target.classList.contains("edit-me")){
    let userInput = prompt("Enter your desired new text")
    axios.post("/update-item", {text: userInput, id: e.target.getAttribute("data-id")}).then(function(){
      // Do something interesting here in the next video
    }).catch(function(){
      console.log("Please try again later.")
    })
    console.log(userInput)
  }
})

Go back to server.js and fill in the a placeholder

in this function

app.post('/update-item', function(req, res){
  // This is where the db communication will happen
  // console.log(req.body.text)
  // res.send("Success")
  db.collection('items').findOneAndUpdate(a, {$set: {text: req.body.text}}, function(){
    // send response to browser
    res.send("success")
  })
})

This is where we tell mongo which document we want to update.

This is what the function will look like now:

app.post('/update-item', function(req, res){
  // This is where the db communication will happen
  // console.log(req.body.text)
  // res.send("Success")
  db.collection('items').findOneAndUpdate({_id: new mongodb.ObjectID(req.body.id)}, {$set: {text: req.body.text}}, function(){
    // send response to browser
    res.send("success")
  })
})

Note this format for a

a = {_id: new mongodb.ObjectID(req.body.id)}

At this point if you refresh the app and edit an item the change is sent to the database.

Now we want to work on the frontend aspect to automatically reload the values

Go to browser.js and work on the comment from the last video:

document.addEventListener("click", function(e){
  if(e.target.classList.contains("edit-me")){
    let userInput = prompt("Enter your desired new text")
    axios.post("/update-item", {text: userInput, id: e.target.getAttribute("data-id")}).then(function(){
      // Do something interesting here in the next video
    }).catch(function(){
      console.log("Please try again later.")
    })
    console.log(userInput)
  }
})

This is what the finished code looks like

document.addEventListener("click", function(e){
  if(e.target.classList.contains("edit-me")){
    let userInput = prompt("Enter your desired new text")
    axios.post("/update-item", {text: userInput, id: e.target.getAttribute("data-id")}).then(function(){
      // We need to take care of refreshing the item that was changed
      // How do we know which item to update?
      // Start with which edit button was clicked on? e.target
      // Go to parent e.target.parentElement.parentElement.querySelector(".item-text")
      e.target.parentElement.parentElement.querySelector(".item-text").innerHTML = userInput
    }).catch(function(){
      console.log("Please try again later.")
    })
    console.log(userInput)
  }
})

Now the change in the item to should be seen right away in the page.

Two additional changes to improve the user expreience

First prompt should be prepopulated with the existing value

Second is when the user clicks cancel we should not send anything to the database

  1. We can send in a second argument to this line

    let userInput = prompt("Enter your desired new text", "hello")

We need to figure out how to get the existing value of the list item.

We do something very similar to what we did in the last step:

document.addEventListener("click", function(e){
  if(e.target.classList.contains("edit-me")){
    let userInput = prompt("Enter your desired new text", e.target.parentElement.parentElement.querySelector(".item-text").innerHTML)
    axios.post("/update-item", {text: userInput, id: e.target.getAttribute("data-id")}).then(function(){
      // We need to take care of refreshing the item that was changed
      // How do we know which item to update?
      // Start with which edit button was clicked on? e.target
      // Go to parent e.target.parentElement.parentElement.querySelector(".item-text")
      e.target.parentElement.parentElement.querySelector(".item-text").innerHTML = userInput
    }).catch(function(){
      console.log("Please try again later.")
    })
    console.log(userInput)
  }
})
  1. For the cancel

Just put the axios request in an if statement:

document.addEventListener("click", function(e){
  if(e.target.classList.contains("edit-me")){
    let userInput = prompt("Enter your desired new text", e.target.parentElement.parentElement.querySelector(".item-text").innerHTML)
    if(userInput){
      axios.post("/update-item", {text: userInput, id: e.target.getAttribute("data-id")}).then(function(){
	// We need to take care of refreshing the item that was changed
	// How do we know which item to update?
	// Start with which edit button was clicked on? e.target
	// Go to parent e.target.parentElement.parentElement.querySelector(".item-text")
	e.target.parentElement.parentElement.querySelector(".item-text").innerHTML = userInput
      }).catch(function(){
	console.log("Please try again later.")
      })
      // console.log(userInput)
    }
  }
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment