vue.js with Laravel pagination and filtering for list
<p>I'm still debating the approach but this is what I have so far. The filters work great but the data list is over 2k items, so some sort of limit is going to need to be applied. The issue is that any limit to the view would have to require a new API pull with any filter being set by any methods I've tried.</p>

<p>My question is should I somehow paginate from the API call or pull all data and paginate with vue? Should I perhaps filter in the backend and apply different API calls or should I use what I have below? The filtering works nicely but I am not clear how I could limit whats displayed yet filter through the entire list then return.</p>

<p>My Vue app and components:</p>

<pre><code>Vue.component('filter', {

props: ['list', 'name'],

template: '#filter-template',

watch: {

    selected: function(currentValue) {

        this.$dispatch('filter-update', [this.name, currentValue]);

    }

}

 });

Vue.component('products', {

template: '#product-template',

created() {

    this.fetchProducts();

},

data:function(){
    return {
        products:[],
        category: 'All',
        collection: 'All',
        design: 'All'
    }
},

events: {

    'push-category': function(id) {

        this.category = id;
        this.filterProducts();

    },

    'push-collection': function(id) {

        this.collection = id;
        this.filterProducts();

    },

    'push-design': function(id) {

        this.design = id;
        this.filterProducts();

    }

},

computed: {

    total: function () {
        return this.products.length;
    }

},

methods: {

    fetchProducts: function() {

        this.$http.get('api/internal/products', function(products) {

            this.$set('products', products);

        });

    },

    filterProducts: function() {

        var parent = this;
        var catFilter = [];
        var collFilter = [];
        var designFilter = [];

        // Collect all the bad guys
        if(this.category == 'All') { 
            catFilter = [];
        } else {

            var key = 'Item_Disc_Group';

            filter(key, this.category, catFilter);

        }

        if(this.collection == 'All') { 
            collFilter = [];
        } else {

            var key = 'Collection';

            filter(key, this.collection, collFilter);

        }

        if(this.design == 'All') { 
            designFilter = [];
        } else {

            var key = 'Fancy_Color_Intensity';

            filter(key, this.design, designFilter);

        }

        // Hide all the bad guys, show any good guys
        for (var i = this.products.length - 1; i &gt;= 0; i--) {
            var product = this.products[i];

            if(catFilter.indexOf(product) &gt; -1) {
                product.On_The_Web = "0";
            } else if(collFilter.indexOf(product) &gt; -1) {
                product.On_The_Web = "0";
            } else if(designFilter.indexOf(product) &gt; -1) {
                product.On_The_Web = "0";
            } else {
                product.On_The_Web = "1";
            }               


        };

        function filter(key, active, array) {

            for (var i = parent.products.length - 1; i &gt;= 0; i--) {
                var product = parent.products[i];

                if(product[key] != active) {
                    array.push(product);
                }

            };

        }

    }

}

});


new Vue({

el: '#product-filter',

created() {

    this.fetchCategories();
    this.fetchCollections();
    this.fetchDesigns();

},

methods: {

    fetchCategories: function() {

        this.$http.get('api/categories', function(categories) {

            this.$set('categories', categories);

        });

    },

    fetchCollections: function() {

        this.$http.get('api/collections', function(collections) {

            this.$set('collections', collections);

        });

    },

    fetchDesigns: function() {

        this.$http.get('api/designs', function(designs) {

            this.$set('designs', designs);

        });

    }

},

events: {

    'filter-update': function(data) {

        if(data[0] == "categories") {
            this.$broadcast('push-category', data[1]);
        } else if (data[0] == "collections") {
            this.$broadcast('push-collection', data[1]);
        } else {
            this.$broadcast('push-design', data[1]);
        }

    }

}

});
</code></pre>

<p>My markup:</p>

<pre><code>&lt;div id="product-filter"&gt;

&lt;filter :list="categories" name="categories"&gt;&lt;/filter&gt;

&lt;filter :list="collections" name="collections"&gt;&lt;/filter&gt;

&lt;filter :list="designs" name="designs"&gt;&lt;/filter&gt;

&lt;div class="clearfix"&gt;&lt;/div&gt;

&lt;products&gt;&lt;/products&gt;


&lt;!-- Vue Templates --&gt;

&lt;template id="filter-template"&gt;
    &lt;div class="form-group col-md-2"&gt;
        &lt;label&gt;@{{ name }}&lt;/label&gt;
        &lt;select v-model="selected" class="form-control input-small"&gt;
            &lt;option selected&gt;All&lt;/option&gt;
            &lt;option value="@{{ option.navision_id }}" v-for="option in list"&gt;@{{ option.name }}&lt;/option&gt;
        &lt;/select&gt;
        &lt;span&gt;Selected: @{{ selected }}&lt;/span&gt;
    &lt;/div&gt;
&lt;/template&gt;

&lt;template id="product-template"&gt;
    &lt;div class="row mix-grid thumbnails"&gt;
        &lt;h1&gt;@{{ total }}&lt;/h1&gt;
        &lt;div v-for="product in products" v-if="product.On_The_Web == '1'" class="col-md-3 col-sm-6 mix category_1"&gt;
            &lt;a href="/products/@{{ product.id }}"&gt;
                &lt;div class="mix-inner"&gt;
                    &lt;img class="img-responsive" src="https://s3-us-west-1.amazonaws.com/sg-retail/images/products/@{{ product.No }}.jpg" alt=""&gt;
                    &lt;div class="prod-details"&gt;
                        &lt;h3&gt;@{{ product.No }}&lt;/h3&gt;
                        &lt;p&gt;&lt;/p&gt;
                        &lt;span class="price"&gt;&lt;/span&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/a&gt;
            &lt;div class="prod-ui"&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/template&gt;

&lt;/div&gt;
</code></pre>