NO BUG: Query Loop wrapping element

Update - see comment below: NO BUG: Query Loop wrapping element - #4 by mizzinc

Browser: Opera
OS: \Windows
URL:


** Bricks**: 1.7.3

Been playing with ACF Flexible Content and Query Loop.
When inspecting code, the element with the query loop wraps each layout. i.e. a block wraps a section.

For example:

<div class="block with queryloop">
<section></section>
</div>
<div class="block with queryloop">
<section></section>
</div>

Sure, I could change the block to a section and the child section to a div. But then, I need to create a custom class to remove the default ACCS styling on the parent section and, of course, reapply all section css styling to the now div.

Plus this adds an extra element.

Code should appear as:

<main>
<article> (with query loop)
<section></section>
<section></section>
<section></section>
</article>
</main>
1 Like

I would do that.

It’s different to a ‘repeater’ element from other builders, the query loop is applied to the element that you wish to duplicate.

1 Like

Went with this method. Maybe a filter or control in future to remove the wrapper element could be useful.

Worthwhile adding a feature request?

1 Like

Given this some further consideration and reverted the title to a bug, or maybe it should be WIP?

Consider the following HTML structure in Bricks.

The expected output on the frontend is:

<article> (with query loop)
<section> <div class="container"><h3>Post Title</h3></div></section>
<section> <div class="container"><h3>Post Title</h3></div></section>
<section> <div class="container"><h3>Post Title</h3></div></section>
</article>

Yes, I am going over this again. My point is. If I hand coded this query loop, then the result would be as above. The query element wraps all child elements.

However, Bricks decides to use the query element to wrap each child element. That is not the expected result, it’s also not true to what’s been designed in the structure panel.

As developers, we don’t like surprises. Bricks gives us granular control, that’s the buy-in and this current output is not true to let’s say Brick ethos. If I wanted each child element to have a wrapping element, then I would add it.

I think, I have a strong case on this one. Could we add a control to disable the default behaviour for backwards compatibility?

What say you?

This is definitely a feature request and not a bug, the element with the query loop is supposed to duplicate (along with all content inside of it) because it’s now in a loop.

You may be best writing up a new feature request with an example of how you imagine it working and what problem it solves, so people can upvote or comment. I can’t currently see the benefit, as it looks like we’d always need to add the query loop to a container, meaning always having to add an extra element if we want something to loop, rather than just directly duplicating any element. (for example you can already achieve the output you’re lookng for by moving the query loop onto a child of the ‘article’ element, rather than applying it to the article element) But adding more specific examples may help more people get behind the idea.

i think if you leave this post as ‘bug’ it could just get remarked as ‘no bug’ and may just get lost. imo I’d write up a new feature request or add to the ideas board.

However, Bricks decides to use the query element to wrap each child element. That is not the expected result,

Just noting this part is incorrect, to clarify incase of a misunderstanding. Bricks isn’t wrapping anythng. It’s just duplicating the ‘article’ element from your structure panel, because that’s the element in the loop. The element you add the query loop to is added inside the loop.

The code version would be


if( have_rows('content') ):
    while ( have_rows('content') ) : the_row();

    /* your <article> element */

    endwhile;
endif;
2 Likes

Hi MIchael,
Thanks so much for your report!

As David said, this is not a bug. This is exactly how the query loop works. The element on which the loop is located is repeated.

In your example, the query loop should be on the section to get the desired result.

<article>
<section> <div class="container"><h3>Post Title</h3></div></section> (loop should be here)
...
</article>

Best regards,
timmse

Thanks everyone for the responses.

Timmse - If I use your suggested method, then I lose the ability to customise individual sections.

For example, the next section might require ACCS var(–section-space-xs) or a unique class. At least that’s how I interpret it.

I went ahead and changed:

  • the block to a section and applied class pad–none to override ACSS base spacing.
  • the child element from a section to a div
  • applied ACCS section padding using variables as a workaround on the div. Use of variables still allows for scalability, I suppose.

Respect, this is not a bug. Updated the title.

Alternatively, I could use a code element rather than query loop. Ideally, I refer to the OP.
Maybe I’m not seeing this correctly, as per everyone’s responses.

To assign different styles to the children, you can use nth-child for example.

Currently, each child gets the exact same styling and classes (because it is a repeated element), but this would also be the case in a normal WordPress loop unless you add a separate index.

Hmm - maybe I’m trying to make the query loop fit into a box it shouldn’t be in.

nth-child styling is an option, not ideal if every single section is unique. I don’t think that’s the right approach.

Maybe the answer is to feature request the query-builder function being added to the code element, whereby it generates the php. Which is kind of similar to a nested element


OR

Add an option in the query builder to output the PHP to copy/paste into code element.

I think there is room for improvement, especially in a use case which requires accounting for many possible variables (css/classes).

Depending on what you’re looping over or where it comes from, you could always pass an attribute to assign styling. Take the most common example of looping though a cpt. If you add a custom field to that cpt, you can output that in the section your repeating and then set up styles based on that.

The field could be a radio group for various layout or spacing options or whatever. Seems the most painless way to me anyway :slight_smile:

Something similar to this just with an acf field instead: How to set a background color based on post category - #2 by manc

1 Like

Looping over ACF Flexible Content manc, so assigning radio groups (for admins only) to each layout is a good workaround idea. Thanks for submitting a response :slight_smile:

@timmse - Trying to build a dynamic template based on ACF repeater fields. A very common case no doubt. The issue I have is similar because the tag assigned to the repeating element is indeed wrapping each element being repeated inside if that element itself does not have a repeater. An example of this:

On the front end, the element is wrapped inside the most-near parent’s HTML tag. It equates to a semantically messy DOM. I tried to pull the inner elements out, but I could not find any way to repeat without it being in a block/div with at least some HTML tag. Regardless of argument on if it matters or not for SEO or other purposes, it bloats the BOM and minimum, when all I want to do is repeat ‘p’ or ‘h2’ or ‘img’ tags inside of a repeater field being looped through.

Do you have any suggestions on how to queryloop just the actual inner elements without wrapping them in the outer element? I even tried custom code block to build the HTML myself, but alas, that code block does not allow a query loop. We need some query-loopable method on all elements, really. Why not allow a query loop on heading elements? On text elements? What does it hurt to allow that, vs just allowing it on “outer” structural elements? Is there any element that would let me do what I need to do? Is there a filter I can use to enable query looping on any element I want?

It doesn’t make sense right? If you’ve originally created layouts using code, the query loop should just be the equivalent of the PHP while() function. Instead it outputs a dom element.

This frustrated me to no end when I started working with ACF Flexible layouts, because my query loop was on the section element and depending on the layout, each section has different CSS attributes applied. Doesn’t work in this setup.

Therefore, I had to output a dumb section element, then apply all the section styling to the first inner tag to maintain good markup.

E.g Section > .container or .wrap or something.

I don’t think my answer directly addresses your issue, but maybe assists looking at things from a different perspective to solve the problem.

Ideally it would be cool to set a query loop but output no wrapper.

Similar to the code element. Or if you want, use the code element to write your ACF while function. That works too!

OR could a query loop be applied to the code element?

Aside. Gutenbricks is a cool solution for flexible layouts using Gutenberg.

1 Like

Yes a queryloop compatible, wrapper element with no code output is definitely necessary to accomplish several lists in an efficient way.

Currently you can’t build a calendar listing with month divider efficiently, due to this.
Related feature request

2 Likes

I still can’t build a calendar listing with dynamically added Headings as month divider. That’s the most frustrating part of Bricks as I already wasted many hours to overcome this issue. I am quite surprised that nearly nobody seems to use an advanced feature in a loop.

@Matej
It looks like this thread is in the archive and won’t be read anymore. Is there anything going on to drastically increase the possibilities with loops. A calendar listing can be implemented with a dead simple query of event posts sorted by date and a heading conditionally controlled via post data.

For proper HTML, you’d also need an element that opens a div tag below the month heading - then the events ul/li appear. And before the next month heading, the div tag is closed.

<div>
  <h2>Januar 2025</h2>
  <ul>
   <li>Event #1</li>
   <li>Event #3</li>
...
  </ul>
</div>
<div>
  <h2>Februar 2025</h2>
  <ul>
     <li>Event #5</li>
     <li>Event #6</li>
...
</div>

Hi @Maexxx,

my answer will probably not be what you wish to hear, but you will have to do this with nested query loops - then you can have the exact structure that you show in your post.

You will have to find a way to query only months, and then inside each month, events. Then you can achieve this.

Matej

Yeah, that’s not what I hoped and that means pagination is not possible then. And it requires overly complicated and inefficient loops, where a simple post query sorted by date would be sufficient.

I hope this shortcoming of Bricks query loops is adressed in an upcoming release. As it impedes so many possibilities that Bricks loop could be used for without the following restriction.

Suggestion
A loop element which outputs no HTML itself, just the elements placed inside. Then I’d place the card and a heading in that wrapper and conditionally enable the month divider heading.
In addition a code element which supports nesting of elements e.g. by placing a {nested_elements} tag in your PHP/HTML code and adding children items would fully satisfy the requirement for this.

These two things would simplify life with Bricks loops and loosen the chains it currently has. There are endless possibilities like dynamically inserting a static card at position 5 without CSS tricks, or following a specific post, which currently requires Javascript. Additionally complicated query loops can get much simpler, as in my example. This also reduces the need for some query options as simpler queries allow you to achieve more and as it should be - see my example which shrinks down to a single loop.

1 Like

Hi,
FYI, I’m trying to create Custom Element to “fix” this loop wrapping. Here’s my work, if someone is interested by helping me :wink:

1 Like

I also thought about creating a custom element, but I don‘t have much experience with it. Might give it a try.

Here‘s my follow up feature request, where related ideas can be discussed

Ok. Let me know if you want to share your code.