-2

Example: clearButtons has two elements. Problem: clearButton.click() is calling only on the one element. And it should at all

Code here: https://stackblitz.com/edit/react-6bam4e

import {Typeahead} from 'react-bootstrap-typeahead';
 // ES2015

class App extends Component {
  constructor() {
    super();
    this.state = {
      items: [{name: 'A'}, {name: 'B'}]
    };
  }

  clearInput = () => {
    const clearButtons = document.querySelectorAll(".rbt-token-remove-button");  
      for (const clearButton of clearButtons) {   
          clearButton.click();  
      }  
  }

  render() {
    return (
      <div>
         <Typeahead
            id={'example4'}
            defaultSelected={this.state.items.slice(0, 3)}
            /*disabled = {this.state.selectGroupTasksId === ''}*/
            labelKey="name"
            multiple
            options={this.state.items}
            placeholder="Choose ..."
            ref={(ref) => this._typeahead = ref}
          />
          <button onClick={this.clearInput }>Button</button>
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));
Umbro
  • 1,984
  • 12
  • 40
  • 99
  • 1
    You wouldn't happen to be getting any console errors would you? It looks like you're going out of bounds. – Michael Bianconi Aug 15 '19 at 17:09
  • 1
    Is there a reason that you are clicking on the buttons rather than just executing the logic to accomplish the same result? – Code-Apprentice Aug 15 '19 at 17:10
  • 1
    You could include a HTML snippet with the relevant elements. Also, why do you want to call `click()` with setTimeout? – pdpino Aug 15 '19 at 17:11
  • 1
    loop should be `for(let i=0; i < clearButton.length; i++)` – I wrestled a bear once. Aug 15 '19 at 17:11
  • he is using let, so the closure isn't required. – I wrestled a bear once. Aug 15 '19 at 17:11
  • 1
    I think problem lies in accessing `i` inside async call `setTimeOut()`. Is it clicking the first one or the last one only (i assume last one). Also the for loop bound should be `<` instead of `<=` – fiveelements Aug 15 '19 at 17:13
  • @Iwrestledabearonce. I've just notice that he's using let so this is not duplicate. – jcubic Aug 15 '19 at 17:13
  • the `=` is literally the only thing wrong with this code. it's just executing the first one before throwing the error because of the settimeout. https://jsfiddle.net/fg5tonyc/ – I wrestled a bear once. Aug 15 '19 at 17:15
  • @fiveelements I delete `setTimeout` but call function only one element – Umbro Aug 15 '19 at 17:15
  • `setTimeout` also has unintended side effects here. It simply clicks all 3 buttons instantly after 100ms (so not 100ms apart as was probably intended). – Flame Aug 15 '19 at 17:20
  • @Umbro I have tried exactly this and it clicks all buttons (see my answer). Request you to post your code which demonstrates the problem to get a definite solution. – fiveelements Aug 15 '19 at 17:23
  • @fiveelements I do just like you. All the time the `click ()` function is called on one element – Umbro Aug 15 '19 at 17:25
  • @Umbro how you are certain that `click()` is called only on one element, please share that information? Run and see yourself in my answer that `click` event in all the buttons are printing on the console when you click `clear` button. – fiveelements Aug 15 '19 at 17:28
  • @Umbro in your updated snippet you see 3 outputs (`1, 2, 3`) on the console and then error. To avoid error change the for loop bound to `<` instead of `<=` as mentioned before. – fiveelements Aug 15 '19 at 17:30
  • @ I wrestled a bear once. @Flame Here is my example:https://stackblitz.com/edit/react-6bam4e I do as you do in the examples but it doesn't work for me. I'm using react and react-bootstrap-typeahead. Should I create a new question? – Umbro Aug 15 '19 at 17:50

4 Answers4

3

Make your life easier and replace your index-based for-loop with a for...of-loop:

clearInput = () => {
    const clearButtons = document.querySelectorAll(".clear-button");  
    for (const clearButton of clearButtons) {
        setTimeout(() => {
          clearButton.click(); 
        }, 100);   
    }
}

clearInput()
<button class="clear-button" onclick="console.log('button 1')">Button 1</button>
<button class="clear-button" onclick="console.log('button 2')">Button 2</button>
connexo
  • 53,704
  • 14
  • 91
  • 128
  • Here is my example:https://stackblitz.com/edit/react-6bam4e I do as you do in the examples but it doesn't work for me. I'm using react and react-bootstrap-typeahead. Should I create a new question? – Umbro Aug 15 '19 at 17:50
3

In continuation to my comment on the original post (may not be complete answer), I am adding this answer to demonstrate.

The same program works with just for loop bound change.

    <input type="button" class="clear-button" onclick="console.log('1')" value="1" />
    <input type="button" class="clear-button" onclick="console.log('2')" value="2" />
    <input type="button" class="clear-button" onclick="console.log('3')" value="3" />
    <input type="button" class="clear-button" onclick="console.log('4')" value="4" /> <br><br>
    <input type="button" onclick="clearInput()" value="clear" />
    <script>
        clearInput = () => {
            const clearButton = document.querySelectorAll(".clear-button");

            for (let i = 0; i < clearButton.length; i++) {
                setTimeout(() => {
                    clearButton[i].click();
                }, 100);
            }
        }

    </script>
fiveelements
  • 3,649
  • 1
  • 17
  • 16
  • Here is my example:https://stackblitz.com/edit/react-6bam4e I do as you do in the examples but it doesn't work for me. I'm using react and react-bootstrap-typeahead. Should I create a new question? – Umbro Aug 15 '19 at 17:50
2

I have no idea what the handler on that button is, but its problematic. Editing your code. This solution worked for me.

  clearInput = () => {
    const clearButtons = document.querySelectorAll(".rbt-token-remove-button");
    if (clearButtons.length > 0) {
      setTimeout(() => {
        clearButtons[0].click();
        this.clearInput()
      })
    }
  }
apachuilo
  • 341
  • 3
  • 6
0

just replace const with let to lock the scope for each not just the last element!

Eslam Abu Hugair
  • 1,162
  • 1
  • 11
  • 23