Home > Software engineering >  Why the input value wont update ? when i click the send button?
Why the input value wont update ? when i click the send button?

Time:06-20

I try to run the code it works for the first time but in the second time it won't work I don't know why ? I want to make it in a way that I can send several messages over and over

var message = document.querySelector('.container');
var btn     = document.getElementById('btn');
var inpt    = document.getElementById('txt');

function AddMessage() {
  if (String(inpt.value) != '' && isNaN(inpt.value) == true) {
    message.innerHTML  = `<p>${inpt.value} </p>`;
    inpt.value = '';
  }
}
input {
  outline: none;
}
<div >
  <input type="text" value="" id="txt">
  <button id="btn" onclick="AddMessage()">send</button>
  <p>whats your name ?</p>
</div>

CodePudding user response:

You can update only inner html for answer, not the full block with input

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <style>
        input{
            outline: none;
        }
    </style>
    <div >
        <input type="text" value="" id="txt">
        <button id="btn" onclick="AddMessage()">send</button>
        <p>whats your name ?</p>
        <p id="answer"></p>
    </div>
    <script>
var message = document.querySelector('.container');
var btn = document.getElementById('btn');
var inpt = document.getElementById('txt');
var answer = document.getElementById('answer');


function AddMessage(){
    if( String(inpt.value) != '' && isNaN(inpt.value) == true  )
    {
        answer.innerHTML = `<p>${inpt.value} </p>`;
        inpt.value = '';
    }
}
    </script>
</body>
</html>


CodePudding user response:

Since your output element is the wrapper for all of the other elements, when you do this you are overwriting all of those elements:

message.innerHTML  = `<p>${inpt.value} </p>`;

Visually (and perhaps even intuitively) this has no noticeable effect. But what it does is create entirely new elements which no longer correspond to your btn and inpt variables. Which leaves you interacting with stale objects that don't represent anything on the screen.

Probably the simplest approach would be to create a more specific output element. For example, add another <div> in your container and output to that:

var message = document.getElementById('message'); // reference new element
var btn     = document.getElementById('btn');
var inpt    = document.getElementById('txt');

function AddMessage() {
  if (String(inpt.value) != '' && isNaN(inpt.value) == true) {
    message.innerHTML  = `<p>${inpt.value} </p>`;
    inpt.value = '';
  }
}
input {
  outline: none;
}
<div >
  <input type="text" value="" id="txt">
  <button id="btn" onclick="AddMessage()">send</button>
  <p>whats your name ?</p>
  <div id="message"></div> <!-- new element -->
</div>

CodePudding user response:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <style>
        input{
            outline: none;
        }
    </style>
    <div >
        <input type="text" value="" id="txt" name="txt">
        <button id="btn" onclick="AddMessage()">send</button>
        <p>whats your name ?</p>
        <ul id="list">
        
        </ul>
    </div>
    <script>
        var message = document.querySelector('.container');
var btn = document.getElementById('btn');
var inpt = document.getElementById('txt');
var list = document.getElementById('list');
let myList = "";

function AddMessage(){
    
    if( String(inpt.value) !== '' && isNaN(inpt.value) == true  )
    {
       myList  =`<li>${inpt.value}</li>`;
       list.innerHTML = myList;
    }
}
    </script>
</body>
</html>

CodePudding user response:

This line message.innerHTML = ...

equals to message.innerHTML = message.innerHTML ..., it assign something new to message.innerHTML, in other words, it rewrites the content, thus btn and inpt won't referece the original dom anymore.

var message = document.querySelector('.container');
var btn = document.getElementById('btn');
var inpt = document.getElementById('txt');
var output = document.getElementById('output');
function AddMessage() {
console.log('addMessage')
  if (String(inpt.value) != '' && isNaN(inpt.value) == true) {
    output.innerText=inpt.value;
  }
}
input {
  outline: none;
}
<div >
  <input type="text" value="" id="txt">
  <button id="btn" onclick="AddMessage()">send</button>
  <p>whats your name ?</p>
  <p id="output"></p>
</div>

CodePudding user response:

Issues with .innerHTML

You are assigning to .innerHTML. This causes recreation of the element's descendants (see innerHTML "On setting..."):

const oldReference = document.getElementById("element");
document.body.innerHTML  = ""; // Assigning to innerHTML
const newReference = document.getElementById("element");

const isSameElement = oldReference === newReference;
console.log({ isSameElement });
<div id="element">

As you can see, the old references btn and inpt won't be the elements currently in the DOM.

Sidenote: Parsing .innerHTML may be quite time-consuming, and its use with user input is a security issue.

Security considerations

Especially with user input you shouldn't use .innerHTML, because that is an easy way to insert scripts into your webpage:

document.body.addEventListener("click", evt => {
  if (!evt.target.closest("button")) return;
  
  const input = document.querySelector("input");
  document.body.innerHTML  = input.value;
});
pre{padding:2px 4px;border:1px solid;width:min-content}
<input><button>Insert</button>

<p>Try to input this:</p>
<pre><code>&lt;img src=""
  one rror="console.log('any script here!')"></code></pre>

<p>Then look into your browser console.

Alternatives for .innerHTML

If you want to add elements, you can use document.createElement(), Element.append(), and Node.textContent:

const input = document.querySelector("input");

document.querySelector("button").addEventListener("click", evt => {
  const p = document.createElement("p");
  p.textContent = input.value;
  document.body.append(p);
  
  input.value = "";
  
  const currentInput = document.querySelector("input");
  console.log("Is same input?", input === currentInput);
});
<input><button>Insert</button>

<p>Also try adding some HTML, for example: <code>&lt;span>Test&lt;/span>

  • Related