3

I'm trying to make a simple post creator with a title, and I want to make the "post-btn" to be disabled and its cursor changed to "not-allowed" if one of the inputs (title, text) is empty ( value.length === 0; ), I've written a function using forEach and an eventListener but it didn't actually work, I'm thinking of another way by adding an eventListener for both inputs alone, but I couldn't imagine any short way to do it without writing a lot of if statements. So I decided to ask for help, if you can correct the mistakes I've done here or help me with a brand new effective and understandable code. To make things more clear I'd say: if the title is empty the buttons gets disabled also if the text is empty the buttons gets disabled as well, if none of them are empty the buttons becomes enabled.

let createPostBehavior = function(){
  let inputs = document.querySelectorAll('.post-input');
  let postBtn =  document.querySelector('.post-btn');

  inputs.forEach(function(inp){
    inp.addEventListener('input', function(e){
      if(e.target.value.length === 0) {
        postBtn.disabled = true;
        postBtn.style.cursor = 'not-allowed';
      } else if (e.target.value.length > 0) {
        postBtn.disabled = false;
        postBtn.style.cursor = 'pointer';
      }

    })
  })
}
createPostBehavior();
<div class="create-post-wrapper">
        <div>
                <p class="sub-headline">Create a new post</p>
        </div>
        <div>
                <input class="post-input" type="text" placeholder="Title">
        </div>
        <textarea id="input" class="post-input"></textarea>
        <div class="buttons-wrapper">
                <button class="post-btn">Post</button>
        </div>
</div>

2
  • 1
    your code works (provided you actually call createPostBehavior() somewhere). The only change I'd add is that post-btn should initially be disabled since both imputs are empty at the start. Commented Jan 20, 2020 at 19:06
  • 1
    I'd think you'd want to check both inputs' values on input to either one, since you need to validate both. Of course, you could just use HTML's required attribute and not mess around with the disabled state of the button, but that's a different UX. Commented Jan 20, 2020 at 19:09

3 Answers 3

3

Currently, when the user's change makes an input non-empty, you conclude that all is well, but that is wrong: another input could still be empty. You must look at the whole picture, and check other inputs as well. As soon as you find one that is empty, the conclusion should be that the data is still not complete.

Also, I would listen for input events on the wrapper element: that way you only need to attach one listener. Then use some to find out if there is still an empty input -- iterating all input elements.

let postBtn = document.querySelector('.post-btn');
let wrapper = document.querySelector('.create-post-wrapper');
let inputs = [...wrapper.querySelectorAll('.post-input')];

function validate() {
  let isIncomplete = inputs.some(input => !input.value);
  postBtn.disabled = isIncomplete;
  postBtn.style.cursor = isIncomplete ? 'not-allowed' : 'pointer';
}

wrapper.addEventListener('input', validate);
validate();
<div class="create-post-wrapper">
  <div>
    <p class="sub-headline">Create a new post</p>
  </div>
  <div>
    <input class="post-input" type="text" placeholder="Title">
  </div>
  <textarea id="input" class="post-input"></textarea>
  <div class="buttons-wrapper">
    <button class="post-btn">Post</button>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

Wow, I've never heard of that "some" thing. Thanks for helping me and letting me know about that feature.
1

Another way to do this, would be using the filter method. We are using it this case as a way to find any input which value's length is 0. After that, we just do the needed operations on the button.

let inputs = document.querySelectorAll('.post-input');
let postBtn =  document.querySelector('.post-btn');

inputs.forEach(inp => inp.addEventListener('input', checkInputs));
  
function checkInputs(event) {
    const inputArray = [...inputs];
    const missingInput = inputArray.filter(inp => inp.value.length === 0).length > 0;
    toggleButton(missingInput);
  }
  
function toggleButton(toggle) {
    postBtn.disabled = toggle;
    postBtn.style.cursor = toggle ? "not-allowed" : "pointer";
  }
<div class="create-post-wrapper">
        <div>
                <p class="sub-headline">Create a new post</p>
        </div>
        <div>
                <input class="post-input" type="text" placeholder="Title">
        </div>
        <textarea id="input" class="post-input"></textarea>
        <div class="buttons-wrapper">
                <button style="cursor: not-allowed" disabled class="post-btn">Post</button>
        </div>
</div>

1 Comment

Works too ! Thanks for the help.
1

Something like this would be a pretty clean way to do it:

const form = document.querySelector('form');
const inputTitle = form.querySelector('input[type="text"]');
const inputContent = form.querySelector('textarea');
const submitButton = form.querySelector('button');

submitButton.disabled = true;

const state = {
  title: '',
  content: ''
};

const updateButton = () => {
  submitButton.disabled = !(state.title && state.content)
};

inputTitle.addEventListener('input', event => {
  state.title = event.target.value;
  updateButton();
});

inputContent.addEventListener('input', event => {
  state.content = event.target.value;
  updateButton();
});
form {
  display: flex;
  flex-direction: column;
}

form input,
form textarea {
  margin-top: 10px;
  padding: 5px;
}

form button {
  margin-top: 10px;
  padding: 5px;
  background-color: #8FBC8F;
  cursor: 'not-allowed';
}

form button:disabled {
  background-color: #EEE;
  cursor: 'pointer';
}
<div>
  <p>Create a new post</p>
  <form>
    <input type="text" placeholder="Title">
    <textarea > </textarea>
    <button>Submit</button>    
  </form>
</div>

1 Comment

The previous answer is way shorter and does the job, Thanks for your help anyways.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.