Ability to have Depth for Repeater/RepeaterMatrix Items #1906

Closed
jlahijani opened this Issue Jul 3, 2016 · 12 comments

Projects

None yet

3 participants

@jlahijani
jlahijani commented Jul 3, 2016 edited

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
Owner

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

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

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

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.

@ryancramerdesign
Owner

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

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
Owner

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
Owner

I've gone ahead and added support for repeater depth in this commit on the core dev branch:
processwire/processwire@e2f9597

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

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

@ryancramerdesign
Owner

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

@jlahijani jlahijani closed this Dec 7, 2016
@ryancramerdesign
Owner

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment