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

[4.0][Feature] Matrix field type (aka repeatable, aka multiply) #131

Closed
tabacitu opened this issue Sep 23, 2016 · 15 comments
Closed

[4.0][Feature] Matrix field type (aka repeatable, aka multiply) #131

tabacitu opened this issue Sep 23, 2016 · 15 comments

Comments

@tabacitu
Copy link
Member

I just thought of something, which changes everything [kidding, it would only change the need for this field type, I just like to make fun of Apple :-) ]. A medium-term functionality I had in mind was what I used to call "matrix fields". Like the "array" field should do for the "text" fields, the "matrix" fields would allow you to make an array of any type of field, and let the admin add more and reorder them.

I now think the name is pretty lame and that it shouldn't be included as a type of field, but maybe it makes more sense, rather than have an array field for text fields, to have an option on ALL field types.

So you'd just add some new optional attributes to your field's definition, something like:

"matrix" => 2, // the number of items shown by default
"matrix_limit" => 5, // the maximum number of items the user is allowed to have in this matrix

And this would:

  • show the label only once;
  • show the hint only once;
  • show the actual field 2 times (with all other attributes you specified);
  • show a + button;
  • allow you to reorder the fields;
  • set the input names to name[] instead of name;
  • on create/update, it would store the values as JSON in the database, in the order you placed them in;

Wouldn't this be an awesome awesome feature?

@tabacitu tabacitu added this to the 3.3 - extras milestone Sep 23, 2016
@tabacitu
Copy link
Member Author

On the other hand, that "matrix" field option would NOT allow you to create matrixes of different field types. So it won't allow you to create, say, a repeatable "widget" for a person, that includes:

  • name
  • title
  • email
  • photo
  • bio

So maybe the matrix functionality should be implemented differently, something like:

$this->crud->addField([ // matrix
    'label' => "Team Members",
    'name' => "team_members",
    'type' => 'matrix',
    'default_size' => 2,
    'maximum_size' => 5,
    'fields' => [
      ['name' => 'name', 'label' => "Name", 'type' => 'text'],
      ['name' => 'title', 'label' => "Title", 'type' => 'text'],
      ['name' => 'email', 'label' => "Email", 'type' => 'email'],
      ['name' => 'photo', 'label' => "Photo", 'type' => 'browse'],
      ['name' => 'bio', 'label' => "Bio", 'type' => 'textarea']
    ]
]);

With the some advantages:

  • we might successfully do it as a non-breaking-change;
  • can contain multiple types of fields;

It does however pose a few questions:

  • how do you do validation for those sub-fields? team_members.name[]?
  • how would the interface look?

...food for thought.

@OwenMelbz
Copy link
Contributor

So as it happens, I needed something similar to this when we were talking about the array field types and have already got a solution that works for my project, it however doubles up as the array field type.

I'll push to a new branch so you can check it out soon

@OwenMelbz
Copy link
Contributor

Here is what I've been doing

#132

@tabacitu
Copy link
Member Author

What you've shown there is awesome for an "array" field type. But they key difference in what I imagine the "matrix" field type to be is that it allows some fields to be of other types (number, wysiwyg, image, etc) - and the "array" field type you've pushed does not.

I think it would be clear if we have these two fields:

  • array (the one you've pushed, only has text fields);
  • custom_array (the "matrix" field, it allows different types of inputs);

Right?

@OwenMelbz
Copy link
Contributor

Sure :) I did actually like the idea of the field types, which we could implement into the array style one if we wanted, but the full matrix one could become complicated with the layout if you're thinking of things like image uploaders and wysiwyg.

@tabacitu
Copy link
Member Author

Agreed. Let's table it for now. We'll see if we can include it in v4.

@b8ne
Copy link
Contributor

b8ne commented Jul 16, 2017

Hey @tabacitu @OwenMelbz ive been absent from laravel for a while, im at a new job and they use Craft sigh.
The 1 benefit of Craft is the use of matrix fields though, so im currently looking to build a matrix model for laravel (backpack) so that it is more like a CMS framework. I know backpack isnt a CMS framework, but with this addon it will have all of the features of one and still allow the dev to use vanilla laravel.
Craft allows various content blocks to be created ie. 3 col block, 4 col block, 2 col and image block. The cms user can then add as many of these blocks as they want and reorder them as sections to build an entire page.
I was thinking this could be done with a whole bunch of json, but that would get messy real quick.
Im thinking the best option would be to make this as an addon package. I would then include 2 migrations, 1 to create a content block table which would store each block saved (would need to have the field values as json), and another table to store crud models on content blocks as a many to many relationship.
Structure of the content blocks would still all be defined in the CrudController.
ie.

[
                'name' => 'matrix_1', // Not a DB col, Used for targeting if multiple matrices are used together
                'type' => 'matrix',
                'label' => 'Content Blocks',
                'max' => 0, // The maximum number of content blocks allowed, 0 for infinite
                'blocks' => [
                    [
                        'name' => 'imageLeftBlock',
                        'label' => 'Image Left Block',
                        'fields' => [
                            [ // image
                                'label' => "Col 1 Image",
                                'name' => "image",
                                'type' => 'image',
                                'upload' => true,
                                'crop' => true,
                                'aspect_ratio' => 4.1,
                            ],
                            [
                                'label' => 'Col 2',
                                'type' => 'ckeditor',
                                'name' => 'col_2',
                            ],
                        ]
                    ],
                    [
                        'name' => '3_col_block',
                        'label' => '3 Col Block',
                        'fields' => [
                            [
                                'label' => 'Col 1',
                                'type' => 'ckeditor',
                                'name' => 'col_1',
                            ],
                            [
                                'label' => 'Col 2',
                                'type' => 'ckeditor',
                                'name' => 'col_2',
                            ],
                            [
                                'label' => 'Col 3',
                                'type' => 'ckeditor',
                                'name' => 'col_2',
                            ],
                        ]
                    ]
                ]
]

Im keen to get this done in the next couple of weeks so maybe discuss further on gitter to get the ball rolling?

@OwenMelbz
Copy link
Contributor

Fine by me :) Although just to clarify - I think what you're suggesting seems to be more of a "page builder" in my eyes to have a flexible content system? rather than a repeatable field that can have different content types in?

@tabacitu
Copy link
Member Author

@b8ne - sounds like something Backpack's missing. Go for it! My advice - try to build the most basic package, launch it and get feedback from the community ASAP. Otherwise you could end up spending a lot of time building something of little interest. Happened to me a number of times :-)

@aripekkako
Copy link

aripekkako commented Dec 13, 2017

It thinks this is a very flexible & useful feature that would be a great addition to Backpack.

This sort of functionality is very common & popular in the WordPress world. Pretty much all the major custom field implementations support this. E.g. Advanced custom fields (1+ milloin active installations) has Repeater and Flexible content fields.

@xavinci
Copy link

xavinci commented Mar 28, 2018

@tabacitu Hey Christian! Saw that you're in Romania... met my wife in Romania in Constanta 10 years ago :-) Beautiful area.

Is there a beta or semi-working version of the proposed Matrix field that I could get my hands on? Or, has anyone in this thread been successful in accomplishing this sort of function? @aripekkako? The Repeater/Flexible Content solutions would be perfect in Laravel Backpack.

@tabacitu
Copy link
Member Author

Hi @simplusgroup ,

I'm originally from Romania, yes, but don't hold it against me :-) I don't identify much as a Romanian - as BS as that sounds, so I'm away half the time. I agree, beautiful country, but poorly managed.

There's isn't any working version that I know of, unfortunately. It is a very very important feature, though, so it is coming in 3.5 or 4.0. We will support this, in a beautiful way, but not at the moment. Until then, you could start from the table field and create a custom one for your need... I'm afraid that's all I got for you.

Cheers!

@b8ne
Copy link
Contributor

b8ne commented Mar 29, 2018

Hey @simplusgroup I spent a day on this a while ago. Got pretty far in terms of templating - its actually pretty simple to setup arrays of fields in the Controller then iterate over them in the view template. The main blocking issue I found was the way we currently handle JS and CSS. A lot of it is injected at compile time and set to run on DOM ready/load, so it cant be re-used when you "add" another field dynamically.
IMO we should hold off this just a little until the issue of asset management is sorted, so then the fields can be rebuilt with the new strategy and matrix in mind. - (no point rebuild all the fields to make a matrix work and then rebuild them all again down the track to suit a new asset preprocessor system).

@aripekkako
Copy link

I have a solution neither and agree with @b8ne that the full solution should be using the new asset management feature.

I've diven into the WordPress Advanced Custom Fields implementation quite deeply in my former job and from that experience I can say that all fields that use JavaScript to initilize something (like a date picker) need to take the matrix implementation into consideration, if it is going to work. This is because the field duplication has to be done with JavaScript and when the duplication is done, all the related JavaScript plugins need to be initialized. Essentially this means that there needs to be some sort of an event that is triggered when the fields are rendered that the JS-initialization can then be connected to.

Looking forward to @tabacitu beautiful implementation. ;)

@tabacitu tabacitu removed this from the 3.3 - all major issues fixed milestone Nov 27, 2019
@tabacitu tabacitu reopened this Nov 27, 2019
@tabacitu tabacitu changed the title [Breaking change] Matrix field option [4.0][Feature] Matrix field type Nov 27, 2019
@tabacitu tabacitu changed the title [4.0][Feature] Matrix field type [4.0][Feature] Matrix field type (aka repeatable, aka multiply) Nov 27, 2019
@tabacitu
Copy link
Member Author

iu

We finally have a PR for this! We've been using it in client projects for a while now, it has no known bugs and it should be pretty stable. But it needs extensive testing, before we can release it for thousands of projects to use.

Let's move the conversation in the PR please: #2266

This was referenced Apr 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants