FormWidget with relation inside a repeater

Hello,

I decided to create a new ticket for this, as I couldn’t change the title and the category of my recent one:

Either I did something completely wrong or I just achieved the almost impossible:
A formWidget with a relation inside a repeater :sweat_smile:

I know, that I could have simply chosen a color picker for inside my repeater and always put the same HEX color code there, but I wanted to have it convenient and sometimes if something gets stuck in my head, I can’t leave it…

Anyway, I’m not going to show my whole code. If somebody is interested in more details, please let me know.

I achieved my goal this way:

I have three tables, one for the basic data, like title, content and the upper part of the repeater field, called basics.

Basic data table:

$table->increments('id')->unsigned();
$table->string('title');
$table->string('slug');
$table->text('content');
$table->text('basics')->nullable();

Repeater formWidget colors table to save the colors from the repeater field into another table:

$table->integer('project_id')->unsigned();
$table->text('form_widget_pivot_color');

Check that I called the second field something with pivot. As long as I understand it correct, this is not a pivot table. I just left the name, because I wanted to start with this idea.

And then I simply have my colors table:

$table->increments('id')->unsigned();
$table->string('name');
$table->string('color_value');

In my PivotColor (again wrong naming) formWidget PHP, I first build the field name of every color checkbox. This was the hardest part for me. A field name could look like that:

Project[basics][136][_pivot_color][0][2]

Check that 136 is the model id, so it’s an update. Otherwise this number must be 0. Then the second zero is the repeater index (so it’s the first repeater item) and then the last 2 is the second checkbox (there I took the color primary id). One has to put this string also inside a hidden input in the rendered partial, as long as I understood it correctly.

I needed to apply this field name string with javascript, as I couldn’t get the repeater index in the formWidget. I tried to get an instance id of the created class, but I failed. Check that I needed the repeater index, as for second last item in the field name string. I just echoed the mostly right name string and fixed it with JS.

Then I check in my formWidget, if there is already a basic entry belonging to a formWidget color DB entry. If so, I set a uuid and build an array with all values, which I then echo in a hidden input in my partial. Check that I think I needed to create an uuid, because otherwise all values would have been overwritten by the last repeater entry. Then I was able to set the values of the checkboxes and the hidden inputs with JS.

In my Project model, I clean out the basics data for the basic data table and save the repeater color data in my other table. Check that all of the repeater color data are coming inside the first basics entry. So if there are three repeater fields, the save values would look like this:

^ array:4 [▼ 0 => array:2 [▼ "name" => "12a" "url" => "1234" ] 1 => array:1 [▼ "_pivot_color" => array:3 [▼ 0 => array:3 [▼ 1 => "1" 2 => "0" 3 => "0" ] 1 => array:3 [▼ 1 => "0" 2 => "0" 3 => "0" ] 2 => array:3 [▼ 1 => "1" 2 => "2" 3 => "0" ] ] ] 2 => array:2 [▼ "name" => "12b" "url" => "333" ] 3 => array:2 [▼ "name" => "12c" "url" => "22" ] ] 

I now need to test again and fix the only thing, that is not working yet properly: the JS isn’t initialized at every time, for example, when I create a new entry.

1 Like

I got rid of the pivot color table and save now my colors values properly inside basics row.

The only thing that bothers me, is that it was really hard to implement a listener after opening the project form (changing from one form to another). I use again a PerformanceObserver and I even needed to do an own MutationObserver with setTimeout :man_facepalming:

Well, as I’m not that ashamed of my code anymore, so I thought I could share it:

Please be aware, that I still need to test everything properly again. But I will have this repository up to date.

I somehow didn’t get the new OC Turbo Router. I was able to get rid of the PerformanceObserver by using:

addEventListener('render', function() {
    // Page has rendered something new
});

My GitHub repository got updated.