-
Notifications
You must be signed in to change notification settings - Fork 6.7k
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
feat(material/chips): prevent chips from being deleted when user holds backspace #19700
feat(material/chips): prevent chips from being deleted when user holds backspace #19700
Conversation
@mmalerba I've come across a pretty annoying edge case. It might be due to a shitty design (the flag), but maybe not. Currently, from within the This makes it so that when a chip is created, I don't flip the flag back to true, and a double backspace press is needed. I'll illustrate:
I would love for a review of the current method I'm using (the boolean flag). I can expose an observable from Currently I don't see this class exposed via public api in the normal chips, but I see it's exposed in the MDC code. |
@mmalerba perhaps this entire behaviour should be moved to and managed by |
I think the flag approach looks fine, but yeah I would suggest moving all of this logic into the input. If that turns out to be too difficult for some reason, it should be ok to add a new observable to |
@mmalerba good to hear. I’ll work on that today 👌🏻 Neither of the methods should be hard, I’d rather do the cleanest approach |
@mmalerba I have a question, don't quite know how to tackle this. When the user creates a new chip (via one of the separator keys, blur, etc), it's up to them to reset the input value, As shown in the chips demo in dev-app: add(event: MatChipInputEvent): void {
const {input, value} = event;
// Add our person
if ((value || '').trim()) {
this.people.push({ name: value.trim() });
}
// Reset the input value
if (input) {
input.value = '';
}
} I've tried getting notified about when this happens (the This is a problem we have regardless of whether the code is in Do you have any thoughts on how we can do that? diff --git a/src/material/chips/chip-input.ts b/src/material/chips/chip-input.ts
index cf4812683..116803cf2 100644
--- a/src/material/chips/chip-input.ts
+++ b/src/material/chips/chip-input.ts
@@ -187,6 +187,12 @@ export class MatChipInput implements MatChipTextControl, OnChanges, OnDestroy, A
}
if (!event || this._isSeparatorKey(event)) {
this.chipEnd.emit({ input: this._inputElement, value: this._inputElement.value });
+ setTimeout(() => {
+ if (this.empty) {
+ console.log('yay that worked');
+ this._focusLastChipOnBackspace = true;
+ }
+ }, 0);
if (event) {
event.preventDefault(); ☝🏻 this works for the normal case (where the user does not mess with the input willingly), and fixes this as long as the change to the input done in the event handling. Not sure if this is the prettiest fix, and AFAIK this will cause a bunch of change detections due to
|
Hmmm yeah this is a tricky one. What if in the chip-list you listen to changes in the child chips and call a method on the chip input to reset the flag whenever the children change? |
@mmalerba problem here is that it's not about whether the chip was actually added to the list or not, but whether the input value was changed by messing with the dom element itself. I'm thinking about all kinds of RxJS flows I can do with the input events and whatnot, but from my testing - this change does not raise an event, as I stated above. Any chance there's another component in the library that had to deal with a similar issue? Is there someone I can ask, or perhaps you can give me directions to what kind of behaviour I should look for in other components to find that myself? |
The only way I can think of to detect when the input's value is programatically set would be to use You're right that resetting it when the chips change isn't exactly right, but in practice when the user types a separator character the input will be reset and a chip will be added, so it does cover the most common case. To cover other edge cases people might have I would just add a Does this sound like a good approach to you? |
822f42e
to
692580c
Compare
692580c
to
c1543a3
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.
Thanks for picking this back up, couple small things and it should be good to go.
src/material/chips/chip-input.ts
Outdated
/** Represents an input event on a `matChipInput`. */ | ||
export interface MatChipInputEvent { | ||
/** The native `<input>` element that the event is being fired for. */ | ||
input: HTMLInputElement; | ||
|
||
/** The value of the input. */ | ||
value: string; | ||
|
||
/** Call to clear the value of the input */ | ||
clearInput(): 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.
rather than having the clearInput
method on the event, how about adding a reference to the MatChipInput
and putting the method on the directive instead. Then people would do something like this: event.chipInput.clear()
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.
Good idea! will change it 👍🏻
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.
What about the input itself? the HTMLInputElement
... should it still be part of the event?
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 remove it without going through a deprecation period. You can mark it as deprecated:
/**
* @deprecated use `chipInput.inputElement`
* @breaking-change 13.0.0 remove this property.
*/
(You'll need to change _inputElement
on MatChipInput
to public and remove the underscore)
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.
Does the MDC-based one need to be updated as well or does it share the same underlying code? I would think at least the tests for the MDC-based chips need to be updated to add the same tests that were added for the non-MDC chips
@mmalerba time I worked on this you (I think) said that it was okay to not deal with the MDC implementation. If it is necessary now I'll take a look. I'm pretty sure its not the same underlying code, but it's only an assumption. What say you? Should I take a look? |
Ah, yeah since the time you started we've started to roll out the MDC-based components inside Google as an initial test before eventually moving them out of experimental. We'll need to make sure it works in the MDC one too so teams don't experience a regression as they migrate |
Awesome. I’ll definitely take a look. Any helpful pointers for someone
who’s not seen MDC based components?
…On Tue, 16 Feb 2021 at 22:43 mmalerba ***@***.***> wrote:
Ah, yeah since the time you started we've started to roll out the
MDC-based components inside Google as an initial test before eventually
moving them out of experimental. We'll need to make sure it works in the
MDC one too so teams don't experience a regression as they migrate
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#19700 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ADITO6EWNQLY4WLZOKQLEJTS7LKI3ANCNFSM4ODCLSZQ>
.
|
IIRC MDC didn't have built in support for connecting the chips with an input, so we just built that part on top, in Angular. That should mean that you don't have to worry too much about the MDC stuff going on in the background. If you do wind up needing to dive deeper into the MDC details, the "advanced approach" described in the MDC docs explains the approach we use to integration. And you can find the code for the MDC chips here. |
I'm looking at the code now, honestly it seems mostly copy-pasted, so it should be somewhat straightforward. I'm looking for any significant differences, so far it looks good. |
It looks like there are a number of failures that will need to be investigated |
Oh interesting! If there’s anything I can do to help investigate it, please
let me know!
…On Mon, 1 Mar 2021 at 20:00 mmalerba ***@***.***> wrote:
It looks like there are a number of failures that will need to be
investigated
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#19700 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ADITO6FV2OQXZUNFRPX45UDTBPI5NANCNFSM4ODCLSZQ>
.
|
So part of the problem appears to be people passing objects like interface MatChipInputEvent {
/**
* The native `<input>` element that the event is being fired for.
* @deprecated Use `MatChipInputEvent#chipInput.inputElement` instead.
* @breaking-change 13.0.0 This property will be removed.
*/
input: HTMLInputElement;
/** The value of the input. */
value: string;
/**
* Reference to the chip input that emitted the event.
* @breaking-change 13.0.0 This property will be made required.
*/
chipInput?: MatChipInput;
} In our examples, you can then just assert that Lets try that and see how the tests go after |
Got it, will try to find a couple of minutes to make the changes 👌🏻
…On Thu, 4 Mar 2021 at 1:40 mmalerba ***@***.***> wrote:
So part of the problem appears to be people passing objects like {input:
..., value: ...} to functions that expect MatChipInputEvent. In order to
make this change less breaking, I suggest changing MatChipInputEvent like
this:
interface MatChipInputEvent {
/** * The native `<input>` element that the event is being fired for. * @deprecated Use `MatChipInputEvent#chipInput.inputElement` instead. * @Breaking-Change 13.0.0 This property will be removed. */
input: HTMLInputElement;
/** The value of the input. */
value: string;
/** * Reference to the chip input that emitted the event. * @Breaking-Change 13.0.0 This property will be made required. */
chipInput?: MatChipInput;}
In our examples, you can then just assert that chipInput is defined like
this: event.chipInput!.clear().
Lets try that and see how the tests go after
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#19700 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ADITO6E4EP66NUY7X52F2YLTB3CFVANCNFSM4ODCLSZQ>
.
|
…focus-last-chip-on-backspace-v2
I re-ran it with the fix applied and most of the errors went away. It looks like there's one more issue: When using the MDC chips the typing on |
I’ll have to check that, it sounds too dumb 😂 I’ll be done with driving in
two hours or so, I’ll apply the fix then.
Thanks man!
…On Thu, 4 Mar 2021 at 20:25 mmalerba ***@***.***> wrote:
I re-ran it with the fix applied and most of the errors went away. It
looks like there's one more issue: When using the MDC chips the typing on
MatChipInputEvent#chipInput is wrong because it refers to the non-MDC
MatChipInput. The fix should be pretty straightforward. Instead of
re-exporting the same interface from the non-MDC chips in the MDC package,
just give MDC package its own version of the interface and export that
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#19700 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ADITO6CJEJANZVLRFUQFOGDTB7GATANCNFSM4ODCLSZQ>
.
|
Hey man, I looked at the code and I can't seem to find the behavior you're describing.
Perhaps someone that was using the MDC chips accidentally imported the non-MDC interface? |
Sorry about that, you're right. That project must've been doing something weird. I'll see if I can fix their app so we can get this in. |
Hey @mmalerba 👋🏻 And update on that? |
My shift as the team's release manager starts tomorrow, I plan to look into it then |
Oh ok ok, unfortunately I’m not aware of your internal team working, but
good to know.
Thanks again, have a good day and good luck with whatever 😅
Btw, just out of curiosity, how many PRs are you going to be in-charge of?
Or like - how many PRs on average do you have to keep up with?
…On Wed, 10 Mar 2021 at 0:51 mmalerba ***@***.***> wrote:
My shift as the team's release manager starts tomorrow, I plan to look
into it then
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#19700 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ADITO6FW5TMMOGHQXD4EC7LTC2J6XANCNFSM4ODCLSZQ>
.
|
I ran the tests again after making some fixes to internal apps and everything passed, so I'll merge this today. We currently have ~150 PRs that could be merged if they didn't cause failures of some kind in Google's codebase. For some of those cases the tests are finding legitimate issues with the PR, but for others it may just be a matter of the tests needing to be updated. That's why it can sometimes take a long time to merge PRs that look like they're ready to go on Github. |
Thanks for the hard work on this! 🎉 |
Thank you for helping me get this merged, your time is obviously invaluable, and I appreciate your responsiveness on this. I've not experienced this in even smaller repos, so what you do is definitely not taken for granted. Hope I'll find more opportunities to contribute! |
…ser holds backspace (angular#19700)" This reverts commit 6230560.
@gioragutt Unfortunately I had to revert this. It broke a team that was using a custom version of the chips input. I'll ask them to investigate and fix it so we can roll forward |
@mmalerba got it. As always, let me know if there's anything I can help with 👍🏻 I'm available for whatever is needed. |
…d when user holds backspace (angular#19700)"" This is a roll-forward of the original PR. We will need to resolve the issues in Google's code base that caused it to be reverted before merging again. This reverts commit 4381b8e.
… deleted when user holds backspace (angular#19700)""
… deleted when user holds backspace (angular#19700)""
#22235) * Revert "Revert "feat(material/chips): prevent chips from being deleted when user holds backspace (#19700)"" This is a roll-forward of the original PR. We will need to resolve the issues in Google's code base that caused it to be reverted before merging again. This reverts commit 4381b8e. * fixup! Revert "Revert "feat(material/chips): prevent chips from being deleted when user holds backspace (#19700)"" * fixup! Revert "Revert "feat(material/chips): prevent chips from being deleted when user holds backspace (#19700)""
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Edge Cases:
Fixes: #18659