Summer Sale! All accounts are 50% off this week.

davdjurgens's avatar

Vue infinite scroll

I've been trying to get infinitescroll working with vue, and followed this tutorial: https://itsolutionstuff.com/post/laravel-vue-js-infinite-scroll-example-with-demoexample.html

My files:

routes/web.php

Route::get('/', function () {
    return view('welcome');
});

Route::get('pins', 'PinController@index');

index function in app/Http/Controllers/PinController.php

public function index()
    {
        $data = Pin::orderBy('id')->paginate(12);
        return response()->json($data);
    }

resources/views/layout.blade.php

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <!-- Styles -->
    <link rel="stylesheet" type="text/css" href="{{asset('css/app.css')}}">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.1/css/all.css" integrity="sha384-O8whS3fhG2OnA5Kas0Y9l3cfpmYjapjI0E4theH4iuMD+pLhbf6JI0jIMfYcK3yZ" crossorigin="anonymous">

    <title>MyPins</title>

</head>
<body>
    
    <nav>
        @include ('partials.nav')
    </nav>
        
    <main class="container">
        @yield ('content')
    </main>

    <footer>
        @include ('partials.footer')
    </footer>

    <!-- Scripts -->
    <script src="{{asset('js/app.js')}}"></script>

</body>
</html>

resources/views/welcome.blade.php

@extends('layout')

@section('content')

<section id="app">
    <pins></pins>
</section>

@endsection

resources/js/app.js

require('./bootstrap');

window.Vue = require('vue');
Vue.use(require('vue-resource'));

Vue.component('pins', require('./components/pins.vue'));
Vue.component('InfiniteLoading', require('vue-infinite-loading'));

const app = new Vue({
    el: '#app'
});

resources/js/components/pins.vue

<template> 

    <div class="columns is-multiline">
        <div v-for="pin in list" class="column is-one-quarter">
            <a :href="'/pins/' + pin.id" >
                <div class="pin">
                    <h4><strong>{{ pin.title }}</strong></h4>
                    <p>{{ pin.description }}</p>
                </div>
            </a>
        </div>
        <infinite-loading @distance="1" @infinite="infiniteHandler"></infinite-loading>     
    </div>
        
</template>

<script>
    
    export default {
        
        mounted() {
            console.log('Pins Mounted');
        },

        data() {
            return {
                list: [],
                page: 1,
            };
        },

        methods: {
            infiniteHandler($state) {
                        let vm = this;
 
                        this.$http.get('/pins?page='+this.page)
                                .then(response => {
                                    return response.json();
                                }).then(data => {
                                    $.each(data.data, function(key, value) {
                                             vm.list.push(value);
                                     });
                                    $state.loaded();
                                });
 
                        this.page = this.page + 1;
                    },
        },
    }

</script>

I'm not entirely sure what is happening in the methods here, which makes it hard to troubleshoot. I don't get any errors when I compile, I don't get any errors in the console. I just don't get any data in the list array.

Can anybody help me?

0 likes
3 replies
akhouad's avatar

please make sure all js plugins are well installed + make sure resources/views/layout.blade has a '.php' extension

davdjurgens's avatar

As far as I can tell I have all js plugins it would need: vue, vue-resource, vue-infinite-loading, axios, jquery. What else does it need?

layouts.blads does have the php extension, I've updated the original post.

davdjurgens's avatar
davdjurgens
OP
Best Answer
Level 1

In case anybody is interested: I was able to solve it. Here's my pins.vue file:

<template> 

    <div class="columns is-multiline">
        <div v-for="pin in list" class="column is-one-quarter-widescreen is-one-third-desktop is-half-tablet">
            <a :href="'/pins/' + pin.id" >
                <div class="pin">
                    <img :src="'/images/' + pin.image ">
                    <div class="pin-content">
                        <h5><strong>{{ pin.title }}</strong></h5>
                        <p>{{ pin.description | truncate(100) }}</p>
                    </div>
                </div>
            </a>
        </div>
        <infinite-loading spinner="waveDots" @infinite="infiniteHandler">
            <span slot="no-more"></span>
        </infinite-loading>     
    </div>
        
</template>

<script>
    
    import InfiniteLoading from 'vue-infinite-loading';

    export default {

        data() {
            return {
                list: [],
                page: 1,
                lastPage: 0,
            };
        },

        methods: {

            infiniteHandler($state) {

                let timeOut = 0;

                if (this.page > 1) {
                    timeOut = 1000;
                }
                    
                setTimeout(() => {
                
                    let vm = this;
                        
                    window.axios.get('/pins?page='+this.page).then(({ data }) => {

                        vm.lastPage = data.last_page;
                        
                        $.each(data.data, function(key, value){
                            
                            vm.list.push(value);        
                        
                        });

                        if (vm.page - 1 === vm.lastPage) {
                            $state.complete();
                        }

                        else {
                            $state.loaded();
                        }
                    
                    });
                    
                    this.page = this.page + 1;
            
                }, timeOut);
             
            },
        },

        components: {
            InfiniteLoading,
        }

    }

</script>

I've added some bells and whistles. If you have any questions feel free to ask.

Please or to participate in this conversation.