Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite scroll on any element. #7

Merged
merged 1 commit into from
Mar 27, 2014
Merged

Infinite scroll on any element. #7

merged 1 commit into from
Mar 27, 2014

Conversation

tcard
Copy link
Contributor

@tcard tcard commented Apr 10, 2013

Sets two new attributes: infinite-scroll-container, which replaces $window with an arbitrary scrollable element, and the helper infinite-scroll-parent, which replaces $window with the element's parent.

@chubbard
Copy link

Actually I've rewritten infinite-scroll so it will find the correct scroll parent automatically without the user having to specify which element to use. I think this is an easier out of the box solution that just works as opposed to making the user stop and think about how to configure infinite-scroll to work for their situation.

@bestander
Copy link

@chubbard could you please share the code?

@yungpanda
Copy link

Works like a charm! Thank you, this saved my project!
Although I don't quite understand the difference between "infinite-scroll-container" and "infinite-scroll-parent", I just used the scrollable element for both.

@tcard
Copy link
Contributor Author

tcard commented May 13, 2013

@yungpanda Glad it helped somebody else. Both attributes do the same: watch on some element's scroll. With infinite-scroll-contained you must specify which element you want to watch, while infinite-scroll-parent just watches the applied element's parent, which is a common case (was for me, anyway).

@knalli
Copy link

knalli commented May 14, 2013

Good one 👍 We're already starting to implementing this ourself. Works good.

@mattkatz
Copy link

@chubbard can you share your code? In the mean time, thanks tcard - I'll be using this as well.

@chubbard
Copy link

I'd be happy to commit the code, but being a github newbie on this. Not sure what is the best way to do that.

@OClement
Copy link

OClement commented Aug 8, 2013

How come this code hasn't been merged yet?

Don't want to sound harsh but a directive that watches only the $window is a bit useless in my opinion, as chances that most users will need to make this work on specific elements, and potentially on multiple elements in the same window, as is in my case;

That said, @tcard, I'm not sure how to use your infinite-scroll-container attrs; Could you provide an example?


Here's how I see hoe this directive should behave though;
If applied to the body, use $window
If applied to anything else, use the element on which the directive is applied as the target container;
Potentially add a use-parent attr or something if really there is a use-case for it (although I fail to see one right now)

That would eleminate the need for extra attributes and config mumbojumbo

What do you guys think?
I might fork this and give it a try myself and see how this go, although I'm quite swamped now;

@knalli
Copy link

knalli commented Aug 8, 2013

Yeah. Actually, we've merged it in our fork, too: https://github.com/hlsolutions/ngInfiniteScroll/tree/scroll-on-any-lement

I think you have only to provide infinite-scroll-parent="true". There are still some issues with scoping/applying, but our patches aren't upstreamed yet.

@OClement
Copy link

OClement commented Aug 8, 2013

Thanks for the update @knalli


Sorry for the long upcoming post:

I'm playing with this right now and coming up with this that seems to work just fine (I haven't done any real testing just yet though)

Note

For some reason I had to put elem in scope or it would use the wrong element;
To put things into context, I have an ng-repeat that iterate through a list and create a bunch of li, then a directive on-repeat-last call a method passed to it to initialize gridsterjs.

Each li's contain is also widget directive, inside which I have a div.content on which I have the infitie-scroll directive (yeah, I am building a dashboard, sort of, with draggable widgets and all).

Referring to elem passed from the link function, would always refer to the $last element of the ng-repeat... A bit weird, not sure if it's my code or an angular bug or something

It looks like this:

    <ul>
        <li on-repeat-last='$parent.initGrid()'
             ng-repeat='widget in widgets'
             widget='widget'>
            <header></header>
            <div class='content'
                    prevent-win-scroll
                    infinite-scroll='loadMore()'
                    ng-include='widget.templateUrl'
                    onload='contentLoaded()' >
            </div>
        </li>
    </ul>

So given that context, here's what I could use succesfuly (in the handler method of ng-infinite-scroll.js`:

var scrollHeight = scope.$el[0].scrollHeight,
    clientHeight = scope.$el[0].clientHeight,
    scrollTop =    scope.$el[0].scrollTop,
    remaining =    scrollHeight - (clientHeight + scrollTop),
    shouldScroll = remaining <= scrollDistance;

Don't even need a ref to the parent container either;
Hopefully/Maybe this can help a few guys out there

I still need to check how this behave given different context and elements though...

@knalli
Copy link

knalli commented Aug 8, 2013

Ehm, build an example please. Much more easier.

@tcard
Copy link
Contributor Author

tcard commented Aug 8, 2013

@OClement Just pass a jQuery selector, such as infinite-scroll-container="#thisElement". Any string that angular.element() would work on.

@OClement
Copy link

OClement commented Aug 8, 2013

@tcard:
Ok I see; Then that means you couldn't use it multiple times like in my situation then, unless creating IDs dynamically for each containers, then having to manage that (as everything is created dynamically)

@knalli:
Yeah I realize it's not easy to get like that; I've spent the last 30min trying to replicate my stuff in plnkr.co but without great success; You can take a look at my Repo here: https://github.com/OClement/Dashboard-PoC

You can checkout the code, cd in that directory then npm install && bower install; once it's done you can run the app with grunt server
(you need to have nodejs with npm installed, and grunt-cli and bower packages installed globally)

sorry if it's complicated :P

@tcard
Copy link
Contributor Author

tcard commented Aug 9, 2013

@OClement IDs are more or less the standard way to refer to elements, aren't they? Anyway, you can also put the infinite-scroll-parent directive in a child of the scrollable element (e.g. <ul><li ng-repeat="..." infinite-scroll-parent ...></li></ul>). It's the way I actually use this.

@knalli
Copy link

knalli commented Aug 9, 2013

I've tried it. Some resources are still missing and won't resolved by Bower. Missing files in browser..

@OClement
Copy link

OClement commented Aug 9, 2013

@knalli Sorry, I forgot to update bower dependencies with a few libs; It should work right now
The "custom" ng-infinite-scroll is inline in the index.html just for testing purposes

@knalli
Copy link

knalli commented Aug 9, 2013

Not really. Try to reduce the problem. Sometimes, a single/simple problem can be solved by reducing the complexity of big apps.

@nokturnal
Copy link

@tcard first off, thanks for doing this... I anticipate this being a life saver. Second, and embarrassingly, I cannot get your implementation to work. I have an absolutely positioned scrollable element and then use your syntax from an earlier post: <div data-infinite-scroll="loadMore()" data-infinite-scroll-distance="2" data-infinite-scroll-container="#container-view"... and receive the following error (seems like it is angular barfing): Error: Lexer Error: Unexpected next character at columns 0-0 [#] in expression [#container-view].

@dmackerman
Copy link

Theses issues and commits confuse me. Where do I actually get this patch? :)

Edit: found it. @nokturnal I'm getting the same error as you.

@CMCDragonkai
Copy link

This is not working for me. I have two ng-repeats happening. One is on the main page. The other is an overlay. When I open up the overlay, it shuts down overflow on the body, but allows overflow on the overlay itself. Now the overlay covers the entire page, it has position fixed. I tried using infinite-scroll-container=".overlay_backdrop" and it doesn't do anything. However when I close the overlay and scroll on the main page, this triggers the handler that is meant for the overlay. The handlers are not being isolated from each other when they are instantiated.

@mattkatz
Copy link

CMCDragonkai - why not show us in a jsfiddle? For me, the patch works.

@AlJohri
Copy link

AlJohri commented Nov 8, 2013

@chubbard Why don't you copy and paste your solution or diff onto http://pastie.org/?

@denisos
Copy link

denisos commented Jan 14, 2014

I pulled the latest js code from: https://github.com/hlsolutions/ngInfiniteScroll/tree/scroll-on-any-lement

But I too am seeing the same error as @nokturnal and @dmackerman:
[$parse:lexerr] Lexer Error: Unexpected next character at columns 0-0 [#] in expression [#list-conversations]. http://errors.angularjs.org/1.2.7/$parse/lexerr?p0=Unexpected%20next%20character%20&p1=s%200-0%20%5B%23%5D&p2=%23list-conversations

I'm on angular v1.2.7

Does anyone know the solution?

@knalli
Copy link

knalli commented Jan 14, 2014

Do you have a demo? Plunkr?

@Narretz
Copy link

Narretz commented Jan 24, 2014

In angular 1.2.x I also get the lexer error. Solution: put your value into commas: '#my-selector'.

@danse
Copy link

danse commented Jan 24, 2014

@BinaryMuse why don't you merge this?

@Narretz
Copy link

Narretz commented Jan 24, 2014

While it's unfortunate that BinaryMuse isn't updating the repo anymore, this should not be merged as it is. Two problems: In 1.2, you get a lexer error, and when you change the scroll-container after linking, the scroll event handler is not bound to the new container.

@kcrwfrd
Copy link

kcrwfrd commented Apr 24, 2014

If infinite-scroll-container and infinite-scroll-parent aren't specified, will the container default to the element the directive is on, or $window?

infinite-scroll-parent isn't terribly useful. Take the following for example, wouldn't having infinite-scroll on an ng-repeated element be problematic?

ul.container
  li(
    infinite-scroll = "myPagingFunc()"
    infinite-scroll-parent = "true"
    ng-repeat = "post in posts"
  )
    h1 {{ post.title }}
    div {{ post.content }}

It would be so much simpler to do the following:

ul.container(
  infinite-scroll = "myPagingFunc()"
)
  li(ng-repeat="post in posts")
    h1 {{ post.title }}
    ...

@feliperyan
Copy link

I can not for the life of me get this to work - the only script that works is the original 1.0 - What am I doing wrong?

@MarcLoupias
Copy link

Don't know without your code.

It works well but without documentation i had to put some console.log() in the directive code to understand how to set up this.

In my case :

Let's say that you have a div with a scroll, in my case because of theses css properties :

.class_with_css_props_leading_to_a_scroll {
  height: 100%;
  overflow-y: auto;
}

And this div contains a child div, and that child div contains one ore more div or li with ng-repeat (3 nested ng-repeat in my case)

Your structure is :

<div id="main_block_with_scroll" class="class_with_css_props_leading_to_a_scroll">
  <div infinite-scroll="youFnToGetMoreResults()" 
          infinite-scroll-container="'#main_block_with_scroll'" 
          infinite-scroll-parent>
    <div ng-repeat="elem in list">
    </div>
  </div>
</div>

Hope it can help.

@bettysteger
Copy link

I've always used it like this without infinite-scroll-parent:

<div infinite-scroll="youFnToGetMoreResults()" id="main_block_with_scroll"
          infinite-scroll-container="'#main_block_with_scroll'">

I couldn't get it done, but thanks to @MarcLoupias 's example I got it working!!

@kristianmandrup
Copy link

Which example exactly?

@bettysteger
Copy link

the comment above ;) #7 (comment)

@Clifford-Foster
Copy link

Thanks @MarcLoupias it works like a charm.

@kaustuv
Copy link

kaustuv commented Sep 19, 2014

@MarcLoupias thanks!

@cecep17
Copy link

cecep17 commented Nov 12, 2014

hi,
i'm has pull from branch https://github.com/hlsolutions/ngInfiniteScroll/tree/scroll-on-any-lement , but why when i'm use, why still my $windows.. not my container.. this my code :

<div ui-view="content" id="myContent">
  <div infinite-scroll="scrollToLoad()" infinite-scroll-distance="1" infinite-scroll-container="'#myContent'" >
  <div ng-repeat="collection in collections" > </div>
 </div>
</div>

thanks..

@fishfacemcgee
Copy link
Contributor

@cecep17 the branch you're referencing is pretty far behind the current state of code. It's probably not a bad idea to update. Regardless, you likely just need the infinite-scroll-parent attribute. Your code seems to match the example here with the exception of the infinite-scroll-parent: #7 (comment)

@cecep17
Copy link

cecep17 commented Nov 12, 2014

@fishfacemcgee which branch for last code? are at master?

@fishfacemcgee
Copy link
Contributor

@cecep17 Master Branch of this repository would have the latest code. You're referencing a side-branch of a fork that hasn't been updated in a long time.

@cecep17
Copy link

cecep17 commented Nov 12, 2014

@fishfacemcgee how i know my

is use ngInfiniteScroll ? my real problem is i have side bar with scroll, at this moment if i scroll my sidebar an have max.. my content with ngInfiniteScroll scrolling to..

i hope you understand and thanks for help.

@fishfacemcgee
Copy link
Contributor

@cecep17 I'm not sure I follow, unfortunately. Your best bet would be to set up a Plunkr or something that can demonstrate the issue.

@ObaidUrRehman
Copy link

Here is a Plunkr in case any one want to see it working: http://plnkr.co/edit/a2u9I9

@PaulMougel
Copy link

Thanks @ObaidUrRehman for the Plunkr.

Has anyone been able to make it work on mobile? I'm having issues, but can't pinpoint the exact root cause… Edit: I used multiple flex divs, which made my layout more complicated than it should be.

@hdmontero
Copy link

Hi guys,

I've been working with this directive and it's just fantastic! However, i have some issues with scrolling.

What happens is that scroll event actions are executing even when i'm not really scrolling the infinite scroll container, has any of you experienced this same problem?

Your help will be appreciated! Thanks!

@takeit
Copy link

takeit commented Feb 2, 2015

@MarcLoupias thanks! that worked very well, I will only add Im using version 1.2.0 of ngInfinite.

@martinmidtsund
Copy link

Thanks for the good work!

@PaulMougel I have used this for a site now, and it works fine on iPhone 4/5/6 and iPad mini as far as I have seen.

@JQGuo
Copy link

JQGuo commented Mar 23, 2015

Was having an issue getting infinite scroll to work and found the solution. It wasn't a problem with the ngInfiniteScroll code though, but I just thought I'd post it here for anyone who is using the same frameworks.

I've been trying to get infinite scroll working on a sidebar container in a project that uses Angular Material Design. I managed to see scroll events firing on the right element using infinite-scroll-parent='true', but it was firing every time I scrolled. So I was debugging the infinite scroll code when I saw that elementBottom and remaining were negative. It appears that having layout="column" (I think its an HTML attribute only used by the material design code) on your element causes something weird to happen. If you scroll, the div appears in the right location visually, but it actually scrolls up in the DOM viewer, so it makes sense that the element offsets are negative. So the fix for me was just removing that attribute. I'm not really a front-end developer so idk if this behaviour is a bug with Material Design or not.

Anyways, took me quite awhile to figure out, hope this helps others out that are using both Material Design and ngInfiniteScroll.

@mgonzalez10
Copy link

My problem was similar to @JQGuo because every time I scrolling, the page event was fired. It was because the div element with ng-repeat had assigned a style float: left.

@oharlem
Copy link

oharlem commented Jul 13, 2015

@mgonzalez10
You are right, when I removed float I started getting just the first page (instead of all at once), but only the first page: when I reach the bottom - no progress, is does not fire up a call to fetch the next data set.
Any thoughts?

Thanks!
D.

@fcristel
Copy link

I'm getting the same problem as @dopgm . The nextPage isn't fetching the next results. I'm only getting the first page when in a modal

@ramirek
Copy link

ramirek commented Dec 1, 2016

I resolved the issue with adding infinite-scroll-parent on the element, it works fine on ng-infinite-scroll: 1.3.0

@ytianzaishui
Copy link

I use infinite scroll on ng-dialog in a div, it works ,but when i scroll function infinite-scroll="mypageFun()" works every time .

<div class="tags-scroll"
                     id="tags-scroll">
                    <div infinite-scroll-distance="-1"
                         infinite-scroll-parent="true"
                         infinite-scroll-immediate-check="false"
                         infinite-scroll="mypageFun()">
                        <table class="table table-bordered"
                               style="margin-bottom: 0;">
                            <tbody>
                            <tr ng-repeat="item in LargeCNCulturalData" ng-if="LargeCNCulturalData.length">
                                <td>{{item.tagName}}</td>
                                <td>
                                    <input id="{{item.tagId}}"
                                           type="checkbox"
                                           ng-checked="largeIsCheckTag(isRepeatList,item.tagId)"
                                           ng-click="largeGetCheckTags($event,item.tagId,item.tagName,item.tagPriority)">
                                </td>
                            </tr>
                            </tbody>
                        </table>
                    </div>
                </div>

@nkmishra1997
Copy link

I have a scroll-able div and my main page is also scrollable. In my case, the desired behavior is that the loadMore() function is fired only when I scroll inside my scrollable div and not when I am scrolling the main page. Right now, the loadMore() is fired even if I scroll the main window. I have followed the example in #7 (comment). Has anyone achieved this kind of behavior? If yes, kindly share the work-around. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.