MurhafSousli / ngx-scrollbar

Custom overlay-scrollbars with native scrolling mechanism
https://ngx-scrollbar.netlify.app/
MIT License
618 stars 99 forks source link

`scrollViewport` directive removes custom CSS classes applied on the viewport element #505

Closed hakimio closed 9 months ago

hakimio commented 1 year ago

Reproduction

Steps to reproduce:

  1. Assign scrollViewport directive to your own div
  2. Set some CSS class on that element:
    <ng-scrollbar>
    <div 
    scrollViewport
    class="foo-bar"
    >
     <!-- CONTENT -->
    </div>
    </ng-scrollbar>

Expected Behavior

The class "foo-bar" is retained on the element.

Actual Behavior

scrollViewport directive overrides all CSS classes and foo-bar class is removed.

Environment

hakimio commented 1 year ago

Following line causes the issue: https://github.com/MurhafSousli/ngx-scrollbar/blob/c265c3c9f9889d0c9231f121db1faf12ac114419/projects/ngx-scrollbar/src/lib/scroll-viewport.ts#L112 It should prepend existing CSS classes instead of just replacing them.

hakimio commented 1 year ago

I can use viewClass input as a workaround, but being able to set the class directly on my div would be a lot more intuitive.

hakimio commented 1 year ago

@MurhafSousli you fix did not work. For some reason += assignment of the class name doesn't seem to work.

Here is some debugging I did. Your code with some console logs:

console.log('class name:', this.nativeElement.className);

this.nativeElement.className += `ng-native-scrollbar-hider ng-scroll-viewport ${customClassName}`;
// Check if the custom viewport has only one child and set it as the content wrapper
if (this.nativeElement.firstElementChild) {
    this.contentWrapperElement = this.nativeElement.firstElementChild;
    this.contentWrapperElement.classList.add('ng-scroll-content');
}
console.log('new class name:', this.nativeElement.className);

Output:

class name: my-class-name
new class name: viewportng-native-scrollbar-hider ng-scroll-viewport 

If I slightly modify the code:

console.log('class name:', this.nativeElement.className);

this.nativeElement.className = `${this.nativeElement.className} ng-native-scrollbar-hider ng-scroll-viewport ${customClassName}`;
// Check if the custom viewport has only one child and set it as the content wrapper
if (this.nativeElement.firstElementChild) {
    this.contentWrapperElement = this.nativeElement.firstElementChild;
    this.contentWrapperElement.classList.add('ng-scroll-content');
}
console.log('new class name:', this.nativeElement.className);

I get correct result:

class name: my-class-name
new class name: my-class-name ng-native-scrollbar-hider ng-scroll-viewport
hakimio commented 1 year ago

Ok, found out what's the issue. You are missing a space. Following doesn't work:

this.nativeElement.className += `ng-native-scrollbar-hider ng-scroll-viewport ${customClassName}`;

but this works:

// space before ng-native-scrollbar-hider
this.nativeElement.className += ` ng-native-scrollbar-hider ng-scroll-viewport ${customClassName}`;