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

[Autocomplete][LiveComponent] Change not detected when using autocomplete_url in a dynamic form #1833

Closed
antoniovj1 opened this issue May 7, 2024 · 6 comments

Comments

@antoniovj1
Copy link

antoniovj1 commented May 7, 2024

I have a dynamic form with autocomplete functionality. The issue starts when I try to change the URL for autocompletion. I can see that the HTML changes, but Tom Select is not updated and is still querying the old URL.

When I use autocomplete with EntityType::class, it just works, but it's not useful in this case.

I think the main problem lies in the initialization of the mutationObserver in the autocomplete controller.

 initializeTomSelect() {
        if (this.selectElement) {
            this.selectElement.setAttribute('data-skip-morph', '');
        }
        if (this.urlValue) {
            this.tomSelect = __classPrivateFieldGet(this, _default_1_instances, "m", _default_1_createAutocompleteWithRemoteData).call(this, this.urlValue, this.hasMinCharactersValue ? this.minCharactersValue : null);
            return;
        }
        if (this.optionsAsHtmlValue) {
            this.tomSelect = __classPrivateFieldGet(this, _default_1_instances, "m", _default_1_createAutocompleteWithHtmlContents).call(this);
            return;
        }
        this.tomSelect = __classPrivateFieldGet(this, _default_1_instances, "m", _default_1_createAutocomplete).call(this);
        this.startMutationObserver();
    }

Because if we enter the this.urlValue, the observer is not started.

Here its my code:

 public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('typeId', EnumType::class, [
                'class' => RuleType::class,
            ])
            ->add('operator', EnumType::class, [
                'class' => QueryOperator::class,
            ])
            ->add('nextNodeOperator', EnumType::class, [
                'class' => JoinOperator::class,
            ]);

        $formModifier = function (FormInterface $form, ?RuleType $ruleType = null): void {
            if ($ruleType === null) {
                $ruleType = RuleType::TYPE_FAMILY;
            }

            if ($ruleType === RuleType::TYPE_FAMILY) {
                $route = $this->router->generate('app_entrypoint_api_search_by_family');
            }

            if ($ruleType === RuleType::TYPE_BRAND) {
                $route = $this->router->generate('app_entrypoint_api_search_by_brand');
            }

            if ($ruleType === RuleType::TYPE_ATTRIBUTE) {
                $route = $this->router->generate('app_entrypoint_api_search_by_attribute');
            }

            $form->add('values', ChoiceType::class, [
                'autocomplete' => true,
                'autocomplete_url' => $route,
                'multiple' => true,
            ]);
        };

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($formModifier): void {
                $data = $event->getData();
                $formModifier($event->getForm(), $data?->typeId());
            }
        );

        $builder->get('typeId')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) use ($formModifier): void {
                $ruleType = $event->getForm()->getData();
                $formModifier($event->getForm()->getParent(), $ruleType);
            }
        );
    }

It might be a bug in my code, but I've tried everything I could think of, and seeing with using an Entity instead of a URL works fine, I believe the problem must be related to what I've commented on.

Thanks.

@smnandre
Copy link
Collaborator

smnandre commented May 7, 2024

The issue starts when I try to change the URL for autocompletion

When you say "dynamic" form you're talking about those Event/listeners, or something else ? Is the rendered HTML correct ?

@antoniovj1
Copy link
Author

antoniovj1 commented May 7, 2024

Yes I'm talking about Event/Listeners, but I'm using also LiveComponents in the form (I'm not sure if is causing the issue)

The HTML looks fine for me, but the Tom Select behaviour is not ok. It starts using de TYPE_FAMILY route and when I change the type I can see de data attributes correctly updated.

But the autocomplete still using the FAMILY route.

This is the HTML at first:

<div class="col-3">
    <div>
        <label for="segment_form_filters_0_rules_0_values-ts-control" class="required" id="segment_form_filters_0_rules_0_values-ts-label">Valor</label>
        <select
            id="segment_form_filters_0_rules_0_values"
            name="segment_form[filters][0][rules][0][values][]"
            required="required"
            data-controller="symfony--ux-autocomplete--autocomplete"
            data-symfony--ux-autocomplete--autocomplete-url-value="/api/v1/search/family"
            data-symfony--ux-autocomplete--autocomplete-max-results-value="10"
            data-symfony--ux-autocomplete--autocomplete-loading-more-text-value="Loading more results..."
            data-symfony--ux-autocomplete--autocomplete-no-results-found-text-value="No results found"
            data-symfony--ux-autocomplete--autocomplete-no-more-results-text-value="No more results"
            data-symfony--ux-autocomplete--autocomplete-preload-value="focus"
            class="form-control form-control-solid tomselected ts-hidden-accessible"
            multiple="multiple"
            data-skip-morph=""
            tabindex="-1"
        ></select>
        <div class="ts-wrapper form-control form-control-solid multi plugin-remove_button plugin-virtual_scroll required invalid preloaded">
            <div class="ts-control">
                <input
                    type="text"
                    autocomplete="off"
                    size="1"
                    tabindex="0"
                    role="combobox"
                    aria-haspopup="listbox"
                    aria-expanded="false"
                    aria-controls="segment_form_filters_0_rules_0_values-ts-dropdown"
                    id="segment_form_filters_0_rules_0_values-ts-control"
                    aria-labelledby="segment_form_filters_0_rules_0_values-ts-label"
                />
            </div>
            <div class="ts-dropdown multi plugin-remove_button plugin-virtual_scroll" style="display: none; visibility: visible;">
                <div role="listbox" tabindex="-1" class="ts-dropdown-content" id="segment_form_filters_0_rules_0_values-ts-dropdown" aria-labelledby="segment_form_filters_0_rules_0_values-ts-label">
                    <div data-selectable="" data-value="5ba52e94-9c46-4c61-abd4-97f5560346eb" class="option" role="option" id="segment_form_filters_0_rules_0_values-opt-1">Accesorios de Jardinería</div>
                    <div data-selectable="" data-value="65776124-bb68-42e7-a527-966660f30c71" class="option" role="option" id="segment_form_filters_0_rules_0_values-opt-2">Piscinas y Mantenimiento</div>
                    <div data-selectable="" data-value="93430262-2e02-4fe0-8052-3091a04837db" class="option" role="option" id="segment_form_filters_0_rules_0_values-opt-8">Recambios y Accesorios Batidoras</div>
                    <div data-selectable="" data-value="0af5a430-e650-425e-ba19-5b3d085ce91c" class="option" role="option" id="segment_form_filters_0_rules_0_values-opt-10">Recambios y Accesorios Microondas</div>
                    <div class="no-more-results option">No more results</div>
                </div>
            </div>
        </div>
    </div>
</div>

And this is after changing TYPE_FAMILY to TYPE_BRAND:

<div class="col-3">
    <div>
        <label for="segment_form_filters_0_rules_0_values-ts-control" class="required" id="segment_form_filters_0_rules_0_values-ts-label">Valor</label>
        <select
            id="segment_form_filters_0_rules_0_values"
            name="segment_form[filters][0][rules][0][values][]"
            required="required"
            data-controller="symfony--ux-autocomplete--autocomplete"
            data-symfony--ux-autocomplete--autocomplete-url-value="/api/v1/search/brand"
            data-symfony--ux-autocomplete--autocomplete-max-results-value="10"
            data-symfony--ux-autocomplete--autocomplete-loading-more-text-value="Loading more results..."
            data-symfony--ux-autocomplete--autocomplete-no-results-found-text-value="No results found"
            data-symfony--ux-autocomplete--autocomplete-no-more-results-text-value="No more results"
            data-symfony--ux-autocomplete--autocomplete-preload-value="focus"
            class="form-control form-control-solid tomselected ts-hidden-accessible"
            multiple="multiple"
            data-skip-morph=""
            tabindex="-1"
        ></select>
        <div class="ts-wrapper form-control form-control-solid multi plugin-remove_button plugin-virtual_scroll required invalid preloaded">
            <div class="ts-control">
                <input
                    type="text"
                    autocomplete="off"
                    size="1"
                    tabindex="0"
                    role="combobox"
                    aria-haspopup="listbox"
                    aria-expanded="false"
                    aria-controls="segment_form_filters_0_rules_0_values-ts-dropdown"
                    id="segment_form_filters_0_rules_0_values-ts-control"
                    aria-labelledby="segment_form_filters_0_rules_0_values-ts-label"
                />
            </div>
            <div class="ts-dropdown multi plugin-remove_button plugin-virtual_scroll" style="display: none; visibility: visible;">
                <div role="listbox" tabindex="-1" class="ts-dropdown-content" id="segment_form_filters_0_rules_0_values-ts-dropdown" aria-labelledby="segment_form_filters_0_rules_0_values-ts-label">
                    <div data-selectable="" data-value="5ba52e94-9c46-4c61-abd4-97f5560346eb" class="option" role="option" id="segment_form_filters_0_rules_0_values-opt-1">Accesorios de Jardinería</div>
                    <div data-selectable="" data-value="65776124-bb68-42e7-a527-966660f30c71" class="option" role="option" id="segment_form_filters_0_rules_0_values-opt-2">Piscinas y Mantenimiento</div>
                    <div data-selectable="" data-value="93430262-2e02-4fe0-8052-3091a04837db" class="option" role="option" id="segment_form_filters_0_rules_0_values-opt-8">Recambios y Accesorios Batidoras</div>
                    <div data-selectable="" data-value="0af5a430-e650-425e-ba19-5b3d085ce91c" class="option" role="option" id="segment_form_filters_0_rules_0_values-opt-10">Recambios y Accesorios Microondas</div>
                    <div class="no-more-results option">No more results</div>
                </div>
            </div>
        </div>
    </div>
</div>

There yo can see that data-symfony--ux-autocomplete--autocomplete-url-value has been updated properly. But Tom Select has the old values and if I type in the input it use the wrong data-symfony--ux-autocomplete--autocomplete-url-value .

This is why I think it is related to the absence of the startMutationObserver call.

@antoniovj1
Copy link
Author

It's maybe related to this #1622 ? 🤔

@smnandre
Copy link
Collaborator

smnandre commented May 7, 2024

Yes there has sadly always been some issues between Autocomplete and LiveComponents.

As you can see in the issue you link, there is an ongoing PR regarding this.

Maybe you can see if you can check / help to finish it ? :)

@antoniovj1
Copy link
Author

antoniovj1 commented May 8, 2024

Are you talking about this PR #1512?

I think I don't have the knowledge to review it, but I can check if it fixes my use case and provide feedback.

@antoniovj1 antoniovj1 changed the title [Autocomplete] Change not detected when using autocomplete_url in a dynamic form [Autocomplete][LiveComponent] Change not detected when using autocomplete_url in a dynamic form May 8, 2024
@antoniovj1
Copy link
Author

I'm closing it as a duplicate of #1500

@antoniovj1 antoniovj1 closed this as not planned Won't fix, can't repro, duplicate, stale May 11, 2024
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

3 participants