• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atinc / ngx-tethys / 68ef226c-f83e-44c1-b8ed-e420a83c5d84

28 May 2025 10:31AM UTC coverage: 10.352% (-80.0%) from 90.316%
68ef226c-f83e-44c1-b8ed-e420a83c5d84

Pull #3460

circleci

pubuzhixing8
chore: xxx
Pull Request #3460: refactor(icon): migrate signal input #TINFR-1476

132 of 6823 branches covered (1.93%)

Branch coverage included in aggregate %.

10 of 14 new or added lines in 1 file covered. (71.43%)

11648 existing lines in 344 files now uncovered.

2078 of 14525 relevant lines covered (14.31%)

6.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

3.9
/src/autocomplete/overlay/autocomplete.service.ts
1
import { getFlexiblePositions, ThyAbstractOverlayService } from 'ngx-tethys/core';
2
import { of, Subject } from 'rxjs';
3
import { takeUntil } from 'rxjs/operators';
4

5
import { Directionality } from '@angular/cdk/bidi';
6
import { coerceArray, coerceElement } from '@angular/cdk/coercion';
7
import {
8
    ComponentType,
9
    FlexibleConnectedPositionStrategy,
10
    Overlay,
11
    OverlayConfig,
12
    OverlayContainer,
13
    OverlayRef,
14
    PositionStrategy,
15
    ScrollDispatcher
16
} from '@angular/cdk/overlay';
17
import { Platform } from '@angular/cdk/platform';
18
import { ComponentPortal } from '@angular/cdk/portal';
19
import { ViewportRuler } from '@angular/cdk/scrolling';
20
import { DOCUMENT } from '@angular/common';
1✔
21
import { ElementRef, Injectable, Injector, NgZone, OnDestroy, StaticProvider, TemplateRef, inject } from '@angular/core';
UNCOV
22

×
UNCOV
23
import { ThyAutocompleteContainer } from './autocomplete-container.component';
×
UNCOV
24
import { ThyAutocompleteRef, ThyInternalAutocompleteRef } from './autocomplete-ref';
×
UNCOV
25
import { THY_AUTOCOMPLETE_DEFAULT_CONFIG, ThyAutocompleteConfig } from './autocomplete.config';
×
UNCOV
26
import { autocompleteAbstractOverlayOptions } from './autocomplete.options';
×
UNCOV
27

×
28
/**
29
 * @private
30
 */
×
31
@Injectable()
32
export class ThyAutocompleteService
UNCOV
33
    extends ThyAbstractOverlayService<ThyAutocompleteConfig, ThyAutocompleteContainer>
×
34
    implements OnDestroy
35
{
UNCOV
36
    private scrollDispatcher = inject(ScrollDispatcher);
×
UNCOV
37
    private ngZone = inject(NgZone);
×
UNCOV
38
    private _viewportRuler = inject(ViewportRuler);
×
UNCOV
39
    private _document = inject(DOCUMENT);
×
UNCOV
40
    private _platform = inject(Platform);
×
UNCOV
41
    private _overlayContainer = inject(OverlayContainer);
×
42

43
    private readonly ngUnsubscribe$ = new Subject();
UNCOV
44

×
UNCOV
45
    private originInstancesMap = new Map<
×
46
        ElementRef | HTMLElement,
×
47
        {
48
            config: ThyAutocompleteConfig;
UNCOV
49
            autocompleteRef: ThyAutocompleteRef<any, any>;
×
UNCOV
50
        }
×
UNCOV
51
    >();
×
52

53
    private buildPositionStrategy<TData>(config: ThyAutocompleteConfig<TData>): PositionStrategy {
UNCOV
54
        const positionStrategy = new FlexibleConnectedPositionStrategy(
×
55
            config.origin,
56
            this._viewportRuler,
57
            this._document,
×
58
            this._platform,
×
59
            this._overlayContainer
60
        );
61
        const positions = getFlexiblePositions(config.placement, config.offset, 'thy-autocomplete');
62
        positionStrategy.withPositions(positions);
63
        positionStrategy.withGrowAfterOpen(true);
64
        positionStrategy.positionChanges.pipe(takeUntil(this.ngUnsubscribe$)).subscribe(change => {
65
            if (change.scrollableViewProperties.isOverlayClipped) {
66
                // After position changes occur and the overlay is clipped by
67
                // a parent scrollable then close the tooltip.
68
                this.ngZone.run(() => this.close());
×
69
            }
×
70
        });
71
        return positionStrategy;
72
    }
73

74
    protected buildOverlayConfig<TData>(config: ThyAutocompleteConfig<TData>): OverlayConfig {
75
        const strategy = this.buildPositionStrategy(config);
76
        const overlayConfig = this.buildBaseOverlayConfig(config);
77
        overlayConfig.positionStrategy = strategy;
×
78
        overlayConfig.scrollStrategy = config.scrollStrategy || this.overlay.scrollStrategies.block();
79
        overlayConfig.width = config.width;
UNCOV
80
        return overlayConfig;
×
UNCOV
81
    }
×
82

83
    protected attachOverlayContainer(overlay: OverlayRef, config: ThyAutocompleteConfig<any>): ThyAutocompleteContainer {
84
        const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
UNCOV
85
        const injector = Injector.create({
×
UNCOV
86
            parent: userInjector || this.injector,
×
87
            providers: [{ provide: ThyAutocompleteConfig, useValue: config }]
88
        });
89
        const containerPortal = new ComponentPortal(ThyAutocompleteContainer, config.viewContainerRef, injector);
UNCOV
90
        const containerRef = overlay.attach<ThyAutocompleteContainer>(containerPortal);
×
UNCOV
91
        return containerRef.instance;
×
UNCOV
92
    }
×
UNCOV
93

×
UNCOV
94
    protected createAbstractOverlayRef<T>(
×
UNCOV
95
        overlayRef: OverlayRef,
×
UNCOV
96
        containerInstance: ThyAutocompleteContainer,
×
UNCOV
97
        config: ThyAutocompleteConfig<any>
×
UNCOV
98
    ): ThyInternalAutocompleteRef<T> {
×
UNCOV
99
        return new ThyInternalAutocompleteRef<T>(overlayRef, containerInstance, config);
×
UNCOV
100
    }
×
UNCOV
101

×
102
    protected createInjector<T>(
103
        config: ThyAutocompleteConfig,
UNCOV
104
        autocompleteRef: ThyAutocompleteRef<T>,
×
UNCOV
105
        autocompleteContainer: ThyAutocompleteContainer
×
UNCOV
106
    ): Injector {
×
UNCOV
107
        const userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
×
UNCOV
108
        const injectionTokens: StaticProvider[] = [
×
UNCOV
109
            {
×
110
                provide: ThyAutocompleteContainer,
UNCOV
111
                useValue: autocompleteContainer
×
UNCOV
112
            },
×
113
            {
114
                provide: ThyAutocompleteRef,
115
                useValue: autocompleteRef
UNCOV
116
            }
×
117
        ];
118

UNCOV
119
        if (config.direction && (!userInjector || !userInjector.get<Directionality | null>(Directionality, null))) {
×
120
            injectionTokens.push({
121
                provide: Directionality,
1✔
122
                useValue: {
123
                    value: config.direction,
1✔
124
                    change: of()
125
                }
126
            });
127
        }
128

129
        return Injector.create({ parent: userInjector || this.injector, providers: injectionTokens });
130
    }
131

132
    private originElementAddActiveClass(config: ThyAutocompleteConfig) {
133
        if (config.originActiveClass) {
134
            coerceElement<HTMLElement>(config.origin).classList.add(...coerceArray(config.originActiveClass));
135
        }
136
    }
137

138
    private originElementRemoveActiveClass(config: ThyAutocompleteConfig) {
139
        if (config.originActiveClass) {
140
            coerceElement<HTMLElement>(config.origin).classList.remove(...coerceArray(config.originActiveClass));
141
        }
142
    }
143

144
    constructor() {
145
        const overlay = inject(Overlay);
146
        const injector = inject(Injector);
147
        const defaultConfig = inject(THY_AUTOCOMPLETE_DEFAULT_CONFIG);
148

149
        super(autocompleteAbstractOverlayOptions, overlay, injector, defaultConfig);
150
    }
151

152
    open<T, TData = any, TResult = any>(
153
        componentOrTemplateRef: ComponentType<T> | TemplateRef<T>,
154
        config?: ThyAutocompleteConfig<TData>
155
    ): ThyAutocompleteRef<T, TResult> {
156
        const originElement = coerceElement(config.origin);
157
        const autocompleteRef = this.openOverlay(componentOrTemplateRef, config) as ThyAutocompleteRef<T>;
158
        config = autocompleteRef.containerInstance.config;
159
        autocompleteRef.afterClosed().subscribe(() => {
160
            this.originElementRemoveActiveClass(config);
161
            this.originInstancesMap.delete(originElement);
162
        });
163

164
        this.originElementAddActiveClass(config);
165
        this.originInstancesMap.set(originElement, {
166
            config,
167
            autocompleteRef
168
        });
169

170
        return autocompleteRef;
171
    }
172

173
    ngOnDestroy() {
174
        this.dispose();
175
    }
176
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc