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

How to use recursive (self-nested) WebC components? #184

Open
Zearin opened this issue Jun 7, 2023 · 9 comments
Open

How to use recursive (self-nested) WebC components? #184

Zearin opened this issue Jun 7, 2023 · 9 comments

Comments

@Zearin
Copy link
Contributor

Zearin commented Jun 7, 2023

TL;DR

A WebC component that can optionally contain itself (much like a ul can contain other uls) is not generating the nested elements correctly.

Since the docs state that “WebC is HTML”, I did not expect a WebC component that is basically a glorified ul to have this issue with nesting.

I am still learning subtleties of how data flows through WebC components, and it’s possible I’m missing something obvious.

(Added in Edit) Steps To Reproduce

  1. Checkout Zearin/webc-org-nested-depts
  2. Run npm i
  3. Run npm start

Test repo demonstration

https://github.com/Zearin/webc-org-nested-depts

The Components

I have a simple project where there are 3 components (all HTML-only). 2 of the 3 are special-case <ul> elements, and the last one is a special-case <li> element.

Components
<!--- dept-list.webc --->
<ul class="dept-list">
    <dept webc:for="d of depts"
        :@name="d.name"
        :@tags="d.tags"
        :@depts="d.contains"
    ></dept>
</ul>
<!--- dept.webc --->
<li class="dept">
    <span class="name" @raw="name"></span>
    <tag-list webc:if="tags" :@tags="tags"></tag-list>

    <dept-list webc:if="depts"
        :@depts="Array.from(depts)" <!--- or just depts; same outcome --->
    ></dept-list>
</li>
<!--- tag-list.webc --->
<ul class="tag-list">
    <li webc:for="tag of tags" @text="tag"></li>
</ul>

The Problem

  • ✅ The top-level list generates fine;
  • ✅ Each top-level dept generates tag-list fine; but
  • ❌ Any nested dept-list are not generating as they should.

Since these are all HTML-only components, I expected no custom elements to exist in the output.

Instead, the nested dept-list elements are generating as empty <dept-list></dept-list> elements. (Added in edit) Here is an example of the problem output.

@Zearin
Copy link
Contributor Author

Zearin commented Jun 7, 2023

@zachleat, @5t3ph, or @darthmall: I’ll gladly buy a coffee or three via sponsorship (of your choice) if someone can help me figure this one out!

@sc0ttes
Copy link

sc0ttes commented Jun 7, 2023

Hey @Zearin,

I'm also figuring out webc right now so this may not be a valid answer but wouldn't the code snippets above create an infinitely recursing list since dept.webc relies on dept-list.webc and vice versa?

Additionally, looking at your repo, appears there's a typo here though I have no idea if that would make any difference.

@Zearin
Copy link
Contributor Author

Zearin commented Jun 8, 2023

Hi @sc0ttes,

No, it wouldn’t create an infinite loop because the data is not infinitely nested. I think it’s 2 or 3 levels deep at the most.

I appreciate your catching the typo, though! Thanks 🙏 ✅Fixed!

@stevenwoodson
Copy link

I've also come across this same scenario with @11ty/webc 0.11.0 and @11ty/eleventy-plugin-webc 0.11.1

Assuming since there's no follow up that you've not figured this one out yet right @Zearin?

@Zearin
Copy link
Contributor Author

Zearin commented Jul 18, 2023

Alas! No. No luck on my end. :)

@maxdhn
Copy link

maxdhn commented Oct 16, 2023

Hi @Zearin,
I'm facing the same issue, and it seems to be intentional behavior by the author (see ast.js).
Unfortunately, self-nesting components are mandatory for our project. Do you have a workaround or perhaps another product to recommend ?

@Zearin
Copy link
Contributor Author

Zearin commented Oct 18, 2023

@maxdhn Alas, I haven't used WebC in months because of this issue. ☹️

@Zearin
Copy link
Contributor Author

Zearin commented Oct 18, 2023

@maxdhn Forgot to mention: I found this ebook incredibly helpful and informative in rolling my own web components (and easier than adopting another library).

@dwighthouse
Copy link

Ran into this today and it is still a problem. I was trying to recreate my own eleventyNavigationToHtml (because that was generating incorrect code too). There's a way to take full control by doing it yourself in Nunjucks. Sadly, it looks like the suggestion to use the equivalent of nested calls to a Nunjucks macro simply doesn't work in webc.

I'm going to guess that this is because the dependency graph is not capable of circular dependencies, since it is doing more than the other systems like Nunjucks which mostly translates text into other text.

sigh Adding this to the list of long-term known issues with webc that I've personally run into in the last two weeks (over a half dozen things at this point).

In this case, you could get around this with a hack by using the webc method of exporting raw strings. This will only be practical if you know in advance what components are going to appear inside other components (knowing for sure any that happen to become recursive are handled manually.

So, in my case:

<ul webc:root="override" webc:if="(items ?? []).length > 0">
    <li webc:for="item of items">
        <a :href="item.url" @raw="item.title"></a>
        <nav-list :@items="item.children"></nav-list>
    </li>
</ul>

Becomes:

<script webc:type="js" webc:root="override">
    const genList = (list) => {
        if ((list ?? []).length <= 0) {
            return '';
        }

        return `
            <ul>
                ${list.map((item) => {
                    return `
                        <li>
                            <a href="${item.url}">${item.title}</a>
                            ${genList(item.children)}
                        </li>
                    `.trim();
                })}
            </ul>
        `.trim();
    };

    `${genList(items)}`;
</script>

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

No branches or pull requests

5 participants