-
-
Notifications
You must be signed in to change notification settings - Fork 372
[Autocomplete]: implement group_by option on Entity Autocompleter results #481
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi!
Really sorry for the slow review - this someone slipped past me! I've left some comments, but this is excellent work and I would love to incorporate it when you have some time to make these changes.
Thanks!
Hi @weaverryan 👋 Thank you for this feedback, I will make the changes following your comments. |
57f8236
to
c7996df
Compare
sorry for the small setback, I had some difficulties on the rebase of the branch 2.x :( I had to do a force push because of my merge error. |
7418dd6
to
c5fe12a
Compare
Here are the changes after rebase and the pagination supports. |
Hi @weaverryan, what should we do with this pr ? I have however tried to be reactive because we are waiting for this feature. |
Maybe if |
I think that's an excellent idea. It would make the PR a lot safer to merge 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry again for being late on this. Let us know if it is possible to use the "old format" if group_by
is not set.
Cheers!
/** | ||
* Return group_by option. | ||
*/ | ||
public function getGroupBy(): mixed; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of physically adding this method, which would break BC, add some documentation to the top for it: https://github.com/SymfonyCasts/reset-password-bundle/blob/6601f15fce7a4934bc9570f76feaf1b93536b1a7/src/ResetPasswordHelperInterface.php#L19 - that will allow people to be aware of it, and then we will add the actual method whenever we release a new major version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also is the return value really mixed? Or is it ?string
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes i think, It can be string, callable or null
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is QUITE the long list of things :). I think we could probably just use null|string|callable
. Then, if someone passes a PropertyPath
or GroupBy
in a form, inside of WrappedEntityTypeAutocompleter
, we could "normalize" those into a string|callable
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm struggling to see how to normalize this, how do you see the implementation of this normalization
c5fe12a
to
28c5cea
Compare
Hello, I made some changes to keep the old format if the group_by option is not set. Would you have some time to give some feedback ? |
9fb1380
to
fcdafdd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is VERY close now - let's push it across the finish line!
src/Autocomplete/CHANGELOG.md
Outdated
@@ -1,5 +1,22 @@ | |||
# CHANGELOG | |||
|
|||
## 2.8.0 | |||
|
|||
- Added support for using `Option Group`: the JSON format with option groupe takes two entries |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Added support for using `Option Group`: the JSON format with option groupe takes two entries | |
- Added support for using [OptionGroups](https://tom-select.js.org/examples/optgroups/). |
And then I don't think we need to show the JSON format below. 99% of people won't care about this - it's just handled for them :)
@@ -142,20 +142,21 @@ export default class extends Controller { | |||
// VERY IMPORTANT: use 'function (query, callback) { ... }' instead of the | |||
// '(query, callback) => { ... }' syntax because, otherwise, | |||
// the 'this.XXX' calls inside this method fail | |||
load: function (query: string, callback: (results?: any) => void) { | |||
load: function (query: string, callback: (options?: any, optgroups?: any) => void) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After a little digging, it looks like this callback as a type:
load: function (query: string, callback: (options?: any, optgroups?: any) => void) { | |
load: function (query: string, callback: TomLoadCallback) { |
The TomLoadCallback
can be imported from 'tom-select/dist/types/types'
like 3 other types already. Then, for the .catch()
on line 154, it would become:
.catch(() => callback([], []));
to satisfy this type.
{ "value": "1", "text": "Pizza" }, | ||
{ "value": "2", "text":"Banana"} | ||
] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is not valid anymore, right?
And we need docs for the new option :)
$results[] = [ | ||
'value' => $autocompleter->getValue($entity), | ||
'text' => $autocompleter->getLabel($entity), | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor, but I think we should "exit early" first if there is no group by. Basically:
if (null === $groupBy = $autocompleter->getGroupBy()) {
// use the old logic
$results = [];
foreach ($paginator as $entity) {
$results[] = [
'value' => $autocompleter->getValue($entity),
'text' => $autocompleter->getLabel($entity),
];
}
return $results;
}
Then the code that handles $groupBy
can continue without needing to be in an else statement (no else
will be needed at all).
/** | ||
* Return group_by option. | ||
*/ | ||
public function getGroupBy(): mixed; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is QUITE the long list of things :). I think we could probably just use null|string|callable
. Then, if someone passes a PropertyPath
or GroupBy
in a form, inside of WrappedEntityTypeAutocompleter
, we could "normalize" those into a string|callable
.
} | ||
} | ||
|
||
if (\is_callable($groupBy)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's not a callable at this point, that would be an error, right? I'm imagining that we check for null
and string
above (and for string, you're converting into a callable). So we could say:
if (!\is_callable($groupBy)) {
// then throw an exception
}
*/ | ||
public function __construct( | ||
public array $results, | ||
public array $options, | ||
public array $optgroups, | ||
public bool $hasNextPage, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't break BC here, even though it's unlikely to cause problems. So:
A) Rename $options
back to $results
B) Move $optgroups
to the final argument and make it optional
Then, let's move the getResults()
logic into the controller. That'll keep this class dead-simple - just a carrier of data.
@@ -23,7 +27,8 @@ final class AutocompleteResultsExecutor | |||
{ | |||
public function __construct( | |||
private DoctrineRegistryWrapper $managerRegistry, | |||
private ?Security $security = null | |||
private PropertyAccessorInterface $propertyAccessor, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To protect BC and trigger a deprecation, we can make the top of the class look something like this:
final class AutocompleteResultsExecutor
{
private PropertyAccessorInterface $propertyAccessor;
private ?Security $security;
public function __construct(
private DoctrineRegistryWrapper $managerRegistry,
$propertyAccessor,
/* Security $security = null */
) {
if ($propertyAccessor instanceof Security) {
trigger_deprecation('symfony/ux-autocomplete', '2.8.0', 'Passing a "%s" instance as the second argument of "%s()" is deprecated, pass a "%s" instance instead.', Security::class, __METHOD__, PropertyAccessorInterface::class);
$this->security = $propertyAccessor;
$this->propertyAccessor = new PropertyAccessor();
} else {
$this->propertyAccessor = $propertyAccessor;
$this->security = func_num_args() >= 3 ? func_get_arg(2) : null;
}
}
99069c0
to
a5b8c55
Compare
Thank you @jvancoillie for this wonderful feature and your excellent work. Apologies for the slow merge on my end - but I'm super excited to happen (I just tried it locally and it was super fun) |
Add possibility to group results (with
group_by
option) on ajax autocomplete result