11ty / eleventy

A simpler site generator. Transforms a directory of templates (of varying types) into HTML.
https://www.11ty.dev/
MIT License
17.27k stars 495 forks source link

getFilteredByTags returns an empty array #1339

Open charue808 opened 4 years ago

charue808 commented 4 years ago

Describe the bug I'm trying to use getFilteredByTags on these existing tags but but am receiving an empty array. I am using getFilteredByTag on each of those tags separately and those are generating arrays

To Reproduce This is the code block that was written

eleventyConfig.addCollection("announcements", function(collection) { const pagesToFilter = collection.getFilteredByTags("service", "program", "volunteer");

console.log("pages to filter", pagesToFilter); // returning an empty array

const announcements = pagesToFilter.filter(function(item) {
  return item.data.hasAnnouncement !== false;
});

console.log('announcements', announcements);

return announcements;

});

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior I expected to return an array of objects with those tags

Screenshots If applicable, add screenshots to help explain your problem.

Environment:

Additional context Add any other context about the problem here.

samuelpath commented 4 years ago

Hi @charue808 Would you be willing to provide your repo for us to reproduce the issue on our side? Thanks, Samuel

samuelpath commented 4 years ago

@charue808 Another question: have you tried logging collection.getAll() before doing the filtering? Like this:

eleventyConfig.addCollection("announcements", function (collection) {
  console.log("collection all: ", collection.getAll());

  const pagesToFilter = collection.getFilteredByTags("article");

  console.log("pages to filter", pagesToFilter); // returning an empty array

  const announcements = pagesToFilter.filter(function (item) {
    return item.data.hasAnnouncement !== false;
  });

  console.log('announcements', announcements);
  return announcements;

});

This way, we should be able to determine whether the issue happens in the collection initial retrieval or whether it happens in the filtering.

charue808 commented 3 years ago

@samuelpath Thank you for your patience. I haven't had a chance to work on 11ty projects. I did the suggestion of collection.getAll() here is the output

eleventyConfig.addCollection("announcements", function (collection) {
  console.log("collection all: ", collection.getAll()); // this returns all the pages

  const pagesToFilter = collection.getFilteredByTags("article"); // getFilteredByTags with one value

  console.log("pages to filter", pagesToFilter); // returns an array

  const announcements = pagesToFilter.filter(function (item) {
    return item.data.hasAnnouncement !== false;
  });

  console.log('announcements', announcements);
  return announcements;

});
eleventyConfig.addCollection("announcements", function (collection) {
  console.log("collection all: ", collection.getAll());

  const pagesToFilter = collection.getFilteredByTags("article", "event", "project");

  console.log("pages to filter", pagesToFilter); // returns an empty array

  const announcements = pagesToFilter.filter(function (item) {
    return item.data.hasAnnouncement !== false;
  });

  console.log('announcements', announcements);
  return announcements;

});

So it looks like getFilteredByTags works with one string but not with more? unless the format is supposed to be different but that's what the docs had...

johnwargo commented 1 year ago

Is there an update on this? I'm experiencing this right now. I have an array called tags, and when I try to call

const posts = collectionApi.getFilteredByTags(...tags).sort(byDate);

It fails. If I pass in an array with a single value in it works, but as soon as I add a second, it fails.

[11ty] Problem writing Eleventy templates: (more in DEBUG output)
[11ty] Cannot read properties of undefined (reading 'data') (via TypeError)
[11ty]
[11ty] Original error stack trace: TypeError: Cannot read properties of undefined (reading 'data')
[11ty]     at Object.postStats (D:\dev\11ty\eleventy-plugin-post-stats\eleventy-plugin-post-stats.js:68:37)
[11ty]     at TemplateMap.getUserConfigCollection (D:\dev\11ty\eleventy-plugin-post-stats\node_modules\@11ty\eleventy\src\TemplateMap.js:674:47)
[11ty]     at TemplateMap.setCollectionByTagName (D:\dev\11ty\eleventy-plugin-post-stats\node_modules\@11ty\eleventy\src\TemplateMap.js:386:50) 
[11ty]     at TemplateMap.initDependencyMap (D:\dev\11ty\eleventy-plugin-post-stats\node_modules\@11ty\eleventy\src\TemplateMap.js:410:20)      
[11ty]     at async TemplateMap.cache (D:\dev\11ty\eleventy-plugin-post-stats\node_modules\@11ty\eleventy\src\TemplateMap.js:459:5)
[11ty]     at async TemplateWriter._createTemplateMap (D:\dev\11ty\eleventy-plugin-post-stats\node_modules\@11ty\eleventy\src\TemplateWriter.js:330:5)
[11ty]     at async TemplateWriter.generateTemplates (D:\dev\11ty\eleventy-plugin-post-stats\node_modules\@11ty\eleventy\src\TemplateWriter.js:360:5)
[11ty]     at async TemplateWriter.write (D:\dev\11ty\eleventy-plugin-post-stats\node_modules\@11ty\eleventy\src\TemplateWriter.js:407:23)      
[11ty]     at async Eleventy.executeBuild (D:\dev\11ty\eleventy-plugin-post-stats\node_modules\@11ty\eleventy\src\Eleventy.js:1191:13)
[11ty] Wrote 0 files in 0.38 seconds (v2.0.1)

Something interesting I noticed as I was testing this out, I wanted to make sure I was passing the array correctly (I don't have a lot of experience with spread operators). When I execute the following code:

const tags: string[] = options.tags || ['post'];
console.dir(options.tags);
console.dir(tags);
console.dir(...tags);

In the console I get the following:

[ 'post', 'news' ]
[ 'post', 'news' ]
'post'

Which seems to indicate that node isn't passing the array correctly.

johnwargo commented 1 year ago

@samuelpath here's a repo you can use: https://github.com/johnwargo/eleventy-plugin-post-stats/tree/multiple-tags

What's weird about this is that if I pass an array with only one value, it works. As soon as the array has more than one tag in it, it fails.

shkarinn commented 10 months ago

I get an empty array if I try to access local data that doesn't have a value tag inside it.

For accessing local data - as in, data returned from files within your _data directory - use the format getAll()[0].data.[customKey]

// Create collection from _data/customData.js

eleventyConfig.addCollection("customDataCollection", (collection) => {
  const allItems = collection.getAll()[0].data.customData;

  // Filter or use another method to select the items you want
  // for the collection
  return allItems;
});

In this code customDataCollection return array with data. And you can use it like collections.customDataCollection

Only collection created with 'tags' can be available with method getFilteredByTags or getFilteredByTag More info by link https://11ty.rocks/posts/creating-and-using-11ty-collections

pdehaan commented 10 months ago

I believe that using getFilteredByTags() returns posts that match ALL the specified tags, not just posts matching ANY of the tags.

Per https://www.11ty.dev/docs/collections/#getfilteredbytags(-tagname-secondtagname-[...]-):

getFilteredByTags( tagName, secondTagName, […] ) Retrieve content that includes all of the tags passed in. Returns an array.


UPDATE: Here's my barely tested attempt at filtering based on any tags. Basically my tags look like tags: ['cats', 'pets'] for each page. So i can filter for all pages with a "pets" tag, and then filter for any pages that also have "cats" OR "dogs" tags:

  eleventyConfig.addCollection("catsAndDogs", function (collectionApi) {
    const tagsToFilter = ["cats", "dogs"];
    const pages = collectionApi.getFilteredByTag("pets");
    return pages.filter(page => {
      const $tags = page.data.tags ?? [];
      return tagsToFilter.some(tag => $tags.includes(tag));
    });
  });

… and because that was a terrible explanation, here's the very quick sample repo: https://github.com/pdehaan/11ty-1339