Skip to content

Commit 13cf8a7

Browse files
authored
Merge pull request #10716 from IgniteUI/13.0.x
Merging 13.0.x into master
2 parents 402fee7 + 6048fb2 commit 13cf8a7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+582
-113
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
All notable changes for each version of this project will be documented in this file.
44

5+
## 13.0.5
6+
7+
### New Features
8+
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`
9+
- Added `dataCloneStrategy` input, which allows users provide their own implementation of how data objects are cloned when row and/or batch editing is enabled. The custom strategy should implement the `IDataCloneStrategy` interface.
10+
511
## 13.0.1
612

713
### New Features

projects/igniteui-angular/src/lib/carousel/carousel-base.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AnimationBuilder, AnimationPlayer, AnimationReferenceMetadata, useAnimation } from '@angular/animations';
2-
import { EventEmitter } from '@angular/core';
2+
import { ChangeDetectorRef, EventEmitter } from '@angular/core';
33
import { fadeIn } from '../animations/fade';
44
import { slideInLeft } from '../animations/slide';
55
import { mkenum } from '../core/utils';
@@ -49,7 +49,7 @@ export abstract class IgxCarouselComponentBase {
4949
/** @hidden */
5050
protected newDuration = 0;
5151

52-
constructor(private builder: AnimationBuilder) {
52+
constructor(private builder: AnimationBuilder, private cdr: ChangeDetectorRef) {
5353
}
5454

5555
/** @hidden */
@@ -86,6 +86,7 @@ export abstract class IgxCarouselComponentBase {
8686
if (this.animationStarted(this.enterAnimationPlayer)) {
8787
this.enterAnimationPlayer.reset();
8888
this.enterAnimationDone.emit();
89+
this.cdr.markForCheck();
8990
}
9091
}
9192

@@ -155,6 +156,7 @@ export abstract class IgxCarouselComponentBase {
155156
this.newDuration = 0;
156157
this.previousItem.previous = false;
157158
this.enterAnimationDone.emit();
159+
this.cdr.markForCheck();
158160
});
159161
this.previousItem.previous = true;
160162
this.enterAnimationPlayer.play();

projects/igniteui-angular/src/lib/carousel/carousel.component.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import {
1818
TemplateRef,
1919
ViewChild,
2020
ContentChild,
21-
Injectable
21+
Injectable,
22+
ChangeDetectorRef
2223
} from '@angular/core';
2324
import { IgxIconModule } from '../icon/public_api';
2425
import { IBaseEventArgs, mkenum, PlatformUtil } from '../core/utils';
@@ -534,9 +535,9 @@ export class IgxCarouselComponent extends IgxCarouselComponentBase implements On
534535
this.restartInterval();
535536
}
536537

537-
constructor(private element: ElementRef, private iterableDiffers: IterableDiffers,
538+
constructor(cdr: ChangeDetectorRef, private element: ElementRef, private iterableDiffers: IterableDiffers,
538539
builder: AnimationBuilder, private platformUtil: PlatformUtil) {
539-
super(builder);
540+
super(builder, cdr);
540541
this.differ = this.iterableDiffers.find([]).create(null);
541542
}
542543

projects/igniteui-angular/src/lib/core/styles/components/tabs/_tabs-theme.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,12 @@
280280
%tabs-header-content {
281281
flex: 1 1 auto;
282282
overflow: hidden;
283+
scroll-behavior: smooth;
283284
}
284285

285286
%tabs-header-wrapper {
286287
position: relative;
287288
flex-grow: 1;
288-
transition: transform .2s $tabs-animation-function;
289289

290290
@if $bootstrap-theme or $indigo-theme {
291291
&::after {

projects/igniteui-angular/src/lib/core/styles/themes/_index.scss

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@
494494
$warn: igx-color($palette, 'warn'),
495495
$error: igx-color($palette, 'error'),
496496
$surface: if($surface != #fff, $surface, #fff),
497-
$grays: if($grays != rgba(0, 0, 0, .38), $grays, #000),
497+
$grays: if($grays != #9e9e9e, $grays, #000),
498498
);
499499

500500
@include igx-theme(
@@ -526,7 +526,7 @@
526526
$warn: igx-color($palette, 'warn'),
527527
$error: igx-color($palette, 'error'),
528528
$surface: if($surface != #fff, $surface, #222),
529-
$grays: if($grays != rgba(0, 0, 0, .38), $grays, #fff),
529+
$grays: if($grays != #9e9e9e, $grays, #fff),
530530
);
531531

532532
@include igx-theme(
@@ -637,7 +637,7 @@
637637
$palette: igx-palette(
638638
$primary,
639639
$secondary,
640-
$surface: if($surface != #f8f9fa, $surface, #222),
640+
$surface: if($surface != white, $surface, #222),
641641
$grays: #fff
642642
),
643643
$schema: $dark-bootstrap-schema,
@@ -691,7 +691,7 @@
691691
$palette: igx-palette(
692692
$primary,
693693
$secondary,
694-
$surface: if($surface != #2a2b2f, $surface, #2a2b2f),
694+
$surface: if($surface != white, $surface, #2a2b2f),
695695
$grays: #fff
696696
),
697697
$schema: $dark-indigo-schema,

projects/igniteui-angular/src/lib/core/utils.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,22 @@ export const cloneHierarchicalArray = (array: any[], childDataKey: any): any[] =
8181
return result;
8282
};
8383

84+
/**
85+
* Creates an object with prototype from provided source and copies
86+
* all properties descriptors from provided source
87+
* @param obj Source to copy prototype and descriptors from
88+
* @returns New object with cloned prototype and property descriptors
89+
*/
90+
export const copyDescriptors = (obj) => {
91+
if (obj) {
92+
return Object.create(
93+
Object.getPrototypeOf(obj),
94+
Object.getOwnPropertyDescriptors(obj)
95+
);
96+
}
97+
}
98+
99+
84100
/**
85101
* Deep clones all first level keys of Obj2 and merges them to Obj1
86102
*
@@ -164,7 +180,7 @@ export const uniqueDates = (columnValues: any[]) => columnValues.reduce((a, c) =
164180
* @returns true if provided variable is Object
165181
* @hidden
166182
*/
167-
export const isObject = (value: any): boolean => value && value.toString() === '[object Object]';
183+
export const isObject = (value: any): boolean => !!(value && value.toString() === '[object Object]');
168184

169185
/**
170186
* Checks if provided variable is Date
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { cloneValue } from "../core/utils";
2+
3+
export interface IDataCloneStrategy {
4+
clone(data: any): any;
5+
}
6+
7+
export class DefaultDataCloneStrategy implements IDataCloneStrategy {
8+
public clone(data: any): any {
9+
return cloneValue(data);
10+
}
11+
}

projects/igniteui-angular/src/lib/data-operations/data-util.spec.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
import { IPagingState, PagingError } from './paging-state.interface';
2121
import { SampleTestData } from '../test-utils/sample-test-data.spec';
2222
import { Transaction, TransactionType, HierarchicalTransaction } from '../services/public_api';
23+
import { DefaultDataCloneStrategy } from './data-clone-strategy';
2324

2425
/* Test sorting */
2526
const testSort = () => {
@@ -516,19 +517,21 @@ const testMerging = () => {
516517
});
517518

518519
it('Should merge delete transactions correctly', () => {
520+
const cloneStrategy = new DefaultDataCloneStrategy();
519521
const data = SampleTestData.personIDNameData();
520522
const secondRow = data[1];
521523
const transactions: Transaction[] = [
522524
{ id: 1, newValue: null, type: TransactionType.DELETE },
523525
{ id: 3, newValue: null, type: TransactionType.DELETE },
524526
];
525527

526-
DataUtil.mergeTransactions(data, transactions, 'ID', true);
528+
DataUtil.mergeTransactions(data, transactions, 'ID', cloneStrategy, true);
527529
expect(data.length).toBe(1);
528530
expect(data[0]).toEqual(secondRow);
529531
});
530532

531533
it('Should merge add hierarchical transactions correctly', () => {
534+
const cloneStrategy = new DefaultDataCloneStrategy();
532535
const data = SampleTestData.employeeSmallTreeData();
533536
const addRootRow = { ID: 1000, Name: 'Pit Peter', HireDate: new Date(2008, 3, 20), Age: 55 };
534537
const addChildRow1 = { ID: 1001, Name: 'Marry May', HireDate: new Date(2018, 4, 1), Age: 102 };
@@ -539,7 +542,7 @@ const testMerging = () => {
539542
{ id: addChildRow2.ID, newValue: addChildRow2, type: TransactionType.ADD, path: [addRootRow.ID] },
540543
];
541544

542-
DataUtil.mergeHierarchicalTransactions(data, transactions, 'Employees', 'ID', false);
545+
DataUtil.mergeHierarchicalTransactions(data, transactions, 'Employees', 'ID', cloneStrategy, false);
543546
expect(data.length).toBe(4);
544547

545548
expect(data[3].Age).toBe(addRootRow.Age);
@@ -555,6 +558,7 @@ const testMerging = () => {
555558
});
556559

557560
it('Should merge update hierarchical transactions correctly', () => {
561+
const cloneStrategy = new DefaultDataCloneStrategy();
558562
const data = SampleTestData.employeeSmallTreeData();
559563
const updateRootRow = { Name: 'May Peter', Age: 13 };
560564
const updateChildRow1 = { HireDate: new Date(2100, 1, 12), Age: 1300 };
@@ -581,7 +585,7 @@ const testMerging = () => {
581585
},
582586
];
583587

584-
DataUtil.mergeHierarchicalTransactions(data, transactions, 'Employees', 'ID', false);
588+
DataUtil.mergeHierarchicalTransactions(data, transactions, 'Employees', 'ID',cloneStrategy, false);
585589
expect(data[1].Name).toBe(updateRootRow.Name);
586590
expect(data[1].Age).toBe(updateRootRow.Age);
587591

@@ -593,6 +597,7 @@ const testMerging = () => {
593597
});
594598

595599
it('Should merge delete hierarchical transactions correctly', () => {
600+
const cloneStrategy = new DefaultDataCloneStrategy();
596601
const data = SampleTestData.employeeSmallTreeData();
597602
const transactions: HierarchicalTransaction[] = [
598603
// root row with no children
@@ -605,7 +610,7 @@ const testMerging = () => {
605610
{ id: data[0].Employees[2].ID, newValue: null, type: TransactionType.DELETE, path: [data[0].ID] }
606611
];
607612

608-
DataUtil.mergeHierarchicalTransactions(data, transactions, 'Employees', 'ID', true);
613+
DataUtil.mergeHierarchicalTransactions(data, transactions, 'Employees', 'ID', cloneStrategy, true);
609614

610615
expect(data.length).toBe(1);
611616
expect(data[0].Employees.length).toBe(1);

projects/igniteui-angular/src/lib/data-operations/data-util.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { IGroupByKey } from './groupby-expand-state.interface';
88
import { IGroupByRecord } from './groupby-record.interface';
99
import { IGroupingState } from './groupby-state.interface';
1010
import { FilteringStrategy } from './filtering-strategy';
11-
import { cloneValue, mergeObjects, mkenum } from '../core/utils';
11+
import { mergeObjects, mkenum } from '../core/utils';
1212
import { Transaction, TransactionType, HierarchicalTransaction } from '../services/transaction/transaction';
1313
import { getHierarchy, isHierarchyMatch } from './operations';
1414
import { GridType } from '../grids/common/grid.interface';
@@ -21,6 +21,7 @@ import {
2121
IgxSorting,
2222
IgxGrouping
2323
} from '../grids/common/strategy';
24+
import { DefaultDataCloneStrategy, IDataCloneStrategy } from '../data-operations/data-clone-strategy';
2425

2526
/**
2627
* @hidden
@@ -147,12 +148,12 @@ export class DataUtil {
147148
* @param deleteRows Should delete rows with DELETE transaction type from data
148149
* @returns Provided data collections updated with all provided transactions
149150
*/
150-
public static mergeTransactions<T>(data: T[], transactions: Transaction[], primaryKey?: any, deleteRows: boolean = false): T[] {
151+
public static mergeTransactions<T>(data: T[], transactions: Transaction[], primaryKey?: any, cloneStrategy: IDataCloneStrategy = new DefaultDataCloneStrategy(), deleteRows: boolean = false): T[] {
151152
data.forEach((item: any, index: number) => {
152153
const rowId = primaryKey ? item[primaryKey] : item;
153154
const transaction = transactions.find(t => t.id === rowId);
154155
if (transaction && transaction.type === TransactionType.UPDATE) {
155-
data[index] = transaction.newValue;
156+
data[index] = mergeObjects(cloneStrategy.clone(data[index]), transaction.newValue);
156157
}
157158
});
158159

@@ -189,6 +190,7 @@ export class DataUtil {
189190
transactions: HierarchicalTransaction[],
190191
childDataKey: any,
191192
primaryKey?: any,
193+
cloneStrategy: IDataCloneStrategy = new DefaultDataCloneStrategy(),
192194
deleteRows: boolean = false): any[] {
193195
for (const transaction of transactions) {
194196
if (transaction.path) {
@@ -205,7 +207,7 @@ export class DataUtil {
205207
case TransactionType.UPDATE:
206208
const updateIndex = collection.findIndex(x => x[primaryKey] === transaction.id);
207209
if (updateIndex !== -1) {
208-
collection[updateIndex] = mergeObjects(cloneValue(collection[updateIndex]), transaction.newValue);
210+
collection[updateIndex] = mergeObjects(cloneStrategy.clone(collection[updateIndex]), transaction.newValue);
209211
}
210212
break;
211213
case TransactionType.DELETE:

projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ export class IgxExpansionPanelComponent extends ToggleAnimationPlayer implements
225225
* ```
226226
*/
227227
public collapse(evt?: Event) {
228-
if (this.collapsed) { // If expansion panel is already collapsed, do nothing
228+
// If expansion panel is already collapsed or is collapsing, do nothing
229+
if (this.collapsed || this.closeAnimationPlayer) {
229230
return;
230231
}
231232
const args = { event: evt, panel: this, owner: this, cancel: false };

0 commit comments

Comments
 (0)