updating the whitelist on scroll event of the suggestion dropdown
Arnaves opened this issue · 12 comments
Brakebein can you guide me in updating the whitelist on scroll event of the suggestion dropdown
I'm not sure what you are extactly trying to achieve. You can listen to the dropdown scroll event as provided by Tagify. However, it will only fire if there is a scrollbar within the dropdown.
settings: TagifySettings = {
callbacks: {
'dropdown:scroll': (event) => {
// do something with respect to the scroll percentage
console.log(event.detail.percentage);
}
}
}
The dropdown:scroll
event won't fire, if there is nothing to scroll. If I understand your needs correctly, you have (maybe) 3 suggestion items and want to update them, when the user uses his mouse wheel, for example. Then you need to listen to the wheel
event of the dropdown element. Use the TagifyService
to gain full access to the Tagify instance.
ngAfterViewInit() {
this.tagifyService.get('test').DOM.dropdown.addEventListener('wheel', (event) => {
if (event.deltaY > 0) {
// scrolled down
} else if (event.deltaY < 0) {
// scrolled up
}
});
// or with rxjs
fromEvent(this.tagifyService.get('test').DOM.dropdown, 'wheel')
.subscribe((event) => {
console.log(event.deltaY);
});
}
Does this lead you into the right direction?
Yes sir,
settings: TagifySettings = {
callbacks: {
'dropdown:scroll': (event) => {
// do something with respect to the scroll percentage
console.log(event.detail.percentage);
}
}
}
This will do it and scroll is always active in my case.
Also how do i detect the scroll has hit the end of scroll bar to call the next set of data.
If event.detail.percentage
equals or is above 100, then you hit the end of the scrollbar. Then you can load the next set of suggestions.
Here is some code to start with. If the user scrolled down to the end of the dropdown, then the next 10 suggestion items will be appended to the list.
private suggestionList = ['A# .NET', 'A# (Axiom)', 'A-0 System', 'A+', '...']; // sample list from https://yaireo.github.io/tagify/
private length = 0;
whitelist$ = new BehaviorSubject<string[]>([]);
ngAfterViewInit() {
// called once to set the first 10 suggestions
this.loadSuggestions();
// listen to scroll event
// throttled so loadSuggestions() won't called twice accidently
fromEvent(this.tagifyService.get('test'), 'dropdown:scroll')
.pipe(throttleTime(50, asyncScheduler, { leading: false, trailing: true }))
.subscribe((event: CustomEvent<Tagify.DropDownScrollEventData>) => {
if (event.detail.percentage >= 100) {
this.loadSuggestions();
}
});
}
private loadSuggestions() {
// increase by 10
this.length += 10;
// set new whitelist
this.whitelist$.next(this.suggestionList.slice(0, this.length));
// update rendererd suggestion list
const tagify = this.tagifyService.get('test');
tagify.dropdown.refilter.call(tagify);
}
settings: TagifySettings = {
maxTags: 3,
enforceWhitelist: true,
placeholder: 'Start Typing...',
autoComplete:{
enabled:true,
rightKey:false,
},
editTags: false,
dropdown: {
maxItems: Infinity, // <- mixumum allowed rendered suggestions
classname: 'tags-look', // <- custom classname for this dropdown, so it could be targeted
enabled: 0, // <- show suggestions on focus
closeOnSelect: false, // <- do not hide the suggestions dropdown once an item has been selected
},
callbacks: {
'dropdown:scroll': (e) => {
// do something with respect to the scroll percentage
console.log(e.detail.percentage);
},
},
};
there is no output on scroll do I need to add something to HTML element as well?
Yes, I also recognized it. That's why I listened to it with fromEvent
in ngAfterViewInit
. For me, it seems to be a bug in the Tagify library. I cannot find dropdown:scroll
among the other event names: https://github.com/yairEO/tagify/blob/master/src/tagify.js#L66
You could open an issue there regarding this missing event name.
So
ngAfterViewInit() {
// called once to set the first 10 suggestions
this.loadSuggestions();
// listen to scroll event
// throttled so loadSuggestions() won't called twice accidently
fromEvent(this.tagifyService.get('test'), 'dropdown:scroll')
.pipe(throttleTime(50, asyncScheduler, { leading: false, trailing: true }))
.subscribe((event: CustomEvent<Tagify.DropDownScrollEventData>) => {
if (event.detail.percentage >= 100) {
this.loadSuggestions();
}
});
}
this will work?
Well, it worked in my small testbed.
ngAfterViewInit() {
const tagifyques = this.tagifyService.get('tagsques');
fromEvent(tagifyques, 'dropdown:scroll')
.pipe(throttleTime(50, asyncScheduler, { leading: false, trailing: true }))
.subscribe((event: CustomEvent<Tagify.DropDownScrollEventData>) => {
if (event.detail.percentage >= 100) {
this.appendWhitelistquesn();
}
});
}
errors:
const tagifyques: Tagify<TagData>
Argument of type 'Tagify' is not assignable to parameter of type 'FromEventTarget'.
Type 'Tagify' is not assignable to type 'JQueryStyleEventEmitter'.
Types of property 'on' are incompatible.
Type '<K extends keyof EventDataMap>(event: K, callback: (event: CustomEvent<EventDataMap[K]>) => void) => Tagify<...>' is not assignable to type '(eventName: string, handler: Function) => void'.
Types of parameters 'event' and 'eventName' are incompatible.
Type 'string' is not assignable to type 'keyof EventDataMap'.
No overload matches this call.
Overload 1 of 5, '(observer?: PartialObserver | undefined): Subscription', gave the following error.
Argument of type '(event: CustomEvent<Tagify.DropDownScrollEventData>) => void' is not assignable to parameter of type 'PartialObserver | undefined'.
Property 'complete' is missing in type '(event: CustomEvent<Tagify.DropDownScrollEventData>) => void' but required in type 'CompletionObserver'.
Overload 2 of 5, '(next?: ((value: unknown) => void) | undefined, error?: ((error: any) => void) | undefined, complete?: (() => void) | undefined): Subscription', gave the following error.
Argument of type '(event: CustomEvent<Tagify.DropDownScrollEventData>) => void' is not assignable to parameter of type '(value: unknown) => void'.
Types of parameters 'event' and 'value' are incompatible.
Type 'unknown' is not assignable to type 'CustomEvent<DropDownScrollEventData>'.ts(2769)
I'm not sure, why TypeScript is moaning about this. It doesn't do so in my example code. Tagify doesn't fully match the type that is expected by fromEvent
.
You can try to add @ts-ignore
above this line to ignore type checking:
// @ts-ignore
fromEvent(this.tagifyService.get('test'), 'dropdown:scroll')
Or set "strict": false
in your `tsconfig.json:
"compilerOptions": {
"strict": false
}
Alternatively, you can still listen to the event this way:
this.tagifyService.get('test').on('dropdown:scroll', event => {
console.log(event.detail.percentage);
});
this.tagifyService.get('test').on('dropdown:scroll', event => {
console.log(event.detail.percentage);
});
this worked with ngAfterViewInit() though the appending happens once, when the dropdown is closed and opened again the append again works
another help ,how to add the first suggestion on pressing tab
I think you would need to override the respective dropdown callback. The code for case 'Tab'
would have to be the same as 'Enter'
, alternatively Tab
could fall through to Enter
.
https://github.com/yairEO/tagify/blob/master/src/parts/dropdown.js#L303-L376
You can try to override this way (I haven't tested it this time):
const tagify = this.tagfiyService('test');
// @ts-ignore - because dropdown.events.callback is not on the type declarations
tagify.dropdown.events.callback.onKeyDown = function (e) {
// no arrow function, since `this` is used and refers to the tagify instance
// copy code and change `case 'Tab':` appropriately
}
Since this is all @yaireo/tagify related and less ngx-tagify, you might want to address your issues there: https://github.com/yairEO/tagify/issues The developer knows his code best.
ngx-tagify is only a wrapper for Angular, it only exposes the most common things. That's why there is the TagifyService
to get the core Tagify instance, for those who want to deeper customize it. In this case, you can directly refer to @yaireo/tagify