Hey all!
I am running into an issue where I have both filters and pagination on an image gallery. For some reason I cannot get both to run together.
My structure:
- Photos (main component)
–PhotoFilters (filter component)
–PhotoList (list of images)
I am pulling all of the photos using a svelte store and a publication.
Here is my store:
import { writable } from 'svelte/store';
export const manageImageResults = writable({
sortMod: {sort: {"createdOn" : 1}},
filters: {
productTags: [],
industries: [],
capabilities: []
},
pageCount: 1,
limit: 4,
offset: 0,
});
export const imagesStore = writable([]);
Here is my publication:
Meteor.publish("photography", function (dataObj) {
const query = {};
if (dataObj.filters.productTags && dataObj.filters.productTags.length) {
query.productTags = { $in: dataObj.filters.productTags };
}
if (dataObj.filters.industries && dataObj.filters.industries.length) {
query.industries = { $in: dataObj.filters.industries };
}
if (dataObj.filters.capabilities && dataObj.filters.capabilities.length) {
query.capabilities = { $in: dataObj.filters.capabilities };
}
const photos = Photography.find(
query,
{
limit: dataObj.limit,
skip: dataObj.offset * dataObj.limit, // Use the offset to skip the already fetched images.
fields: {
_id: 1,
url: 1,
thumb: 1,
createdOn: 1,
},
},
{
sort: dataObj.sortMod.sort,
}
);
console.log(photos.fetch().length)
return photos;
});
Here is my main Photos Page level component:
<script>
import { Counts } from 'meteor/tmeasday:publish-counts';
import { manageImageResults } from "./stores";
import { photoCount } from "../../../../GlobalStores/GlobalStores";
import { onDestroy } from "svelte";
import { Photography } from "../../../../../api/BrandGuide/Photography";
import { useTracker } from "meteor/rdb:svelte-meteor-data";
import PhotoUpload from "./Components/PhotoUpload.svelte";
import PhotoFilters from "./Components/PhotoFilters.svelte";
import ImageList from "./Components/ImageList.svelte";
export let currentUser, userProfile, userPermission;
let photoUpload = false, images, imgObj, numberPerPage, noPrev, noNext, totalPages, imagesCount, subscription;
photoCount.subscribe((value) => {
numberPerPage = value;
});
manageImageResults.subscribe((value) => {
imgObj = value;
});
onDestroy(() => {
manageImageResults.update(n => ({
sortMod: { sort: { createdOn: 1 } },
filters: {
productTags: [],
industries: [],
capabilities: [],
},
limit: 4,
offset: 0,
}));
});
$: {
// Meteor.subscribe('photographyCount', imgObj);
// imagesCount = Counts.get('photographyCount');
// Meteor.subscribe("photography", imgObj);
if(imgObj){
images = useTracker(() => {
Meteor.subscribe('photographyCount', imgObj);
imagesCount = Counts.get('photographyCount');
Meteor.subscribe("photography", imgObj);
let skipCount = imgObj.offset * imgObj.limit;
return Photography.find({}, {
limit: 4,
skip: skipCount,
fields: {
_id: 1,
url: 1,
thumb: 1,
createdOn: 1,
}
},{
sort: imgObj.sortMod.sort
}).fetch();
});
noImages = ($images <= 0) ? true : false;
noNext = (imgObj.offset * imgObj.limit >= imagesCount);
noPrev = (imgObj.offset >= 1) ? false : true;
totalPages = Math.ceil(imagesCount / imgObj.limit);
}
}
const showHidePhotoUpload = () => {
photoUpload = !photoUpload;
};
const handlePhotoUploadToggle = () => {
photoUpload = !photoUpload;
};
const nextPage = () => {
imgObj.offset++;
//set manageImageResults with all values from imgObj
manageImageResults.update(value => {
value.offset = imgObj.offset;
return value;
});
};
const prevPage = () => {
imgObj.offset--;
//set manageImageResults with all values from imgObj
manageImageResults.update(value => {
value.offset = imgObj.offset;
return value;
});
};
</script>
<div class="headlineWithButton">
<h1 class="admin">Photography</h1>
<button class="btn small black" on:click|preventDefault={showHidePhotoUpload}>Add Photo</button>
</div>
<PhotoUpload
{currentUser}
{userProfile}
{userPermission}
{photoUpload}
on:toggle={handlePhotoUploadToggle}
/>
<PhotoFilters {currentUser} {userProfile} {userPermission} />
{#if $images && $images.length > 0}
<ImageList {currentUser} {userProfile} {userPermission} images={$images} brandGuide={false} partnerResource={false}/>
{/if}
<div class="pageContain">
<div class="pageWrap">
<button class="btn page" disabled={noPrev} on:click={prevPage}>
<img src="/images/prev.svg" alt="">
</button>
<span>Page: {imgObj.offset + 1} of {totalPages}</span>
<button class="btn page" disabled={noNext} on:click={nextPage}>
<img src="/images/next.svg" alt="">
</button>
</div>
</div>
Here is my filter component:
<script>
import { manageImageResults } from "../stores";
export let currentUser, userProfile, userPermission;
let selectedProduct = "",
selectedIndustry = "",
selectedCapability = "";
const applyFilters = () => {
manageImageResults.update(value => {
value.filters.productTags = selectedProduct ? [selectedProduct] : [];
value.filters.industries = selectedIndustry ? [selectedIndustry] : [];
value.filters.capabilities = selectedCapability ? [selectedCapability] : [];
return value;
});
};
const clearFilters = () => {
selectedProduct = "";
selectedIndustry = "";
selectedCapability = "";
applyFilters();
};
</script>
<div class="photoFiltersWrap">
<div class="photoFilters">
<div class="title">
Filter By:
</div>
<div class="productFilter">
<select name="product-filter" id="product-filter" bind:value={selectedProduct}>
<option value="" disabled>Choose Product</option>
<option value="Brush Tip Applicators">Brush Tip Applicators</option>
<option value="Channel Applicators">Channel Applicators</option>
<option value="Flat Applicators">Flat Applicators</option>
<option value="Round Applicators">Round Applicators</option>
<option value="Wraparound Applicators">Wraparound Applicators</option>
<option value="Fluid Dispensing Tips & Accessories">Fluid Dispensing Tips & Accessories</option>
<option value="e3mini">e3mini</option>
<option value="e3minimax">e3minimax</option>
<option value="e3multi">e3multi</option>
<option value="Applicator Track">Applicator Track</option>
<option value="Bottle Holders">Bottle Holders</option>
<option value="Ce360">Ce360</option>
<option value="Compliance">Compliance</option>
<option value="Handheld Remote">Handheld Remote</option>
<option value="Horizontal dp3">Horizontal dp3</option>
<option value="Plastic Bottles & Caps">Plastic Bottles & Caps</option>
</select>
</div>
<div class="productFilter">
<select name="industry-filter" id="industry-filter" bind:value={selectedIndustry}>
<option value="" disabled>Choose Industry</option>
<option value="Aerospace">Aerospace</option>
<option value="Agriculture">Agriculture</option>
<option value="Appliances">Appliances</option>
<option value="Automotive">Automotive</option>
<option value="Chemical">Chemical</option>
<option value="Construction">Construction</option>
<option value="Consumer Goods">Consumer Goods</option>
<option value="Defense">Defense</option>
<option value="Glass">Glass</option>
<option value="Industrial Automation">Industrial Automation</option>
<option value="Marine">Marine</option>
<option value="Medical Equipment">Medical Equipment</option>
<option value="RV">RV</option>
<option value="Structural Glazing">Structural Glazing</option>
</select>
</div>
<div class="productFilter">
<select name="capability-filter" id="capability-filter" bind:value={selectedCapability}>
<option value="" disabled>Choose Capability</option>
<option value="Fluid Applicators">Fluid Applicators</option>
<option value="Fluid Application Systems">Fluid Application Systems</option>
</select>
</div>
<div class="submit">
<button on:click|preventDefault={applyFilters}>Search</button>
</div>
</div>
{#if selectedProduct || selectedIndustry || selectedCapability}
<div class="clear">
<a href="#"
on:click|preventDefault={() => {
clearFilters();
}}
>
Clear Filters
</a>
</div>
{/if}
</div>
I can get the filters working if I keep the:
Meteor.subscribe("photography", imgObj);
Inside the useTracker function. If I move it outside (commented) then the pagination works, but not the filters.
I have tried everything I know to get this working…any support or ideas are greatly appreciated!