ryancramerdesign / ProcessWire

Our repository has moved to https://github.com/processwire – please head there for the latest version.
https://processwire.com
Other
727 stars 199 forks source link

Ability to have Depth for Repeater/RepeaterMatrix Items #1906

Closed jlahijani closed 7 years ago

jlahijani commented 8 years ago

I'm not sure if this would be too specific to be a RepeaterMatrix feature, but I figured I'd throw it out there.

With RepeaterMatrix, you have the ability to build matrix-types (which are basically components) and it achieves a page builder like functionality, which is absolutely great.

However, the ability to have a completely custom grid with which those components exist in is not entirely possible. BUT, if you think it through, RepeaterMatrix can actually do that through some clever thinking and in a way that I think isn't too intrusive to its current purpose.

Imagine you made 3 matrix types called Container, Column, and Row. Now you can insert these types around your component types and fashion a grid.

The only drawback is that Repeater/RepeaterMatrix items do not have any built-in concept of depth, therefore everything appears on the same level. If the concept of depth could be a part of Repeater Items, this can open up some more possibilities in how you use the field. Perhaps this depth capability can be turned off by default.

Do not confuse this with nesting of Repeaters, but rather faux nesting. WordPress's menu builder works on this exact concept and they've figured out all the required JavaScript. :)

Here's a screenshot of an example result:

x2

Remember, the only feature I'm proposing is the ability to have the concept of depth and the necessary backend JavaScript/CSS to make that happen (of which WP's menu system is based on).

I am not proposing specific matrix types, a grid builder, specific fields or frontend output. That is solely up to the developer to configure on their own. Having depth opens up some possibilities and really solves the on-the-fly grid builder approach (especially once Live Preview is supported for Repeaters in ProDrafts).

Thoughts?

ryancramerdesign commented 8 years ago

Thanks, sounds interesting. Though I'm not sure I fully understand where/how one would use this. Is it to build some kind of table output on the front end? Could the same be accomplished by just adding a Page or Options field within the repeater items where you can choose the nesting level? Help me understand the use case here? :)

jlahijani commented 8 years ago

The thought process is how can ProcessWire achieve a "page builder" similar to the breed of page/grid builders that are popping up all over the place, like BeaverBuilder for WP (arguably the best one).

The way I see it, those page builders are a combination of 2 fundamental things: (1) a grid builder (2) a components system

Having a visual grid builder ultimately forces these page builders to adopt a grid system / CSS framework. This goes directly against what PW is all about... being completely markup agnostic (which is one of many reasons to love PW).

RepeaterMatrix essentially is a components system. So that covers point 2 above. But, it doesn't have the ability to have these components laid-out on a page within an on-the-fly grid.

So, the question becomes, how do you do that?

Limiting Example Method 1 One immediate and simple way you could do it is like this... let's say I have 2 matrix types that I want to add to a page and have them be displayed side-by-side on the frontend. You could simply add a field on each matrix type representing its grid/column width, but the downsides are (1) forces you to build in grid management in the matrix-types themselves (2) not visually apparent on the backend.

Limiting Example Method 2 Another way I've tried (and realized the limitations of) is to do the following:

  1. Create a Repeater called "Row"
  2. Create another Repeater inside the "Row" Repeater calling it "Column"
  3. Create a field inside this "Column" repeater to represent the column width. So let's say you want this column to be 3 units wide (based on a 12 column grid)... then you'd simply have an integer field where the user inputs their desired width.
  4. Create another field and put it inside the "Column" repeater... it would be a RepeaterMatrix called "Components".

So what you have is: Repeater ("Row") -> Repeater ("Column") -> RepeaterMatrix ("Components... bodycopy, accordion, etc.")

This works, but it's problematic. The reason why is because if you create a Component (which is inside a Repeater which is inside a Repeater) and then want to move that component to a different part of your grid, you can't given understandable and necessary limitations. It's also clunky and visually difficult to work with as a content editor.

Proposed Solution The way around this is to avoid nesting of repeaters when building a grid structure. This way, you can easily drag things around since they are not nested in the traditional sense. Having depth and makes it visually easier to understand on the backend, and provides the marker of how to output one's grid and components on the frontend.

Django CMS's page builder is based on this concept. Please visit the demo: https://control.aldryn.com/demo/get-new/

Then click the "Edit Page" button on top right, then click the "Structure" button on top right to see the feature. It's very similar to what RepeaterMatrix already is but with grid capability.

My feature suggestion is simply for the concept of depth and leave the rest (frontend output, components, etc.) to the site developer.

gmclelland commented 8 years ago

I think what you are saying is that you want nested repeaters and for those repeaters to be collapsible on the backend? Is that correct?

image

jlahijani commented 8 years ago

It depends what you mean by the word "nested repeaters".

ProcessWire can already handle "real" nested repeaters. The problem with "real" nested repeaters is that you can't move a nested repeater item to another parent repeater. The screenshot you provided, in the context of ProcessWire, is not using "real" nested repeaters, but instead a Repeater (well RepeaterMatrix technically) with the ability for the repeater items to have depth.

It's fake nesting... fake depth, which is what I'm proposing.

WordPress's menu builder works on the same concept behind the scenes.

jlahijani commented 8 years ago

Video demo: https://drive.google.com/open?id=0B0x_4Nn3mU3dbFVnX2ZjUzlXQWs

ryancramerdesign commented 7 years ago

Just circling back on this. Seems like good ideas you've got here and perhaps we should go ahead and implement it as an option available for repeater and repeater matrix fields. I'll start looking into it here, but since it looks like you've done some work with it already, wanted to check how far you'd gone on the code side?

jlahijani commented 7 years ago

Hey Ryan. Whatever I did in that video demo was merely hacking some things together to demonstrate the point and nothing "clean". It's also within the limitations of the Repeater/RepeaterMatrix, meaning if you have a Repeater within a Repeater, then the nested repeater items cannot be moved from one parent repeater to another parent repeater. I think if that problem is solved, then the approach I described in this thread is not necessary.

ryancramerdesign commented 7 years ago

It's also within the limitations of the Repeater/RepeaterMatrix, meaning if you have a Repeater within a Repeater, then the nested repeater items cannot be moved from one parent repeater to another parent repeater. I think if that problem is solved, then the approach I described in this thread is not necessary.

I don't think dragging between actual nested repeaters would be possible. Or if it was, it would probably be overwhelming to code and maintain, not to mention a nightmare for the user to configure. What I like about your solution is that it seems realistic to implement, would be easy for the user to configure and code around (it's all in 1 repeater/matrix field), and quite useful for the scenarios you described. I'll experiment here and see what I can come up with.

ryancramerdesign commented 7 years ago

I've gone ahead and added support for repeater depth in this commit on the core dev branch: https://github.com/processwire/processwire/commit/e2f9597c5af561b2aea2373b1cd213c30be9155d

This uses your idea exactly as you presented, except for the depth movement, which uses the existing "drag" icon, so that it supports horizontal drag in addition to the existing vertical drag. This works in either regular repeaters or matrix. To enable depth, edit the repeater field settings and you'll see a new input where you can specify a max depth. Once enabled and editing any repeater field, you can drag items to set depth from 0 to the max configured.

To retrieve depth on the front-end, just access the repeater item's "depth" property, or call the getDepth() function:

foreach($page->repeater as $item) {
  $depth = $item->depth; // this
  $depth = $item->getDepth(); // or this
}

To set depth on the API side, you can use the $item->setDepth($n) method, and then save the item.

I'm interested to know if this all sounds consistent with what you were looking for in the original proposal? Thanks. –Ryan

jlahijani commented 7 years ago

I just tested it out and it's pretty much what I envisioned. Thank you!

ryancramerdesign commented 7 years ago

Great! Thanks for the idea. I think a lot of people will like this, as it seems to have a lot of potential uses.

ryancramerdesign commented 7 years ago

@jlahijani I pushed an update that makes the horizontal drag/drop of the items (to set depth) work a lot better. It was pretty inconsistent before. So if you'd started playing with it at all, make sure to grab the newer commit from today.

gmclelland commented 6 years ago

@jlahijani and @ryancramerdesign Do you have any code examples of how you would output a RepeaterMatrix field with depth on the frontend?

Like with the example image that is provided? image

I'm guessing the code posted on http://processwire.com/api/modules/profields/repeater-matrix/#repeater-matrix-from-the-api wouldn't quite cover it?

gmclelland commented 6 years ago

I just read the post about depth at https://processwire.com/blog/posts/pw-3.0.44-repeaters/, but I'm still confused on how I can output this with PHP?

adrianbj commented 6 years ago

Honestly not meaning to be a wise guy at all, but did you try the php snippet that Ryan showed in that blog post?

$depth = -1;
foreach($page->repeater_items as $item) {
  if($item->depth > $depth) {
    echo "<ul>";
  } else if($item->depth < $depth) {
    echo "</ul>";
  }
  echo "<li>$item->title";
  $depth = $item->depth;
}
while($depth--) echo "</ul>";

Otherwise you can make something with more "custom" logic where you check the value of $item->depth and return it however you want based on whether it's 0, 1, 2, 3 etc.

Maybe if you explain exactly what you are trying to do we can help a little better. Maybe a forum post would be better at this point?

gmclelland commented 6 years ago

No, I haven't tried yet. I didn't think that code would work because it is using <ul> elements. In the picture above, you may have different html elements based on the RepeaterMatrix item type. Maybe I'm just over analyzing it?

I agree, this probably should be posted in a forum post. I'll type one up.

Thanks Adrian!

adrianbj commented 6 years ago

I didn't think that code would work because it is using

    elements. In the picture above, you may have different html elements based on the RepeaterMatrix item type.

True - that is why you will probably need to roll your own based on the content and how you need to output it. The principal of check the value of the depth property is still the same though.

gmclelland commented 6 years ago

Just adding https://processwire.com/talk/topic/18370-how-to-output-repeatermatrix-items-with-depth/ this as a reference in case someone comes here looking.