Gbuomprisco / ngx-chips

Tag Input component for Angular
MIT License
903 stars 357 forks source link

onTagEdited not firing? #722

Open m-ghaoui opened 6 years ago

m-ghaoui commented 6 years ago

I'm submitting a ... (check one with "x")

[x] bug report => search github for a similar issue or PR before submitting
[ ] support request/question

Notice: feature requests will be ignored, submit a PR if you'd like

Current behavior I have a tag-input with (onTagEdited)="onTagEdited($event)". I double click on a tag, make changes, and the tag automatically reverts back to the old value.

Expected behavior I expect the onTagEdited event to fire and the tag to be renamed.

Minimal reproduction of the problem with instructions (if applicable)

What do you use to build your app?. Please specify the version "@angular/cli": "^1.7.3"

Angular version:

    "@angular/animations": "^5.2.9",
    "@angular/cdk": "^5.2.4",
    "@angular/common": "^5.2.9",
    "@angular/compiler": "^5.2.9",
    "@angular/core": "^5.2.9",
    "@angular/forms": "^5.2.9",
    "@angular/http": "^5.2.9",
    "@angular/material": "^5.2.4",
    "@angular/material-moment-adapter": "^5.2.4",
    "@angular/platform-browser": "^5.2.9",
    "@angular/platform-browser-dynamic": "^5.2.9",
    "@angular/router": "^5.2.9",

ngx-chips version: "ngx-chips": "^1.7.7"

Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ] Chrome 67.0.3389.0 (Official build) canary (64-bits) Firefox Quantum 59.0.2 (64-bits)

m-ghaoui commented 6 years ago

I reverted back to the version I used when I first wrote the code:

"ngx-chips": "1.6.2",

and the event does fire.

image

Gbuomprisco commented 6 years ago

Hi are you using a validator? Please post some code.

m-ghaoui commented 6 years ago

Sure,

Here is the relevant tag:

</form> <!-- Note, the form is above the tag-input -->

<tag-input [(ngModel)]="trainingTagsInTrainingList" [identifyBy]="'Guid'" [displayBy]="'Name'" [addOnBlur]="true" [clearOnBlur]="true"
    (onAdd)="onTagAdd($event)" (onRemove)="onTagRemove($event)" (onTagEdited)="onTagEdited($event)" placeholder="+Tag"
    secondaryPlaceholder="Voeg tag toe" [editable]="true">
    <tag-input-dropdown #tagInputDropDownTags [autocompleteItems]="trainingTagsList" [identifyBy]="'Guid'" [displayBy]="'Name'"
    [showDropdownIfEmpty]="true" [focusFirstElement]="false">
    </tag-input-dropdown>
</tag-input>

I do have a FormBuilder and a bunch of form fields with the formControlName tag.

But the <tag-input> is below the <form> element and uses [(ngModel)]. As far as I know, I am not using a validator in the <tag-input>.

The trainingsInTagList and trainingTagsList looks like this:

trainingTagsInTrainingList: GuidName[]; // The model
trainingTagsList: GuidName[]; // The values for the tag-input-dropdown

Event handlers:

public onTagAdd(item: GuidName) {
    this.addTag(item); 
}

public onTagRemove(item: GuidName) {
    this.removeTag(item);
}

public async onTagEdited(item: GuidName) {
    await this.renameTag(item); // <-- This line does not get hit in version 1.7.7, but it does get hit in version 1.6.2
}

GuidName class:

export class GuidName {
  Guid: string | undefined;
  Name: string | undefined;
  Selected: boolean;

  constructor(guid: string | undefined, name: string | undefined) {
    this.Guid = guid;
    this.Name = name;
    this.Selected = false;
  }
}

The onTagEdited() handler does not even get hit on version 1.7.7, but it does with 1.6.2.

Could it be because onTagEdited is async? It works in 1.6.2.

Gbuomprisco commented 6 years ago

I don't think being async is the problem (I tried this too). I introduced a feature to validate the tag when it gets edited: the behavior you see is exactly what happens when the validator detects an invalid tag, so for some reason the editing is not passing the validation.

I don't see problems in your code though and can't reproduce using a similar configuration to yours. Just to make sure, can you try v1.7.8? Also, it may seem silly, but the tag won't be added if the same one is already in the list, so make sure you're adding a new item

m-ghaoui commented 6 years ago

It does no seem to work. The line does not get hit.

"ngx-chips": "1.7.8",

Incidentally, this version does not work either,

"ngx-chips": "1.8.0",
m-ghaoui commented 6 years ago

Also, it may seem silly, but the tag won't be added if the same one is already in the list, so make sure you're adding a new item

I'm renaming it to a unique item. For example:

one two three ---> one, twooooooooooooooo, three. It jumps back to one, two, three

m-ghaoui commented 6 years ago

Here is the line being hit with version 1.6.2

image

Gbuomprisco commented 6 years ago

Can you upload an online reproduction of the issue? I haven't been able to reproduce

m-ghaoui commented 6 years ago

Ok. I'll try. You need to give me some time.

Gbuomprisco commented 6 years ago

Use stackblitz as in my demo, it's really quick :) you can fork the demo and start from there

renanmoraes commented 6 years ago

I think I'm having the same problem, I try to return the value to be put in the field but it does not work.

   <tag-input [onAdding]="transform"
            [validators]="validatorsTag"
            [errorMessages]="errorMessages"
            (onTagEdited)="onTagEdited($event)"
             (onSelect)="onSelect($event)"
             (onBlur)="onBlur()"
              [editable]="true"
              [identifyBy]="'hour'"
              [displayBy]="'hour'"
              formControlName="timesheet"
              theme="dark"
              placeholder="+ Horários"
              [secondaryPlaceholder]="'Adicione horários'"></tag-input>

onTagEdited(value): Observable<any> {
    const index = value.hour.indexOf(':');
    const reg = new RegExp('^[0-9]*$');
    console.log('tag', value)
    if (value.hour.length < 4 || !reg.test(value.hour)) {
      console.log(this.hourSelectedBeforeAlter)
      return Observable.of(this.hourSelectedBeforeAlter);
    }

    if (index === -1) {
      const val = value.hour.split('');
      const formated = {
        _id: (value._id) ? value._id : null,
        hour: val[0] + val[1] + ':' + val[2] + val[3]
      };
      return Observable.of(formated);
    } else {
      const val = value.split('');
      const formated = {
        _id: (value._id) ? value._id : null,
        hour: val[0] + val[1] + ':' + val[3] + val[4]
      };
      return Observable.of(formated);
    }
  }

Image and video hosting by TinyPic

You can observe that I select the item and change it, however according to my code it needs to return to the value that was previously in the code, I put consoles logs to make sure it would arrive correctly and it is, however at the moment of returning it does not work.

The behavior that I expect pe when put for example 22dd: 00 it returns to 22:00 because it is not a valid value.

ThalesMatoso commented 6 years ago

Some news on this case, but still with problems on this subject. Please ask for an opinion, I know it is not for you but it would be very interesting to do.

Gbuomprisco commented 6 years ago

@renanmoraes you're not going to be able to edit the tag using that hook. You will need onAdding

jsalvata commented 6 years ago

I've been suffering a bug which I believe is this same one: when using identifiers (different from the display strings) and a tag is edited, it is always found to be a duplicate of itself and the edit is undone.

One solution would be to skip duplicate checking when editing tags, since allowDupes is defined to "tags with the same value" -- so tags with the same display string should always be allowed.

The right solution for me, however, is to just check for duplicate display strings -- since that's what I want to avoid duplicating.

jsalvata commented 6 years ago

Just in case it helps anyone, I've worked around the issue by adding this to my component (apologies for the crudeness):

 ...
  @ViewChild('tagInput') private tagInput: TagInputComponent;
 ...
  ngOnInit() {
    (this.tagInput as any).findDupe= (function (this: any, tag: any): CustomerEmail | undefined {
      return this.items.find((item: any) => item.display === tag.display && item.value !== tag.value);
    }).bind(this.tagInput);
 ...
gelevanog commented 6 years ago

Any updates?

michgerts commented 6 years ago

Any updates?

designcouch commented 5 years ago

Would also love any updates on this. I can get the event to fire partially, but it seems to fire before the edit is complete, so the visible text in the tag changes, but the updated value returned does not.

Example: Tag "Ewok" is edited. The text now reads "Blue Ewok." When I include onTagEdited, the text changes to "Blue Ewok" but all other data in the html, and the value returned are still "Ewok"

andn99 commented 5 years ago

any updates for this issue. I'm still having it on ngx-chips: 2.0.2

michgerts commented 5 years ago

I would love to hear about updates or workarounds here.

anmolio commented 4 years ago

If you are using different values for [identifyBy] & [displayBy] ; once you edited the tag and enter the changes will be undone; using the same display and identify values will make it work!

truongtokiet commented 3 years ago

If you are using different values for [identifyBy] & [displayBy] ; once you edited the tag and enter the changes will be undone; using the same display and identify values will make it work!

I tried and it works. Many thank.