From f988ec3934ecc99598f264c2c27ebb7455237f8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harri=20H=C3=A4iv=C3=A4l=C3=A4?= Date: Thu, 10 Apr 2025 10:30:53 +0300 Subject: [PATCH 1/2] WIP: sorting for live component --- .../src/Form/Type/LiveCollectionType.php | 60 +++++++++++++++++++ src/LiveComponent/src/LiveCollectionTrait.php | 40 +++++++++++++ .../templates/form_theme.html.twig | 6 ++ 3 files changed, 106 insertions(+) diff --git a/src/LiveComponent/src/Form/Type/LiveCollectionType.php b/src/LiveComponent/src/Form/Type/LiveCollectionType.php index 2fc3aea95f3..c1a54742fdf 100644 --- a/src/LiveComponent/src/Form/Type/LiveCollectionType.php +++ b/src/LiveComponent/src/Form/Type/LiveCollectionType.php @@ -35,6 +35,14 @@ public function buildForm(FormBuilderInterface $builder, array $options): void $prototype = $builder->create('delete', $options['button_delete_type'], $options['button_delete_options']); $builder->setAttribute('button_delete_prototype', $prototype->getForm()); } + + if ($options['allow_sort']) { + $moveUpPrototype = $builder->create('move_up', $options['button_move_up_type'], $options['button_move_up_options']); + $builder->setAttribute('button_move_up_prototype', $moveUpPrototype->getForm()); + + $moveDownPrototype = $builder->create('move_down', $options['button_move_down_type'], $options['button_move_down_options']); + $builder->setAttribute('button_move_down_prototype', $moveDownPrototype->getForm()); + } } public function buildView(FormView $view, FormInterface $form, array $options): void @@ -92,6 +100,53 @@ public function finishView(FormView $view, FormInterface $form, array $options): array_splice($entryView->vars['button_delete']->vars['block_prefixes'], 1, 0, 'live_collection_button_delete'); } } + + // Add move up and move down buttons + if ($form->getConfig()->hasAttribute('button_move_up_prototype')) { + $prototype = $form->getConfig()->getAttribute('button_move_up_prototype'); + + $prototypes = []; + foreach ($form as $k => $entry) { + $prototypes[$k] = clone $prototype; + $prototypes[$k]->setParent($entry); + } + + foreach ($view as $k => $entryView) { + $entryView->vars['button_move_up'] = $prototypes[$k]->createView($entryView); + + $attr = $entryView->vars['button_move_up']->vars['attr']; + $attr['data-action'] ??= 'live#action'; + $attr['data-live-action-param'] ??= 'moveCollectionItemUp'; + $attr['data-live-name-param'] ??= $view->vars['full_name']; + $attr['data-live-index-param'] ??= $k; + $entryView->vars['button_move_up']->vars['attr'] = $attr; + + array_splice($entryView->vars['button_move_up']->vars['block_prefixes'], 1, 0, 'live_collection_button_move_up'); + } + } + + if ($form->getConfig()->hasAttribute('button_move_down_prototype')) { + $prototype = $form->getConfig()->getAttribute('button_move_down_prototype'); + + $prototypes = []; + foreach ($form as $k => $entry) { + $prototypes[$k] = clone $prototype; + $prototypes[$k]->setParent($entry); + } + + foreach ($view as $k => $entryView) { + $entryView->vars['button_move_down'] = $prototypes[$k]->createView($entryView); + + $attr = $entryView->vars['button_move_down']->vars['attr']; + $attr['data-action'] ??= 'live#action'; + $attr['data-live-action-param'] ??= 'moveCollectionItemDown'; + $attr['data-live-name-param'] ??= $view->vars['full_name']; + $attr['data-live-index-param'] ??= $k; + $entryView->vars['button_move_down']->vars['attr'] = $attr; + + array_splice($entryView->vars['button_move_down']->vars['block_prefixes'], 1, 0, 'live_collection_button_move_down'); + } + } } public function configureOptions(OptionsResolver $resolver): void @@ -105,8 +160,13 @@ public function configureOptions(OptionsResolver $resolver): void 'button_add_options' => [], 'button_delete_type' => ButtonType::class, 'button_delete_options' => [], + 'button_move_up_type' => ButtonType::class, + 'button_move_up_options' => [], + 'button_move_down_type' => ButtonType::class, + 'button_move_down_options' => [], 'allow_add' => true, 'allow_delete' => true, + 'allow_sort' => true, 'by_reference' => false, ]); } diff --git a/src/LiveComponent/src/LiveCollectionTrait.php b/src/LiveComponent/src/LiveCollectionTrait.php index 70f11f23b8b..6bc0e167a7f 100644 --- a/src/LiveComponent/src/LiveCollectionTrait.php +++ b/src/LiveComponent/src/LiveCollectionTrait.php @@ -46,6 +46,46 @@ public function removeCollectionItem(PropertyAccessorInterface $propertyAccessor $propertyAccessor->setValue($this->formValues, $propertyPath, $data); } + #[LiveAction] + public function moveCollectionItemUp(PropertyAccessorInterface $propertyAccessor, #[LiveArg] string $name, #[LiveArg] int $index): void + { + if ($index <= 0) { + return; + } + + $propertyPath = $this->fieldNameToPropertyPath($name, $this->formName); + $data = $propertyAccessor->getValue($this->formValues, $propertyPath); + + if (!\is_array($data) || !isset($data[$index]) || !isset($data[$index - 1])) { + return; + } + + // Swap the current item with the one above it + $temp = $data[$index - 1]; + $data[$index - 1] = $data[$index]; + $data[$index] = $temp; + + $propertyAccessor->setValue($this->formValues, $propertyPath, $data); + } + + #[LiveAction] + public function moveCollectionItemDown(PropertyAccessorInterface $propertyAccessor, #[LiveArg] string $name, #[LiveArg] int $index): void + { + $propertyPath = $this->fieldNameToPropertyPath($name, $this->formName); + $data = $propertyAccessor->getValue($this->formValues, $propertyPath); + + if (!\is_array($data) || !isset($data[$index]) || !isset($data[$index + 1])) { + return; + } + + // Swap the current item with the one below it + $temp = $data[$index + 1]; + $data[$index + 1] = $data[$index]; + $data[$index] = $temp; + + $propertyAccessor->setValue($this->formValues, $propertyPath, $data); + } + private function fieldNameToPropertyPath(string $collectionFieldName, string $rootFormName): string { $propertyPath = $collectionFieldName; diff --git a/src/LiveComponent/templates/form_theme.html.twig b/src/LiveComponent/templates/form_theme.html.twig index 1042510f2f9..4349883469a 100644 --- a/src/LiveComponent/templates/form_theme.html.twig +++ b/src/LiveComponent/templates/form_theme.html.twig @@ -10,4 +10,10 @@ {%- if button_delete is defined and not button_delete.rendered -%} {{ form_row(button_delete) }} {%- endif -%} + {%- if button_move_up is defined and not button_move_up.rendered -%} + {{ form_row(button_move_up) }} + {%- endif -%} + {%- if button_move_down is defined and not button_move_down.rendered -%} + {{ form_row(button_move_down) }} + {%- endif -%} {%- endblock live_collection_entry_row -%} From 7e5557dbcf40729c3eed365b13bd32a9862688cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harri=20H=C3=A4iv=C3=A4l=C3=A4?= Date: Thu, 10 Apr 2025 10:39:16 +0300 Subject: [PATCH 2/2] Coding standard --- .../src/Form/Type/LiveCollectionType.php | 8 ++++---- src/LiveComponent/src/LiveCollectionTrait.php | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/LiveComponent/src/Form/Type/LiveCollectionType.php b/src/LiveComponent/src/Form/Type/LiveCollectionType.php index c1a54742fdf..7c34d7e6e38 100644 --- a/src/LiveComponent/src/Form/Type/LiveCollectionType.php +++ b/src/LiveComponent/src/Form/Type/LiveCollectionType.php @@ -35,11 +35,11 @@ public function buildForm(FormBuilderInterface $builder, array $options): void $prototype = $builder->create('delete', $options['button_delete_type'], $options['button_delete_options']); $builder->setAttribute('button_delete_prototype', $prototype->getForm()); } - + if ($options['allow_sort']) { $moveUpPrototype = $builder->create('move_up', $options['button_move_up_type'], $options['button_move_up_options']); $builder->setAttribute('button_move_up_prototype', $moveUpPrototype->getForm()); - + $moveDownPrototype = $builder->create('move_down', $options['button_move_down_type'], $options['button_move_down_options']); $builder->setAttribute('button_move_down_prototype', $moveDownPrototype->getForm()); } @@ -100,7 +100,7 @@ public function finishView(FormView $view, FormInterface $form, array $options): array_splice($entryView->vars['button_delete']->vars['block_prefixes'], 1, 0, 'live_collection_button_delete'); } } - + // Add move up and move down buttons if ($form->getConfig()->hasAttribute('button_move_up_prototype')) { $prototype = $form->getConfig()->getAttribute('button_move_up_prototype'); @@ -124,7 +124,7 @@ public function finishView(FormView $view, FormInterface $form, array $options): array_splice($entryView->vars['button_move_up']->vars['block_prefixes'], 1, 0, 'live_collection_button_move_up'); } } - + if ($form->getConfig()->hasAttribute('button_move_down_prototype')) { $prototype = $form->getConfig()->getAttribute('button_move_down_prototype'); diff --git a/src/LiveComponent/src/LiveCollectionTrait.php b/src/LiveComponent/src/LiveCollectionTrait.php index 6bc0e167a7f..354e0b0ec98 100644 --- a/src/LiveComponent/src/LiveCollectionTrait.php +++ b/src/LiveComponent/src/LiveCollectionTrait.php @@ -52,19 +52,19 @@ public function moveCollectionItemUp(PropertyAccessorInterface $propertyAccessor if ($index <= 0) { return; } - + $propertyPath = $this->fieldNameToPropertyPath($name, $this->formName); $data = $propertyAccessor->getValue($this->formValues, $propertyPath); - + if (!\is_array($data) || !isset($data[$index]) || !isset($data[$index - 1])) { return; } - + // Swap the current item with the one above it $temp = $data[$index - 1]; $data[$index - 1] = $data[$index]; $data[$index] = $temp; - + $propertyAccessor->setValue($this->formValues, $propertyPath, $data); } @@ -73,16 +73,16 @@ public function moveCollectionItemDown(PropertyAccessorInterface $propertyAccess { $propertyPath = $this->fieldNameToPropertyPath($name, $this->formName); $data = $propertyAccessor->getValue($this->formValues, $propertyPath); - + if (!\is_array($data) || !isset($data[$index]) || !isset($data[$index + 1])) { return; } - + // Swap the current item with the one below it $temp = $data[$index + 1]; $data[$index + 1] = $data[$index]; $data[$index] = $temp; - + $propertyAccessor->setValue($this->formValues, $propertyPath, $data); }