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

atinc / ngx-tethys / ec413220-57ac-4960-8ac4-93070cf96239

22 Feb 2024 12:31PM UTC coverage: 90.604%. Remained the same
ec413220-57ac-4960-8ac4-93070cf96239

Pull #3029

circleci

minlovehua
refactor(select): rename native select and custom select #INFR-10691
Pull Request #3029: refactor(select): rename native select and custom select and provide schematics #INFR-10691

5425 of 6642 branches covered (81.68%)

Branch coverage included in aggregate %.

362 of 381 new or added lines in 3 files covered. (95.01%)

9 existing lines in 2 files now uncovered.

13504 of 14250 relevant lines covered (94.76%)

981.27 hits per line

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

89.39
/src/pagination/pagination.component.ts
1
import {
2
    Component,
3
    OnInit,
4
    ChangeDetectionStrategy,
5
    Input,
6
    Output,
7
    EventEmitter,
8
    ChangeDetectorRef,
9
    HostBinding,
10
    Optional,
11
    Inject,
12
    TemplateRef
13
} from '@angular/core';
14
import { ThyPaginationConfigModel } from './pagination.class';
15
import { PaginationDefaultConfig, DEFAULT_RANGE_COUNT, THY_PAGINATION_CONFIG, ThyPaginationConfig } from './pagination.config';
16
import { useHostRenderer } from '@tethys/cdk/dom';
17
import { isTemplateRef } from 'ngx-tethys/util';
18
import { PaginationTotalCountFormat } from './pagination.pipe';
19
import { ThyIcon } from 'ngx-tethys/icon';
1✔
20
import { ThyOption, ThyEnterDirective } from 'ngx-tethys/shared';
21
import { FormsModule } from '@angular/forms';
92✔
22
import { ThySelect } from 'ngx-tethys/select';
92✔
23
import { NgIf, NgTemplateOutlet, NgFor } from '@angular/common';
13✔
24
import { InputBoolean, InputNumber } from 'ngx-tethys/core';
25

26
/**
27
 * 分页组件,当数据量过多时,使用分页分解数据。
78✔
28
 * @name thy-pagination
78✔
29
 * @order 10
78✔
30
 */
1✔
31
@Component({
1✔
32
    selector: 'thy-pagination',
1✔
33
    templateUrl: './pagination.component.html',
34
    changeDetection: ChangeDetectionStrategy.OnPush,
35
    standalone: true,
36
    imports: [NgIf, NgTemplateOutlet, ThySelect, FormsModule, NgFor, ThyOption, ThyIcon, ThyEnterDirective, PaginationTotalCountFormat]
79✔
37
})
79✔
38
export class ThyPagination implements OnInit {
2✔
39
    isTemplateRef = isTemplateRef;
2✔
40
    public config: ThyPaginationConfigModel = Object.assign({}, PaginationDefaultConfig, this.paginationConfig.main);
2✔
41

42
    /**
43
     * 设置当前页,支持双向绑定
44
     * @default 1
3✔
45
     */
3✔
46
    @Input()
3✔
47
    @InputNumber()
1✔
48
    set thyPageIndex(pageIndex: number) {
1✔
49
        this.pageIndex = pageIndex;
1✔
50
        if (this.initialized) {
51
            this.setPageIndex(pageIndex);
52
        }
53
    }
14✔
54

55
    /**
56
     * 每页条目数量
×
57
     * @default 20
58
     */
59
    @Input()
14✔
60
    @InputNumber()
14✔
61
    set thyPageSize(pageSize: number) {
62
        this.pageSize = pageSize;
UNCOV
63
        this.selectPageSize = pageSize;
×
64
        if (this.initialized) {
65
            this.calculatePageCount();
UNCOV
66
            this.initializePages(this.pageIndex, this.pageCount);
×
UNCOV
67
            this.cdr.markForCheck();
×
UNCOV
68
        }
×
UNCOV
69
    }
×
70

71
    /**
72
     * 总页数 与 totalPages 二选一传入
73
     */
74
    @Input()
71✔
75
    @InputNumber()
76
    set thyTotal(total: number) {
77
        this.total = total;
66✔
78
        if (this.initialized) {
79
            this.calculatePageCount();
80
            this.setPageIndex(this.pageIndex);
80✔
81
            this.cdr.markForCheck();
80✔
82
        }
80✔
83
    }
80✔
84

80✔
85
    /**
80✔
86
     * 自定义分页页码,设置自定义分页页码后将不根据 Total 和 PageSize 来自动计算页码,完全以传入的页码为准
80✔
87
     * @type number[]
80✔
88
     */
80✔
89
    @Input()
80✔
90
    set thyCustomPages(pages: number[]) {
80✔
91
        this.customPages = pages;
80✔
92
        this.config.showTotalPageCount = false;
80✔
93
        if (this.initialized) {
80✔
94
            this.calculatePageCount();
80✔
95
            this.initializePages(this.pageIndex, this.pageCount);
80✔
96
            this.cdr.markForCheck();
80✔
97
        }
80✔
98
    }
80✔
99

100
    /**
101
     * 是否禁用
79✔
102
     */
79✔
103
    @Input('thyDisabled') @InputBoolean() disabled = false;
79✔
104

79✔
105
    /**
106
     * 是否显示快速跳转
107
     * @default false
79!
108
     */
79!
109
    @Input('thyShowQuickJumper')
110
    @InputBoolean()
111
    set showQuickJumper(value: boolean) {
112
        this.config.showQuickJumper = value;
101✔
113
    }
101✔
114

101✔
115
    /**
116
     * 设置是否显示总页数信息
101✔
117
     * @default true
118
     */
101✔
119
    @Input('thyShowTotalPageCount')
101✔
120
    @InputBoolean()
121
    set showTotalPageCount(value: boolean) {
122
        this.config.showTotalPageCount = value;
85✔
123
    }
85✔
124

3✔
125
    /**
126
     * 设置分页组件的大小
127
     * @type sm | md | lg
82!
128
     * @default md
129
     */
85✔
130
    @Input('thySize')
131
    set size(size: 'sm' | 'md' | 'lg') {
132
        this.selectSize = size;
13✔
133
        this.hostRenderer.addClass(`thy-pagination-${size}`);
134
    }
135

103✔
136
    /**
4✔
137
     * 设置最大显示数量,超出最大显示数后会自动进行分割显示
32✔
138
     * @default 9
139
     */
140
    @Input('thyMaxCount')
141
    @InputNumber()
142
    set maxCount(value: number) {
143
        this.config.maxCount = value;
4✔
144
    }
145

99✔
146
    /**
99✔
147
     * 设置边缘显示数量
99✔
148
     * @default 2
99✔
149
     */
99✔
150
    @Input('thyMarginalCount') @InputNumber() marginalCount: number;
99✔
151

4✔
152
    /**
4✔
153
     * 设置中间区域显示数量
154
     * @default 7
4✔
155
     */
4✔
156
    @Input()
157
    @InputNumber()
4✔
158
    set thyRangeCount(value: number) {
1✔
159
        if (Number.isInteger(value)) {
160
            this.config.rangeCount = value;
161
            if (this.initialized) {
4!
162
                this.setMarginalCount(value);
4✔
163
            }
164
        }
4✔
165
    }
4✔
166

167
    @Input('thyShowSizeChanger')
168
    @InputBoolean()
4✔
169
    set showSizeChanger(value: boolean) {
4✔
170
        this.config.showSizeChanger = value;
4✔
171
    }
1✔
172

173
    /**
4!
UNCOV
174
     * @type number[]
×
175
     */
176
    @Input('thyPageSizeOptions')
4✔
177
    set pageSizeOptions(value: number[]) {
18✔
178
        this.config.pageSizeOptions = value;
179
    }
180

181
    /**
182
     * 只有一页时是否隐藏分页器
183
     * @default false
4✔
184
     */
185
    @Input('thyHideOnSinglePage') @InputBoolean() hideOnSinglePage: boolean;
186

95✔
187
    /**
284✔
188
     * 页码改变的回调
189
     */
190
    @Output('thyPageIndexChange') pageIndexChange = new EventEmitter<number>();
191

192
    /**
193
     * 与Bootstrap pagination 兼容,后续版本会进行删除,参数保持与 bootstrap 一致
194
     */
99✔
195
    @Output('thyPageChanged') pageChanged = new EventEmitter<{ page: number }>();
196

197
    @Output('thyPageSizeChanged') pageSizeChanged = new EventEmitter<number>();
5✔
198

5✔
199
    public pages: { index?: number; text?: string; active?: boolean }[] = [];
200

201
    public pageIndex = 1;
5!
UNCOV
202

×
203
    public pageSize: number;
204

5✔
205
    public pageCount: number;
5✔
206

207
    public customPages: number[];
208

2✔
209
    public total: number;
2!
210

2✔
211
    public range = { from: 0, to: 0 };
212

2✔
213
    public firstIndex = 1;
214

215
    public isHideOnSinglePage = false;
2✔
216

2✔
217
    private initialized = false;
2✔
218

2✔
219
    private hostRenderer = useHostRenderer();
220

1✔
221
    public selectSize = 'md';
222

223
    public selectPageSize: Number = 20;
224

1✔
225
    @HostBinding('class.thy-pagination') isPaginationClass = true;
226

227
    /**
228
     * 是否显示范围和total
229
     * @default false
230
     */
231
    @HostBinding('class.thy-pagination-has-total')
232
    @Input('thyShowTotal')
233
    showTotal: boolean | TemplateRef<{ $implicit: number; range: { from: number; to: number } }> = false;
234

235
    constructor(
236
        @Optional()
237
        @Inject(THY_PAGINATION_CONFIG)
238
        private paginationConfig: ThyPaginationConfig,
239
        private cdr: ChangeDetectorRef
240
    ) {}
241

242
    ngOnInit() {
243
        this.setMarginalCount(this.config.rangeCount);
244
        this.calculatePageCount();
245
        this.setPageIndex(this.pageIndex);
246
        this.initialized = true;
1✔
247
    }
248

249
    private setMarginalCount(range: number) {
250
        if (!this.marginalCount) {
251
            this.marginalCount = range <= DEFAULT_RANGE_COUNT ? 1 : 2;
1✔
252
        }
253
    }
254

255
    private setPageIndex(pageIndex: number) {
256
        this.pageIndex = pageIndex > this.pageCount ? this.pageCount : pageIndex || 1;
1✔
257
        const toPageSize = this.pageIndex * this.pageSize;
258
        this.range = {
259
            from: (this.pageIndex - 1) * this.pageSize + 1,
260
            to: toPageSize > this.total ? this.total : toPageSize
261
        };
1✔
262
        this.initializePages(this.pageIndex, this.pageCount);
263
        this.cdr.markForCheck();
264
    }
265

1✔
266
    private calculatePageCount() {
267
        let pageCount = null;
268
        if (this.customPages && this.customPages.length > 0) {
269
            pageCount = this.customPages[this.customPages.length - 1];
270
        } else {
1✔
271
            pageCount = this.pageSize < 1 ? 1 : Math.ceil(this.total / this.pageSize);
272
        }
273
        this.pageCount = Math.max(pageCount || 0, 1);
274
    }
275

1✔
276
    private makePage(index: number, text: string, active: boolean): { index: number; text: string; active: boolean } {
277
        return { index, text, active };
278
    }
279

280
    private initializePages(pageIndex: number, pageCount: number) {
1✔
281
        if (this.customPages && this.customPages.length > 0) {
282
            this.pages = this.customPages.map(page => {
283
                return {
284
                    index: page,
1✔
285
                    text: page.toString(),
286
                    active: page === +pageIndex
287
                };
288
            });
289
            return;
1✔
290
        }
291

292
        let pages = [];
293
        const marginalCount = this.marginalCount;
294
        const rangeCount = this.config.rangeCount;
1✔
295
        const maxCount = this.config.maxCount;
296
        const isMaxSized = pageCount > maxCount;
297
        if (isMaxSized) {
298
            const beforePages = [];
1✔
299
            const afterPages = [];
300

301
            // beforePages
302
            for (let i = 1; i <= marginalCount; i++) {
303
                beforePages.push(this.makePage(i, i.toString(), i === pageIndex));
304
            }
305
            if (pageIndex - Math.ceil(rangeCount / 2) > this.firstIndex) {
306
                beforePages.push(this.makePage(pageIndex - rangeCount, '···', null));
307
            }
308

309
            // afterPages
310
            if (pageIndex + Math.ceil(rangeCount / 2) < pageCount) {
311
                afterPages.push(this.makePage(pageIndex + rangeCount, '···', null));
312
            }
313
            for (let i = pageCount - marginalCount + 1; i <= pageCount; i++) {
314
                afterPages.push(this.makePage(i, i.toString(), i === pageIndex));
315
            }
316

317
            // mainPages
318
            let start = Math.max(marginalCount + 1, pageIndex - (rangeCount - 1) / 2);
319
            let end = Math.min(pageIndex + (rangeCount - 1) / 2, pageCount - marginalCount);
320
            if (pageIndex - 1 <= marginalCount) {
321
                end = rangeCount;
322
            }
323
            if (pageCount - pageIndex <= marginalCount) {
324
                start = pageCount - rangeCount + 1;
325
            }
326

327
            for (let i = start; i <= end; i++) {
328
                pages.push({
329
                    index: i,
330
                    text: i.toString(),
331
                    active: i === +pageIndex
332
                });
333
            }
334
            pages = [...beforePages, ...pages, ...afterPages];
335
        } else {
336
            for (let i = 1; i <= pageCount; i++) {
337
                pages.push({
338
                    index: i,
339
                    text: i.toString(),
340
                    active: i === +pageIndex
341
                });
342
            }
343
        }
344
        this.pages = pages;
345
    }
346

347
    private pageChange(pageIndex: number) {
348
        this.pageIndexChange.emit(pageIndex);
349
        this.pageChanged.emit({ page: pageIndex });
350
    }
351

352
    selectPage(pageIndex: number) {
353
        if (this.disabled || pageIndex === this.firstIndex - 1 || pageIndex === this.pageCount + 1) {
354
            return;
355
        }
356
        this.setPageIndex(pageIndex);
357
        this.pageChange(this.pageIndex);
358
    }
359

360
    jumpPage(input: HTMLInputElement) {
361
        const pageIndex = +input.value;
362
        if (Number.isInteger(pageIndex)) {
363
            this.selectPage(pageIndex);
364
        }
365
        input.value = '';
366
    }
367

368
    onPageSizeChange(event: number) {
369
        this.pageSize = event;
370
        this.calculatePageCount();
371
        this.setPageIndex(this.pageIndex);
372
        this.pageSizeChanged.emit(event);
373
    }
374
}
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