PolymerElements / iron-scroll-threshold

Polymer element for triggering an event when nearing the beginning or end of a scrollable element
21 stars 17 forks source link

on-lower-threshold is only triggered at page load #23

Open doughaase opened 7 years ago

doughaase commented 7 years ago

Description

I'm trying to use the iron-scroll-threshold combined with iron-list. When I open up the page that has the list, on-lower-threshold is fired. Nothing happens as I scroll the list.

I have the following file structure:

index.html:

<style>
      body {
        margin: 0;
        font-family: 'Roboto', 'Noto', sans-serif;
        line-height: 1.5;
        height: 100vh;
        background-color: #eeeeee;
      }
    </style>
  </head>
  <body>
    <my-app></my-app>    
  </body>

my-app.html has nothing specific regarding css heights or layouts, only the display:block value:

 :host {
        --app-primary-color: #002F5B;
        --app-secondary-color: black;
        display: block;        
      }   

person-list.html:

:host {     
          padding: 10px;           
          display: block; 
          @apply(--paper-font-common-base);
      }
      iron-list {
        height: 90vh;    
    }
    <iron-scroll-threshold id="threshold"                           
                           lower-threshold="100"
                           on-lower-threshold="loadMoreData"
                           lower-triggered="{{nearBottom}}">

      <iron-list id="personlist" scroll-target="threshold" items="[[persons]]" as="item" hidden$="[[!storedUser.loggedin]]" selection-enabled>
        <template>
          <div>
              <div class$="[[getClassForItem(item, selected)]]" tabindex$="[[tabIndex]]">                
                  <div class="pad">                      
                      <div class="primary-text" hidden$="[[item.apelido]]">[[item.nome]]</div>
                  </div>
              </div>
          </div>           
        </template>
      </iron-list>
    </iron-scroll-threshold>
  loadMoreData: function() {
          console.log('test');
        }

I didn't declared any div for the iron-scroll-threshold. It's just: dom > template > style > ajax > iron-scroll > iron-list.

Expected outcome

The scroll to the near bottom of the list should fire the function loadMoreData.

Actual outcome

The function is fired when I load the page, and nothing else happens. The scroll is not triggering the on-lower-threshold.

I'm following the documentation: https://www.webcomponents.org/element/PolymerElements/iron-scroll-threshold ... and as far as I know, the example matches what I just coded.

cmevawala commented 7 years ago

You need to clear the triggers: this.$.scrollTheshold.clearTriggers(); check this link: https://github.com/PolymerElements/iron-list/blob/master/demo/scroll-threshold.html

blasten commented 7 years ago

Yep.

doughaase commented 7 years ago

The clearTriggers function was already on that code the whole time. Why is this issue closed? That was not the solution.

blasten commented 7 years ago

@doughaase are you able to send a complete jsbin?

karthik-hande commented 7 years ago

Even I'm facing the same issue!! on-lower-threshold="loadMoreData" is not triggering function

Mika83AC commented 7 years ago

I'm facing the same issue. The on-xxx-threshold functions are triggered on page load, but not when scrolling to the top or bottom of the defined area.

I'm using it with a dom-repeat:

<ul id="movies" class="grid" on-scroll="_onScroll" scroll-target="scrollThreshold">
   <template id="moviesList" is="dom-repeat" items="[[state.visibleList]]">
      <li>
         <mmc-list-item movie="[[item]]"></mmc-list-item>
      </li>
   </template>
</ul>

<iron-scroll-threshold id="scrollThreshold" on-upper-threshold="_onUpperThreshold" on-lower-threshold="_onLowerThreshold">
</iron-scroll-threshold>
_onUpperThreshold: function() {
   this.$.scrollThreshold.clearTriggers();
},
_onLowerThreshold: function() {
   this.$.scrollThreshold.clearTriggers();
},

Regards, Michael

marko911 commented 7 years ago

I'm facing exact same issue. The lower-threshold is only triggered on page load and it seems like the iron-scroll-threshold element isn't even listening to scroll events. When I scroll to the bottom o the list it never fires. I also cleared triggers after the inital fire and still same thing. My host element is set to height:100vh and the code for this element is

 </style>

    <iron-scroll-threshold on-lower-threshold="loadMoreData" lower-threshold="500" id="threshold">
      <template is="dom-repeat" items="[[list]]" scroll-target="document">
        <paper-icon-item class="article">
          <div item-icon>
            <div class="number">{{getIndex(index)}}</div>
          </div>
          <paper-ripple class="article"></paper-ripple>
          <div class="inner"><a href="[[item.url]]" target="_blank">[[item.title]]</a>
            <template is="dom-if" if="[[showComments]]">
              <div class="comments">[[item.domain]]<a href="https://www.reddit.com[[item.permalink]]" target="_blank">[[item.num_comments]]
                comments</a></div>
            </template>
          </div>
          <paper-icon-button on-tap="toggleFave" class="favorite" icon="{{getStarType(item)}}"></paper-icon-button>
        </paper-icon-item>
      </template>
    </iron-scroll-threshold>
  </template>
  <script>
    class Articles {
      beforeRegister() {
        this.is = "gd-articles"
        this.properties = {
          list: {
            type: Array,
            value: [],
            observer: 'isReddit'
          },
          themeColor: {
            type: String,
            value: "",
            observer: 'getTheme'
          },
          showComments: {
            type: Boolean,
            value: "",
          }
        }
      }

      getIndex(index) {
        return index + 1;
      }

      loadMoreData() {
        console.log('fire!');
      }
chwzr commented 7 years ago

hey i have also the same issue with iron-scroll-threshold, using the app-toolbox basic app-template(from the tutorial on the polymer page). The function gets fired on pageload, and after this never again, even when i clear the triggers.. I think its an issue with the scroll-target property. if i use it as in the demo "scrolling region" it is working fine. But if i set this to 100% hight and 100%width, there are two scrollbars. and the original scrollbar of the iron page element is not used. -->looks ugly

then I've tried to use the dom modul view itself: "my-view3" as scroll-target. --> also not working then i've seen this and i am thinking this is causing the issue, as this element has its own scroller and this scroller i want to use as scroll-target. i think then it should work as aspected. ive added an ID to the app-header-layout element like so:

and then i used this at my page: ` ` and in the script section of the page i tried to use something this ``` constructor() { this.scrollTarget = Polymer.dom(this.root).querySelector('#scrollHeader').scrollTarget; } ``` but it console it says: Polymer.dom(...).querySelector(...) is null does anyone know how to adress this element in a propper way? i think it is null because it is in the my-app.html file, and i am doing this in the my-view3.html file which is included via iron-pages. it would be a breeze if someone knows a way of adding iron-scroll-threshold to a iron page of the default app-toolbox template 👍 kind regards chwzr
dshukertjr commented 7 years ago

I'm also facing similar problem. Waiting for responce...

chwzr commented 7 years ago

I found out if i use the app-header without "has-scrolling-region" it work as aspected. So please tell us a way how to make it working with the has-scrolling-region activated.. i guess we just have to set a propper scroll target. but how and which target?

in the documentation of the app-header layout, its mentioned that it uses the document as scroll target for the has-scrolling-region, but it dont think so/ when i define document as scroll target for the iron-scrolling-threshold it only triggers once for obvious reasons.

so in the meantime i do not use the has-scrolling-region ( but I think it looks better with this.. ).

kind regards :)

dshukertjr commented 7 years ago

When I removed the "has-scrolling-region" attribute from the app-header element, the on-lower-threshold event started firing every time I scroll the document no matter how close I am to the bottom or which direction I am scrolling.

marko911 commented 7 years ago

One thing Ive noticed is to make sure to put the scroll target as the element that actually does the scrolling. In some cases it might be a parent element.

dshukertjr commented 7 years ago

So this is what I have:

My app-header-layout has an id of "appHeaderLayout" like the following <app-header-layout id="appHeaderLayout" has-scrolling-region> and along with that, I have the iron-scroll-threshold element as app-header-layout element's parent's sibling element <iron-scroll-threshold on-lower-threshold="_loadMoreQuestions" lower-threshold="400" id="threshold" lower-triggered="{{nearBottom}}" scroll-target="appHeaderLayout"> </iron-scroll-threshold>

I have its scroll-target attribute set to the id of app-header element, but the on-lower-threshold event is triggered only once when the page first loads. Yes, I have called the clearTriggers() method as following: _loadMoreQuestions: function(){ console.log('load more questions fired'); var threshold=this.$.threshold; threshold.clearTriggers(); },

marko911 commented 7 years ago

I ended up writing my own infinite scroll functions because this element is broken at the moment.

dshukertjr commented 7 years ago

I guess that is what I would do too then

jurerick commented 7 years ago

I have the same problem

dheerajsarwaiya commented 7 years ago

@marko911 - Is it possible for you to share your solution. I am stuck at the same place. Thanks.

marko911 commented 7 years ago

Rough version here so play with it to accommodate your own use. @dheerajsarwaiya

Basically add this behavior to the element where your scroll container lives and then set the property scrollTarget to that container ie. `this.set('scrollTarget', this.$.scrollingContainer) or use Polymer dom api etc.

Also on the same element you add this behavior, add a 'scroll-trigger' listener so you can fire what you need to when scroll threshold is reached.

<link rel="import" href="../../bower_components/polymer/polymer.html">

<script>
  window.GdBehaviors = window.GdBehaviors || {};
  GdBehaviors.GdInfiniteScrollBehavior = {
    properties: {

      scrollTarget: {
        type: Object,
        observer: '_scrollTargetChanged'
      },

      lowerThreshold: {
        type: Number,
        value: 80
      },

      lowerTriggered: {
        type: Boolean,
        value: false,
        notify: true,
        readOnly: true
      }
    },

    _scrollTargetChanged(target) {
      if (target) {
        this._toggleScrollListener(target);
      }
    },

    scrollHandler: function () {
      const THROTTLE_THRESHOLD = 200;
      if (!this.isDebouncerActive('_checkThreshold')) {
        this.debounce('_checkThreshold', function () {
          this.checkScrollThresholds();
        }, THROTTLE_THRESHOLD);
      }
    },

    checkScrollThresholds: function () {
      const lowerScrollValue = this.scrollTarget.scrollHeight - this.scrollTarget.offsetHeight - this.scrollTarget.scrollTop;
      if (lowerScrollValue <= this.lowerThreshold && !this.lowerTriggered) {
        this._setLowerTriggered(true);
        this.fire('scroll-trigger');
      }
    },

    _toggleScrollListener: function (target) {
      this.set('scrollTarget', target);
      target.addEventListener('scroll', this.scrollHandler.bind(this));
    },

    clearTrigger: function () {
      this._setLowerTriggered(false);
    }
  }

</script>
jonadeline commented 7 years ago

+1. 2 days I'm facing the problem, finally ending here.

jonadeline commented 7 years ago

I've finally make it work. In my case, I'm using the <iron-scroll-threshold> on a <paper-dialog-scrollable> element. After many tests I noticed that I had to wait the <paper-dialog> to be opened in order <iron-scroll-threshold> can get the correct height of the scrollable target. If not <iron-scroll-threshold> fires the lower-threshold event at loading as the scrollable target doesn't exist yet. It's like <iron-scroll-threshold> understands that behavior as the scroll is at the bottom of the scrollable target.

So I decided to put the <iron-scroll-threshold> in a <dom-if> binded to the open state of the paper-dialog.

Roughly here is what I've done :

HTML :

<paper-dialog with-backdrop auto-fit-on-attach on-iron-overlay-opened="_handleOverlayOpening">
      <paper-dialog-scrollable id="scroll">
        <div class="layout vertical">
          <template is="dom-repeat" items="[[items]]">
            <paper-checkbox >
              [[item]]
            </paper-checkbox>
          </template>
        </div>
      </paper-dialog-scrollable>
</paper-dialog>

<dom-if if="[[_isOpen]]">
      <template>
        <iron-scroll-threshold id="scrollTheshold" scroll-target="scroll" on-lower-threshold="_loadMoreData"></iron-scroll-threshold>
      </template>
</dom-if>

JS :

_handleOverlayOpening() {
   this._isOpen = true;
}

_loadMoreData(e) {
    console.log('yihaaaa');
}

Hope this can help in your use cases. Probably you have juste to wait an other element to be fully ready before to init your <iron-scroll-threshold>

derhuebiii commented 6 years ago

I've finally make it work. In my case, I'm using the <iron-scroll-threshold> on a <paper-dialog-scrollable> element. After many tests I noticed that I had to wait the <paper-dialog> to be opened in order <iron-scroll-threshold> can get the correct height of the scrollable target. If not <iron-scroll-threshold> fires the lower-threshold event at loading as the scrollable target doesn't exist yet. It's like <iron-scroll-threshold> understands that behavior as the scroll is at the bottom of the scrollable target.

So I decided to put the <iron-scroll-threshold> in a <dom-if> binded to the open state of the paper-dialog.

Roughly here is what I've done :

HTML :

<paper-dialog with-backdrop auto-fit-on-attach on-iron-overlay-opened="_handleOverlayOpening">
      <paper-dialog-scrollable id="scroll">
        <div class="layout vertical">
          <template is="dom-repeat" items="[[items]]">
            <paper-checkbox >
              [[item]]
            </paper-checkbox>
          </template>
        </div>
      </paper-dialog-scrollable>
</paper-dialog>

<dom-if if="[[_isOpen]]">
      <template>
        <iron-scroll-threshold id="scrollTheshold" scroll-target="scroll" on-lower-threshold="_loadMoreData"></iron-scroll-threshold>
      </template>
</dom-if>

JS :

_handleOverlayOpening() {
   this._isOpen = true;
}

_loadMoreData(e) {
    console.log('yihaaaa');
}

Hope this can help in your use cases. Probably you have juste to wait an other element to be fully ready before to init your <iron-scroll-threshold>

This is not working for me unfortunately. And isn't it the same effect als calling clearTriggers? The problem also is, when #scrollThreshold is inside the dom-if, I cannot access it for clearTriggers anymore...

cipheroth commented 5 years ago

It does not work with Polymer 3 !!!!!! or what the fuck ???

dheerajsarwaiya commented 5 years ago

I worked on Polymer from 2016 to mid of 2018 .. and then I started learning React .. It would not be wrong to say that React is far superior than polymer. Leave polymer before google shut it down. (they are planning to )

cipheroth commented 5 years ago

Nah, I am going to push and support the idea of WebComponents, and I have used React for many other projects. Im just going to create my own Element/Component. Thanks

ptytb commented 5 years ago

Solved with switching to alicorn-scroll-watcher, seems to work just fine. Install yarn add alicorn-scroll-watcher-p3