Automatically scroll down to next listgroup item a

2019-07-24 17:37发布

问题:

1) I am trying to Auto scroll to the next item in listgroup. For example if user answer the first question it should auto scroll to the second question. (React) and onSubmit it should scroll to the first not answered question
2) When user view this list in mobile view the YES or NO Radio button should display in center and also SUBMIT AND CLEAR BUTTON (BOOTSTRAP)
3) How to know which item is selected from the drop down and display it in console.

Code

回答1:

There are a number of ways this can be achieved. One way would be to add a method that scrolls to an item in your form, via "vanilla js", and then use that in both your onInputChanged on onSubmut methods.

You could defined this function in your component as:

  // Scrolls the list to a list item by list item index
  scrollToItemByIndex = (index) => {

    // Find the list item element (by index), and scroll wrapper element 
    const scrollItem = document.querySelector(`[scrollIndex="${ (index) }"]`)
    const scrollWrapper = document.querySelector(`[scrollWrapper="scrollWrapper"]`)

    if(scrollItem && scrollWrapper) {

      // If list item found in DOM, get the top offset
      const itemRect = scrollItem.offsetTop // [UPDATED]
      const wrapperRect = scrollWrapper.offsetTop // [UPDATED]

      // Scroll the wrapper to the offset of the list item we're scrolling to
      scrollWrapper.scrollTo(0, itemRect - wrapperRect)
    }
  }

You onInputChange function could then be updated as follows:

 onInputChange = ({ target }) => {
    const { cards } = this.state;
    const { options } = this.state;

    const nexState = cards.map((card, index) => {
      if (card.cardName !== target.name) return card;

      const options = card.options.map(opt => {
        const checked = opt.radioName === target.value;
        return {
          ...opt,
          selected: checked
        }
      })

      // [ADD] When input changes (ie something is set), scroll to next item
      this.scrollToItemByIndex( index + 1 )

      const style = options.every(option => !option.selected) ? 'danger' : 'info'

      return {
        ...card,
        style,
        options
      }
    });
    this.setState({ cards: nexState })
  }

Also, your onSubmit would be updated to scroll to any form items that are not valid:

 onSubmit = () => {

    this.state.cards.forEach((card, index) => {
      var invalid = card.options.every(option => !option.selected)
      if (invalid) {
        card.style = 'danger'

        // [ADD] this item has invalid input, so scroll to it
        this.scrollToItemByIndex(index)

      }
      else {
        card.style = 'info'
      }
    });

    ...
 }

Finally, you'd need to update your component's render method with the following, to ensure that the query selectors above function correctly:

<ul class="nav nav-pills nav-stacked anyClass" scrollWrapper="scrollWrapper">

and:

{cards.map((card, idx) => (<ListGroup bsStyle="custom" scrollIndex={idx}>
    ... 
</  ListGroup   >)}

[UPDATED] A full working sample can be found here: https://stackblitz.com/edit/react-z7nhgd?file=index.js

Hope this helps!