PeachScript / vue-infinite-loading

An infinite scroll plugin for Vue.js.
https://peachscript.github.io/vue-infinite-loading/
MIT License
2.67k stars 368 forks source link

Component not triggered if not in view #134

Closed abishekrsrikaanth closed 6 years ago

abishekrsrikaanth commented 6 years ago

Version

2.2.3

Vue.js version

2.1.10

What is expected?

When a list that is configured with the vue-infinite-loading is not in view, then the component is not triggered.

What is actually happening?

I use the bootstrap tab and on each tab there is a table that is configured to individual vue-infinite-loading component. If the tab isn't active, then the component is not triggered.

How do I go about loading the table on a tab that isn't active

PeachScript commented 6 years ago

You can try this.$refs.infiniteLoading.attemptLoad method to trigger load manually after tab switched.

Maybe I should add a event to support that, how do you think?

abishekrsrikaanth commented 6 years ago

yes, an event will be great, but is there a way to load them without having to bring them to view.

Here is my use-case. I have a common filter for the data that needs to be loaded on both tabs. And I load both the tabs based on the filter selections and also update the count on the tab selector. Currently this doesn't work if I call this.$refs.infiniteLoadingRef.attemptLoad manually on mounted.

I additionally tried calling this.$refs.infiniteLoadingRef.$emit('$InfiniteLoading:reset');. Did not seem to help on mounted as well.

capto_capture 2018-02-12_10-31-10_am

Appreciate if you can help me on this at the earliest.

abishekrsrikaanth commented 6 years ago

@PeachScript Do you have any suggestions on how to implement this? Right now I have to downgrade to 2.2.0 to get this working, but if there is an option allowLoadingIfInvisible=true, that will be great.

abishekrsrikaanth commented 6 years ago

@PeachScript any updates on this?

PeachScript commented 6 years ago

@abishekrsrikaanth sorry for late, it is a special case, I will consider it carefully, thanks.

For now, you can extends a new Component from this component, and override the attemptLoad method to remove this line.

aleksanderd commented 6 years ago

+1 any updates?

aleksanderd commented 6 years ago

one more way to make it working without overriding/hacking infinite component.

mounted () {
  this.$refs.infinite.isLoading = true // to avoid duplicate(normal) request if "we visible"
  this.loadMore(this.$refs.infinite.stateChanger)
}

where loadMore is callback onInfinity what you think?

PeachScript commented 6 years ago

Hi @abishekrsrikaanth @aleksanderd , this issue has been on hold for long time, I'm so sorry.

I've considered it carefully, and made two opinions:

  1. The scroll distance logic depends on the getBoundingClientRect API but it cannot works for an off-screen element, so it will be too complex if implement the allowLoadingIfInvisible feature;
  2. From the user experience perspective, if we want to preload some data for users, we should prepare it directly rather than via a infinite scroll component because the scroll container is invisible for users.

So I think we can implement it like this:

export default {
  /* ... */
  mounted() {
    // preload the first page of data for users
    this.infiniteHandler();
  },
  methods: {
    infiniteHandler($state = { loaded() {}, complete() {} }) {
      /* logic to request and fill up data */
    },
  },
};

How do you think about it?

zek commented 5 years ago

Any news for this? I am using nuxt and component is invisible under a dropdown menu. I cant use ref solution.

I need to set also state because if 1 page is loaded and I try to load next page "No results" is shown

PeachScript commented 5 years ago

Hi @zek , could you explain why the infinite list be in a dropdown menu? I want to know the details of your situation.

Goldbeener commented 3 years ago

same case , here is my solution for reference:

<template>
  <infinite-loading v-if="isVisible" ...>

  </infinite-loading>
</template>

<script>
  export default {
    /* ... */
    data(){
       isVisible: false,
    },
    mounted() {
      const self = this;
      const intersectionObserver = new IntersectionObserver(function(entries) {
          if (entries[0].intersectionRatio <= 0) return;
          // present
          self.isVisible = true;
      });
      intersectionObserver.observe(document.querySelector(target));
    },
  };
</script>