mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[ACS-9012] Add the option to truncate display value in text column (#10440)
* [ACS-9012] Add the option to truncate disaplay value in text column * [ACS-9012] Use slice as substr is deprecated * [ACS-9012] Remove redundant param
This commit is contained in:
parent
88eb654c30
commit
60a9565c71
@ -65,6 +65,7 @@ Defines column properties for DataTable, Tasklist, Document List and other compo
|
||||
| currencyConfig | `CurrencyConfig` | [Default currency config](#default-currency-config) | Currency configuration to customize the formatting and display of currency values within the component. |
|
||||
| decimalConfig | `DecimalConfig` | [Default decimal config](#default-decimal-config) | Decimal configuration to customize the formatting and display of decimal values within the component. |
|
||||
| dateConfig | `DateConfig` | [Default date config](#default-date-config) | Date configuration to customize the formatting and localization of date values within the component. |
|
||||
| maxTextLength | `number` | 250 | Max length of the text displayed in column before truncation. |
|
||||
|
||||
## Properties configuration
|
||||
|
||||
@ -467,6 +468,31 @@ const shouldPerformAction = this.columns
|
||||
if (shouldPerformAction) { /* action */}
|
||||
```
|
||||
|
||||
### Specifying max text length in the column
|
||||
|
||||
If you want to restrict max number of characters displayed in the column you can use `maxTextLength` param.
|
||||
|
||||
Example of using `maxTextLength` from a JSON config file:
|
||||
|
||||
```json
|
||||
[
|
||||
{"type": "text", "key": "id", "title": "Id"},
|
||||
{"type": "text", "key": "name", "title": "name", "maxTextLength": 100},
|
||||
]
|
||||
```
|
||||
|
||||
HTML `<data-column>` element example:
|
||||
|
||||
```html
|
||||
...
|
||||
<data-columns>
|
||||
<data-column [maxTextLength]="100" key="name" title="Name"></data-column>
|
||||
...
|
||||
</data-columns>
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
## See also
|
||||
|
||||
- [Document list component](../../content-services/components/document-list.component.md)
|
||||
|
27
docs/core/pipes/truncate.pipe.md
Normal file
27
docs/core/pipes/truncate.pipe.md
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
Title: Truncate pipe
|
||||
Added: v7.0.0-alpha.7
|
||||
Status: Active
|
||||
Last reviewed: 2024-11-28
|
||||
---
|
||||
|
||||
# Truncate Pipe
|
||||
|
||||
Truncates the text when it exceeds specified max length. It also appends provided ellipsis at the end of the string.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
<!-- {% raw %} -->
|
||||
|
||||
```HTML
|
||||
<div>
|
||||
{{ textToTruncate | truncate:100:'***' }}
|
||||
</div>
|
||||
```
|
||||
|
||||
<!-- {% endraw %} -->
|
||||
|
||||
| Name | Type | Default value | Description |
|
||||
| ------------- | -------- | ------------- | ---------------------------------------------------------------------- |
|
||||
| maxTextLength | `number` | 250 | Max length of the text that should be displayed prio to truncating. |
|
||||
| ellipsis | `string` | `...` | String which will be appended to the text when truncating will happen. |
|
@ -97,4 +97,24 @@ describe('DataTableCellComponent', () => {
|
||||
|
||||
expect(component.row.obj).toBe('New Value');
|
||||
});
|
||||
|
||||
it('should truncate display text and not truncate tooltip if configured on column', () => {
|
||||
const row: DataRow = {
|
||||
id: '1',
|
||||
isSelected: false,
|
||||
hasValue: () => true,
|
||||
getValue: () => 'hello world',
|
||||
obj: 'Initial Value',
|
||||
cache: []
|
||||
};
|
||||
|
||||
component.data = new ObjectDataTableAdapter(mockCarsData, mockCarsSchemaDefinition);
|
||||
component.column = { key: 'car_name', type: 'text', maxTextLength: 10 };
|
||||
component.row = row;
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
checkDisplayedText('hello worl...');
|
||||
checkDisplayedTooltip('hello world');
|
||||
});
|
||||
});
|
||||
|
@ -15,15 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
DestroyRef,
|
||||
inject,
|
||||
Input,
|
||||
OnInit,
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, DestroyRef, inject, Input, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { DataColumn } from '../../data/data-column.model';
|
||||
import { DataRow } from '../../data/data-row.model';
|
||||
import { DataTableAdapter } from '../../data/datatable-adapter';
|
||||
@ -32,11 +24,12 @@ import { DataTableService } from '../../services/datatable.service';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ClipboardDirective } from '../../../clipboard/clipboard.directive';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { TruncatePipe } from '../../../pipes/truncate.pipe';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-datatable-cell',
|
||||
standalone: true,
|
||||
imports: [CommonModule, ClipboardDirective],
|
||||
imports: [CommonModule, ClipboardDirective, TruncatePipe],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: `
|
||||
<ng-container>
|
||||
@ -47,11 +40,13 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
[attr.aria-label]="value$ | async"
|
||||
[title]="tooltip"
|
||||
class="adf-datatable-cell-value"
|
||||
>{{ value$ | async }}</span
|
||||
>{{ column?.maxTextLength ? (value$ | async | truncate : column?.maxTextLength) : (value$ | async) }}</span
|
||||
>
|
||||
</ng-container>
|
||||
<ng-template #defaultCell>
|
||||
<span [title]="tooltip" class="adf-datatable-cell-value">{{ value$ | async }}</span>
|
||||
<span [title]="tooltip" class="adf-datatable-cell-value">{{
|
||||
column?.maxTextLength ? (value$ | async | truncate : column?.maxTextLength) : (value$ | async)
|
||||
}}</span>
|
||||
</ng-template>
|
||||
`,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
@ -325,6 +325,13 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
|
||||
justify-content: end;
|
||||
padding-right: 15px;
|
||||
|
||||
&:focus-visible,
|
||||
&:focus-within {
|
||||
.adf-datatable-hide-actions-without-hover {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
&-provided {
|
||||
max-width: 100px !important;
|
||||
justify-content: center;
|
||||
@ -359,13 +366,6 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.adf-datatable-actions-menu:focus-visible,
|
||||
.adf-datatable-actions-menu:focus-within {
|
||||
.adf-datatable-hide-actions-without-hover {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.adf-datatable-cell--image {
|
||||
max-width: $data-table-thumbnail-width;
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ export interface DataColumn<T = unknown> {
|
||||
currencyConfig?: CurrencyConfig;
|
||||
decimalConfig?: DecimalConfig;
|
||||
dateConfig?: DateConfig;
|
||||
maxTextLength?: number;
|
||||
}
|
||||
|
||||
export interface LocaleConfig {
|
||||
|
@ -43,6 +43,7 @@ export class ObjectDataColumn<T = unknown> implements DataColumn<T> {
|
||||
currencyConfig?: CurrencyConfig;
|
||||
decimalConfig?: DecimalConfig;
|
||||
dateConfig?: DateConfig;
|
||||
maxTextLength?: number;
|
||||
|
||||
constructor(input: any) {
|
||||
this.id = input.id ?? '';
|
||||
@ -67,5 +68,6 @@ export class ObjectDataColumn<T = unknown> implements DataColumn<T> {
|
||||
this.currencyConfig = input.currencyConfig;
|
||||
this.decimalConfig = input.decimalConfig;
|
||||
this.dateConfig = input.dateConfig;
|
||||
this.maxTextLength = input.maxTextLength;
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import { DecimalNumberPipe } from './decimal-number.pipe';
|
||||
import { MomentDatePipe } from './moment-date.pipe';
|
||||
import { MomentDateTimePipe } from './moment-datetime.pipe';
|
||||
import { DateTimePipe } from './date-time.pipe';
|
||||
import { TruncatePipe } from './truncate.pipe';
|
||||
|
||||
export const CORE_PIPES = [
|
||||
LocalizedDatePipe,
|
||||
@ -44,7 +45,8 @@ export const CORE_PIPES = [
|
||||
MomentDatePipe,
|
||||
MomentDateTimePipe,
|
||||
DateTimePipe,
|
||||
InitialUsernamePipe
|
||||
InitialUsernamePipe,
|
||||
TruncatePipe
|
||||
] as const;
|
||||
|
||||
/**
|
||||
|
60
lib/core/src/lib/pipes/truncate.pipe.spec.ts
Normal file
60
lib/core/src/lib/pipes/truncate.pipe.spec.ts
Normal file
@ -0,0 +1,60 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { TruncatePipe } from './truncate.pipe';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||
import { Injector, runInInjectionContext } from '@angular/core';
|
||||
|
||||
describe('TruncatePipe', () => {
|
||||
let pipe: TruncatePipe;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CoreTestingModule]
|
||||
});
|
||||
const injector = TestBed.inject(Injector);
|
||||
runInInjectionContext(injector, () => {
|
||||
pipe = new TruncatePipe();
|
||||
});
|
||||
});
|
||||
|
||||
it('should truncate texts longer than maxTextLength value', () => {
|
||||
const text = 'This is a long text';
|
||||
expect(pipe.transform(text, 10)).toBe('This is a ...');
|
||||
});
|
||||
|
||||
it('should not truncate texts shorter than maxTextLength value', () => {
|
||||
const text = 'Short text';
|
||||
expect(pipe.transform(text, 20)).toBe('Short text');
|
||||
});
|
||||
|
||||
it('should truncate texts longer than 250 chars and append "..." by default', () => {
|
||||
let text =
|
||||
'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes,';
|
||||
text += ' nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim.';
|
||||
let truncatedString =
|
||||
'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, ';
|
||||
truncatedString += 'nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium ...';
|
||||
expect(pipe.transform(text)).toBe(truncatedString);
|
||||
});
|
||||
|
||||
it('should append custom ellipsis when ellipsis param is provided', () => {
|
||||
const text = 'This is a long text';
|
||||
expect(pipe.transform(text, 10, '***')).toBe('This is a ***');
|
||||
});
|
||||
});
|
28
lib/core/src/lib/pipes/truncate.pipe.ts
Normal file
28
lib/core/src/lib/pipes/truncate.pipe.ts
Normal file
@ -0,0 +1,28 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
@Pipe({
|
||||
standalone: true,
|
||||
name: 'truncate'
|
||||
})
|
||||
export class TruncatePipe implements PipeTransform {
|
||||
transform(value: string, maxTextLength = 250, ellipsis = '...') {
|
||||
return value.length > maxTextLength ? value.slice(0, maxTextLength) + ellipsis : value;
|
||||
}
|
||||
}
|
@ -51,4 +51,5 @@ export interface DocumentListPresetRef extends ExtensionElement {
|
||||
};
|
||||
draggable?: boolean;
|
||||
resizable?: boolean;
|
||||
maxTextLength?: number;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user