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

How to have custom values in select dropdowns? #175

Closed
steinsag opened this issue Dec 8, 2020 · 9 comments
Closed

How to have custom values in select dropdowns? #175

steinsag opened this issue Dec 8, 2020 · 9 comments
Labels
Type: Question If you have questions about using ngqp

Comments

@steinsag
Copy link

steinsag commented Dec 8, 2020

In my form, I have a HTML select. The options have a custom value (UUIDs). However, which I normally set in template as follows:

<select class="custom-select" id="valueListKey" [formControl]="selectedKey" type="text" queryParamName="keyId">
    <option value=""></option>
    <option *ngFor="let key of keys" value="{{ key.id }}">
            {{ key.name }}
    </option>
</select>

In my component, I got:

selectedKey = new FormControl('');
this.paramGroup = queryParamBuilder.group({
    keyId: queryParamBuilder.stringParam('keyId', { emptyOn: '' }),
});

But when this is rendered in the browser, the options have a new value 1, 2, 3, ...

So I guess I somehow need to tell that I'm using custom values for my options. But how do I do that?

@steinsag steinsag added the Type: Question If you have questions about using ngqp label Dec 8, 2020
@Airblader
Copy link
Collaborator

Hi!

The ControlValueAccessor shipped with ngqp uses a numeric counter for the IDs and then correlates that back to the value (see e.g. https://github.com/TNG/ngqp/blob/master/projects/ngqp/core/src/lib/accessors/select-option.directive.ts#L24). This works on its own, since in the URL you can see that your custom value is used, not the numeric one.

The problem arises because you're also binding a FormControl against the select, and Angular's FormControl will inspect the value property (which is modified to the numeric counter by ngqp). Binding both Angular Forms controls and ngqp against the same element is problematic for some reasons, this is one of them, which is why it is discouraged.

If you really do need to have the value in a FormControl, instead of binding it to the element through the formControl directive, you can manually sync the values into it through something like

this.paramGroup.get('keyId').valueChanges.subscribe(v => this.selectedKey.setValue(v));

But in general I would recommend working directly with the QueryParamGroup itself and not proxy it through a form control.

@Airblader
Copy link
Collaborator

Side note: you could also avoid this by providing your own ControlValueAccessor, of course. Just like Angular Forms, ngqp will prioritize custom CVAs over its built-in ones when available.

@steinsag
Copy link
Author

steinsag commented Dec 8, 2020

Thank you @Airblader for your valuable feedback. So in general: When using NGQP, I shouldn't use reactive forms at all? Is that correct? This could also explain some other "problems" I'm seeing like that initial param values not being added to the form controls.

@Airblader
Copy link
Collaborator

Yes, that is correct. And I understand that it's unfortunate, but the way reactive forms and the CVA infrastructure work I can't see a way to make it work smoothly.

In the past I have been considering a separate API that makes it less/no boilerplate to synchronize reactive form controls from ngqp controls, and I'd still be open to doing so.

The original use case for ngqp when I wrote it was actually entirely orthogonal to reactive forms: either you want to submit something or you just want to synchronize to the URL, but not both. A submitted form synchronized to the URL would only have to do so on submission anyway, which is a much easier version of the problem ngqp solves (of doing so "in realtime"). I'm happy to support other uses cases where sensible, but a direct integration with reactive forms isn't something I think is possible until Angular has rewritten forms from scratch (and even then we'll have to see). But again, by programmatically synchronizing the param group to the reactive forms you can solve all of this for now, it's just a bit more work.

@Airblader
Copy link
Collaborator

Just to highlight it one more time, though: unless you have a really good reason to, maybe you don't even need a FormControl at all. ngqp offers much of the same APIs.

@steinsag
Copy link
Author

steinsag commented Dec 8, 2020

Mmmh, for me the most important benefit of using reactive forms are the built-in input validators. I got a lot of logic in that part of the code, so in my specific case I guess it will have to stick to reactive forms and come up with a custom solution for updating query params. But I will take a deep look at how NGQP keeps track of the query params :-)

Again, thank you for this great module and your time and support!

@Airblader
Copy link
Collaborator

This is somewhat related to #123. I didn't originally intend for something like "validation" because the core design decision for ngqp was to treat the URL as the source of truth, and a URL we don't really have control over (in the sense that a user can open any URL they want). That thinking is probably not really accurate, though, because of course a control can be invalid and still have that invalid value as its value (that's how Angular forms work, too).

I think this can still be done by wiring up either ngqp or the Angular form control and programmatically synchronizing the other one. It's boilerplate-y and not ideal, but if you need some of the options of ngqp it's probably easier to manage than setting it up yourself still (as mentioned, an API to make this boilerplate go away is something I'd be open for, too).

Again, thank you for this great module and your time and support!

Thanks! And sorry that this doesn't seem to be a great fit out of the box for this case. I really wish integrating with Angular forms would be easier. ;-)

I will close this issue for now given that it's an answered question, but of course feel free to keep replying / asking or opening new issues!

@steinsag
Copy link
Author

steinsag commented Dec 9, 2020

Sometimes sleep helps :-) Of course I can use NGQP, because for my list views with quick filters, I don't have validators. And in my forms to edit or create objects, I don't want to store this information in query params. So it works perfectly fine now after I removed the FormControls!

@Airblader
Copy link
Collaborator

Awesome! And exactly what ngqp was designed for. Glad it worked out in the end!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Question If you have questions about using ngqp
Projects
None yet
Development

No branches or pull requests

2 participants