jixodoj
jixodoj

Reputation: 329

How to add event listener to mulitple inputs with same class

I have style input field with HTML and CSS. If we focus on the input I'm shrinking the label with CSS. but If we click somewhere else the label does not shrink. So I'm checking for the input value with javascript and shrinking the lable if the input have value. but the current code only applies on the first input.

How can I fix this?

document.querySelector('.input-group .form-input').addEventListener('input', shrinkLabel);

function shrinkLabel(e) {
  const input = e.target,
    label = input.nextElementSibling;

  if (input.value.length > 0) {
    label.classList.add('shrink');
  } else {
    label.classList.remove('shrink');
  }
}
.input-group {
  position: relative;
  margin: 1rem 0;
}

.input-group .form-input {
  display: block;
  background: none;
  background-color: #fff;
  color: #202124;
  font-family: 'Poppins', sans-serif;
  font-size: 16px;
  padding: 13px 15px;
  width: 100%;
  border: 2px solid rgba(0, 0, 0, 0.12);
  border-radius: 5px;
  margin: 0;
}

.input-group .form-input:focus {
  outline: none;
  border-color: #d80810;
}

.input-group .form-input:focus ~ .form-input-label {
  font-size: 14px;
  top: -12px;
  color: #d80810;
}

.input-group .form-input-label {
  background: #fff;
  color: #80868b;
  font-size: 16px;
  position: absolute;
  pointer-events: none;
  padding: 0 7px;
  left: 8px;
  top: 15px;
  -webkit-transition: 300ms ease all;
  transition: 300ms ease all;
}

.input-group .form-input-label.shrink {
  font-size: 14px;
  top: -12px;
  color: #d80810;
}
<div class="input-group mb-4">
  <input
    type="text"
    name="username"
    value=""
    id="username"
    class="form-input"
  />
  <label for="username" class="form-input-label">Username</label>
</div>
<div class="input-group">
  <input
    type="password"
    name="password"
    value=""
    id="password"
    class="form-input"
  />
  <label for="password" class="form-input-label">Password</label>
</div>

Upvotes: 1

Views: 1244

Answers (5)

Robert
Robert

Reputation: 2763

if you a little bit modificate your inputs and put placeholder=" " then you can use pseudo class :placeholder-shown to catch not empty inputs and you can achieve you goal without js. JsBin

.input-group {
  position: relative;
  margin: 1rem 0;
}

.input-group .form-input {
  display: block;
  background: none;
  background-color: #fff;
  color: #202124;
  font-family: 'Poppins', sans-serif;
  font-size: 16px;
  padding: 13px 15px;
  width: 100%;
  border: 2px solid rgba(0, 0, 0, 0.12);
  border-radius: 5px;
  margin: 0;
}

.input-group .form-input:focus {
  outline: none;
  border-color: #d80810;
}

.input-group .form-input:focus ~ .form-input-label
{
  font-size: 14px;
  top: -12px;
  color: #d80810;
}

.input-group .form-input:not(:placeholder-shown) ~ .form-input-label {
  font-size: 14px;
  top: -12px;
}

.input-group .form-input-label {
  background: #fff;
  color: #80868b;
  font-size: 16px;
  position: absolute;
  pointer-events: none;
  padding: 0 7px;
  left: 8px;
  top: 15px;
  -webkit-transition: 300ms ease all;
  transition: 300ms ease all;
}

.input-group input:not(:empty) + label {
  font-size: 14px;
  top: -12px;
  color: #d80810;
}
<div class="input-group mb-4">
  <input
    type="text"
    name="username"
    placeholder=" "   
    value=""
    id="username"
    class="form-input"
  />
  <label for="username" class="form-input-label">Username</label>
</div>
<div class="input-group">
  <input
    type="password"
    name="password"
    placeholder=" "     
    value=""
    id="password"
    class="form-input"
  />
  <label for="password" class="form-input-label">Password</label>
</div>

Upvotes: 0

mbkfa93
mbkfa93

Reputation: 126

That's because document.querySelector returns only the first result. you should instead use document.querySelectorAll('.input-group .form-input') that will return a list of available inputs then, you should loop over that list and add the event listener to each of the inputs

const inputs = document.querySelectorAll('.input-group .form-input')
if (inputs && inputs.length) {
  inputs.forEach(input => input.addEventListener('input', shrinkLabel));
}

function shrinkLabel(e) {
  const input = e.target,
    label = input.nextElementSibling;

  if (input.value.length > 0) {
    label.classList.add('shrink');
  } else {
    label.classList.remove('shrink');
  }
}
.input-group {
  position: relative;
  margin: 1rem 0;
}

.input-group .form-input {
  display: block;
  background: none;
  background-color: #fff;
  color: #202124;
  font-family: 'Poppins', sans-serif;
  font-size: 16px;
  padding: 13px 15px;
  width: 100%;
  border: 2px solid rgba(0, 0, 0, 0.12);
  border-radius: 5px;
  margin: 0;
}

.input-group .form-input:focus {
  outline: none;
  border-color: #d80810;
}

.input-group .form-input:focus~.form-input-label {
  font-size: 14px;
  top: -12px;
  color: #d80810;
}

.input-group .form-input-label {
  background: #fff;
  color: #80868b;
  font-size: 16px;
  position: absolute;
  pointer-events: none;
  padding: 0 7px;
  left: 8px;
  top: 15px;
  -webkit-transition: 300ms ease all;
  transition: 300ms ease all;
}

.input-group .form-input-label.shrink {
  font-size: 5px;
  top: -12px;
  color: #d80810;
}
<div class="input-group mb-4">
  <input type="text" name="username" value="" id="username" class="form-input" />
  <label for="username" class="form-input-label">Username</label>
</div>
<div class="input-group">
  <input type="password" name="password" value="" id="password" class="form-input" />
  <label for="password" class="form-input-label">Password</label>
</div>

<div class="input-group">
  <input type="text" name="other" value="" id="other" class="form-input" />
  <label for="other" class="form-input-label">other</label>
</div>

Note: I've set the font size to a very small value to make sure the change is easily noticed

Upvotes: 0

Dshiz
Dshiz

Reputation: 3341

Use document.querySelectorAll(). You would then need to add your event listener with a forEach loop.

This example is from this MDN article

var highlightedItems = userList.querySelectorAll(".highlighted");

highlightedItems.forEach(function(userItem) {
  deleteUser(userItem);
});

Upvotes: 1

Derek Wang
Derek Wang

Reputation: 10204

document.querySelector returns the first Element within the document that matches the specific selector.

So that addEventListener will be applied on the first input only.

To get all matched elements, it is needed to use document.querySelectorAll.

document.querySelectorAll('.input-group .form-input').forEach((item) => {
  item.addEventListener('input', shrinkLabel);
});

function shrinkLabel(e) {
  const input = e.target,
    label = input.nextElementSibling;

  if (input.value.length > 0) {
    label.classList.add('shrink');
  } else {
    label.classList.remove('shrink');
  }
}
.input-group {
  position: relative;
  margin: 1rem 0;
}

.input-group .form-input {
  display: block;
  background: none;
  background-color: #fff;
  color: #202124;
  font-family: 'Poppins', sans-serif;
  font-size: 16px;
  padding: 13px 15px;
  width: 100%;
  border: 2px solid rgba(0, 0, 0, 0.12);
  border-radius: 5px;
  margin: 0;
}

.input-group .form-input:focus {
  outline: none;
  border-color: #d80810;
}

.input-group .form-input:focus ~ .form-input-label {
  font-size: 14px;
  top: -12px;
  color: #d80810;
}

.input-group .form-input-label {
  background: #fff;
  color: #80868b;
  font-size: 16px;
  position: absolute;
  pointer-events: none;
  padding: 0 7px;
  left: 8px;
  top: 15px;
  -webkit-transition: 300ms ease all;
  transition: 300ms ease all;
}

.input-group .form-input-label.shrink {
  font-size: 14px;
  top: -12px;
  color: #d80810;
}
<div class="input-group mb-4">
  <input
    type="text"
    name="username"
    value=""
    id="username"
    class="form-input"
  />
  <label for="username" class="form-input-label">Username</label>
</div>
<div class="input-group">
  <input
    type="password"
    name="password"
    value=""
    id="password"
    class="form-input"
  />
  <label for="password" class="form-input-label">Password</label>
</div>

Upvotes: 4

Manav
Manav

Reputation: 1367

document.querySelectorAll('.input-group .form-input').forEach(item => {
  item.addEventListener('input', shrinkLabel);
});

.querySelectorAll should work here!

Upvotes: 1

Related Questions