@clr/angular 15.0.0 → 15.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8712,10 +8712,10 @@ class ClrDaypicker {
8712
8712
  }
8713
8713
  }
8714
8714
  ClrDaypicker.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ClrDaypicker, deps: [{ token: ViewManagerService }, { token: DateNavigationService }, { token: LocaleHelperService }, { token: ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component });
8715
- ClrDaypicker.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.2", type: ClrDaypicker, selector: "clr-daypicker", host: { properties: { "class.daypicker": "true" } }, ngImport: i0, template: "<div class=\"clr-sr-only\">{{commonStrings.keys.modalContentStart}}</div>\n<div class=\"calendar-header\">\n <div class=\"calendar-pickers\">\n <button\n class=\"calendar-btn monthpicker-trigger\"\n type=\"button\"\n (click)=\"changeToMonthView()\"\n [attr.aria-label]=\"monthAttrString\"\n [attr.title]=\"monthAttrString\"\n >\n {{calendarMonth}}\n </button>\n <button\n class=\"calendar-btn yearpicker-trigger\"\n type=\"button\"\n (click)=\"changeToYearView()\"\n [attr.aria-label]=\"yearAttrString\"\n [attr.title]=\"yearAttrString\"\n >\n {{calendarYear}}\n </button>\n </div>\n <div class=\"calendar-switchers\">\n <button\n class=\"calendar-btn switcher\"\n type=\"button\"\n (click)=\"previousMonth()\"\n [attr.aria-label]=\"commonStrings.keys.datepickerPreviousMonth\"\n >\n <cds-icon shape=\"angle\" direction=\"left\" [attr.title]=\"commonStrings.keys.datepickerPreviousMonth\"></cds-icon>\n </button>\n <button\n class=\"calendar-btn switcher\"\n type=\"button\"\n (click)=\"currentMonth()\"\n [attr.aria-label]=\"commonStrings.keys.datepickerCurrentMonth\"\n >\n <cds-icon shape=\"event\" [attr.title]=\"commonStrings.keys.datepickerCurrentMonth\"></cds-icon>\n </button>\n <button\n class=\"calendar-btn switcher\"\n type=\"button\"\n (click)=\"nextMonth()\"\n [attr.aria-label]=\"commonStrings.keys.datepickerNextMonth\"\n >\n <cds-icon shape=\"angle\" direction=\"right\"></cds-icon>\n </button>\n </div>\n</div>\n<clr-calendar></clr-calendar>\n<div class=\"clr-sr-only\">{{commonStrings.keys.modalContentEnd}}</div>\n", dependencies: [{ kind: "directive", type: CdsIconCustomTag, selector: "cds-icon" }, { kind: "component", type: ClrCalendar, selector: "clr-calendar" }] });
8715
+ ClrDaypicker.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.2", type: ClrDaypicker, selector: "clr-daypicker", host: { properties: { "class.daypicker": "true" } }, ngImport: i0, template: "<div class=\"clr-sr-only\">{{commonStrings.keys.modalContentStart}}</div>\n<div class=\"calendar-header\">\n <div class=\"calendar-pickers\">\n <button\n class=\"calendar-btn monthpicker-trigger\"\n type=\"button\"\n (click)=\"changeToMonthView()\"\n [attr.aria-label]=\"monthAttrString\"\n [attr.title]=\"monthAttrString\"\n >\n {{calendarMonth}}\n </button>\n <button\n class=\"calendar-btn yearpicker-trigger\"\n type=\"button\"\n (click)=\"changeToYearView()\"\n [attr.aria-label]=\"yearAttrString\"\n [attr.title]=\"yearAttrString\"\n >\n {{calendarYear}}\n </button>\n </div>\n <div class=\"calendar-switchers\">\n <button\n class=\"calendar-btn switcher\"\n type=\"button\"\n (click)=\"previousMonth()\"\n [attr.aria-label]=\"commonStrings.keys.datepickerPreviousMonth\"\n >\n <cds-icon shape=\"angle\" direction=\"left\" [attr.title]=\"commonStrings.keys.datepickerPreviousMonth\"></cds-icon>\n </button>\n <button\n class=\"calendar-btn switcher\"\n type=\"button\"\n (click)=\"currentMonth()\"\n [attr.aria-label]=\"commonStrings.keys.datepickerCurrentMonth\"\n >\n <cds-icon shape=\"event\" [attr.title]=\"commonStrings.keys.datepickerCurrentMonth\"></cds-icon>\n </button>\n <button\n class=\"calendar-btn switcher\"\n type=\"button\"\n (click)=\"nextMonth()\"\n [attr.aria-label]=\"commonStrings.keys.datepickerNextMonth\"\n >\n <cds-icon shape=\"angle\" direction=\"right\" [attr.title]=\"commonStrings.keys.datepickerNextMonth\"></cds-icon>\n </button>\n </div>\n</div>\n<clr-calendar></clr-calendar>\n<div class=\"clr-sr-only\">{{commonStrings.keys.modalContentEnd}}</div>\n", dependencies: [{ kind: "directive", type: CdsIconCustomTag, selector: "cds-icon" }, { kind: "component", type: ClrCalendar, selector: "clr-calendar" }] });
8716
8716
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ClrDaypicker, decorators: [{
8717
8717
  type: Component,
8718
- args: [{ selector: 'clr-daypicker', host: { '[class.daypicker]': 'true' }, template: "<div class=\"clr-sr-only\">{{commonStrings.keys.modalContentStart}}</div>\n<div class=\"calendar-header\">\n <div class=\"calendar-pickers\">\n <button\n class=\"calendar-btn monthpicker-trigger\"\n type=\"button\"\n (click)=\"changeToMonthView()\"\n [attr.aria-label]=\"monthAttrString\"\n [attr.title]=\"monthAttrString\"\n >\n {{calendarMonth}}\n </button>\n <button\n class=\"calendar-btn yearpicker-trigger\"\n type=\"button\"\n (click)=\"changeToYearView()\"\n [attr.aria-label]=\"yearAttrString\"\n [attr.title]=\"yearAttrString\"\n >\n {{calendarYear}}\n </button>\n </div>\n <div class=\"calendar-switchers\">\n <button\n class=\"calendar-btn switcher\"\n type=\"button\"\n (click)=\"previousMonth()\"\n [attr.aria-label]=\"commonStrings.keys.datepickerPreviousMonth\"\n >\n <cds-icon shape=\"angle\" direction=\"left\" [attr.title]=\"commonStrings.keys.datepickerPreviousMonth\"></cds-icon>\n </button>\n <button\n class=\"calendar-btn switcher\"\n type=\"button\"\n (click)=\"currentMonth()\"\n [attr.aria-label]=\"commonStrings.keys.datepickerCurrentMonth\"\n >\n <cds-icon shape=\"event\" [attr.title]=\"commonStrings.keys.datepickerCurrentMonth\"></cds-icon>\n </button>\n <button\n class=\"calendar-btn switcher\"\n type=\"button\"\n (click)=\"nextMonth()\"\n [attr.aria-label]=\"commonStrings.keys.datepickerNextMonth\"\n >\n <cds-icon shape=\"angle\" direction=\"right\"></cds-icon>\n </button>\n </div>\n</div>\n<clr-calendar></clr-calendar>\n<div class=\"clr-sr-only\">{{commonStrings.keys.modalContentEnd}}</div>\n" }]
8718
+ args: [{ selector: 'clr-daypicker', host: { '[class.daypicker]': 'true' }, template: "<div class=\"clr-sr-only\">{{commonStrings.keys.modalContentStart}}</div>\n<div class=\"calendar-header\">\n <div class=\"calendar-pickers\">\n <button\n class=\"calendar-btn monthpicker-trigger\"\n type=\"button\"\n (click)=\"changeToMonthView()\"\n [attr.aria-label]=\"monthAttrString\"\n [attr.title]=\"monthAttrString\"\n >\n {{calendarMonth}}\n </button>\n <button\n class=\"calendar-btn yearpicker-trigger\"\n type=\"button\"\n (click)=\"changeToYearView()\"\n [attr.aria-label]=\"yearAttrString\"\n [attr.title]=\"yearAttrString\"\n >\n {{calendarYear}}\n </button>\n </div>\n <div class=\"calendar-switchers\">\n <button\n class=\"calendar-btn switcher\"\n type=\"button\"\n (click)=\"previousMonth()\"\n [attr.aria-label]=\"commonStrings.keys.datepickerPreviousMonth\"\n >\n <cds-icon shape=\"angle\" direction=\"left\" [attr.title]=\"commonStrings.keys.datepickerPreviousMonth\"></cds-icon>\n </button>\n <button\n class=\"calendar-btn switcher\"\n type=\"button\"\n (click)=\"currentMonth()\"\n [attr.aria-label]=\"commonStrings.keys.datepickerCurrentMonth\"\n >\n <cds-icon shape=\"event\" [attr.title]=\"commonStrings.keys.datepickerCurrentMonth\"></cds-icon>\n </button>\n <button\n class=\"calendar-btn switcher\"\n type=\"button\"\n (click)=\"nextMonth()\"\n [attr.aria-label]=\"commonStrings.keys.datepickerNextMonth\"\n >\n <cds-icon shape=\"angle\" direction=\"right\" [attr.title]=\"commonStrings.keys.datepickerNextMonth\"></cds-icon>\n </button>\n </div>\n</div>\n<clr-calendar></clr-calendar>\n<div class=\"clr-sr-only\">{{commonStrings.keys.modalContentEnd}}</div>\n" }]
8719
8719
  }], ctorParameters: function () { return [{ type: ViewManagerService }, { type: DateNavigationService }, { type: LocaleHelperService }, { type: ClrCommonStringsService }]; } });
8720
8720
 
8721
8721
  /*
@@ -12797,8 +12797,10 @@ class Items {
12797
12797
  this.loading = false;
12798
12798
  /**
12799
12799
  * Tracking function to identify objects. Default is reference equality.
12800
+ *
12801
+ * @deprecated in v15 and scheduled for removal in v17 (CDE-71)
12800
12802
  */
12801
- this.trackBy = (_index, item) => item;
12803
+ this.iteratorTrackBy = (_index, item) => item;
12802
12804
  /**
12803
12805
  * Whether we should use smart items for this datagrid or let the user handle
12804
12806
  * everything.
@@ -12872,6 +12874,22 @@ class Items {
12872
12874
  this._filterItems();
12873
12875
  }
12874
12876
  }
12877
+ canTrackBy() {
12878
+ // all items are needed unless `datagridTrackBy` is set because `iteratorTrackBy` requires the item's index
12879
+ return !!this.datagridTrackBy || Array.isArray(this.all);
12880
+ }
12881
+ trackBy(item, index) {
12882
+ if (this.datagridTrackBy) {
12883
+ return this.datagridTrackBy(item);
12884
+ }
12885
+ else if (Array.isArray(this.all)) {
12886
+ index = index !== null && index !== void 0 ? index : this.all.indexOf(item);
12887
+ return this.iteratorTrackBy(index, item);
12888
+ }
12889
+ else {
12890
+ throw new Error('improper call to Items#trackBy');
12891
+ }
12892
+ }
12875
12893
  get displayed() {
12876
12894
  // Ideally we could return an immutable array, but we don't have it in Clarity yet.
12877
12895
  return this._displayed;
@@ -12971,7 +12989,7 @@ class ClrDatagridItems {
12971
12989
  this._rawItems = items ? items : []; // local copy for ngOnChange diffing
12972
12990
  }
12973
12991
  set trackBy(value) {
12974
- this.items.trackBy = value;
12992
+ this.items.iteratorTrackBy = value;
12975
12993
  this.iterableProxy.ngForTrackBy = value;
12976
12994
  }
12977
12995
  /**
@@ -13482,17 +13500,15 @@ class Selection {
13482
13500
  }
13483
13501
  case SelectionType.Single: {
13484
13502
  let newSingle;
13485
- const trackBy = this._items.trackBy;
13486
13503
  let selectionUpdated = false;
13487
13504
  // if the currentSingle has been set before data was loaded, we look up and save the ref from current data set
13488
13505
  if (this.currentSingle && !this.prevSingleSelectionRef) {
13489
- if (this._items.all && this._items.trackBy) {
13490
- const lookup = this._items.all.findIndex(maybe => maybe === this.currentSingle);
13491
- this.prevSingleSelectionRef = this._items.trackBy(lookup, this.currentSingle);
13506
+ if (this._items.canTrackBy()) {
13507
+ this.prevSingleSelectionRef = this._items.trackBy(this.currentSingle);
13492
13508
  }
13493
13509
  }
13494
13510
  updatedItems.forEach((item, index) => {
13495
- const ref = trackBy(index, item);
13511
+ const ref = this._items.trackBy(item, index);
13496
13512
  // If one of the updated items is the previously selectedSingle, set it as the new one
13497
13513
  if (this.prevSingleSelectionRef === ref) {
13498
13514
  newSingle = item;
@@ -13522,15 +13538,13 @@ class Selection {
13522
13538
  }
13523
13539
  case SelectionType.Multi: {
13524
13540
  let leftOver = this.current.slice();
13525
- const trackBy = this._items.trackBy;
13526
13541
  let selectionUpdated = false;
13527
13542
  // if the current has been set before data was loaded, we look up and save the ref from current data set
13528
13543
  if (this.current.length > 0 && this.prevSelectionRefs.length !== this.current.length) {
13529
- if (this._items.all && this._items.trackBy) {
13544
+ if (this._items.canTrackBy()) {
13530
13545
  this.prevSelectionRefs = [];
13531
13546
  this.current.forEach(item => {
13532
- const lookup = this._items.all.findIndex(maybe => maybe === item);
13533
- this.prevSelectionRefs.push(this._items.trackBy(lookup, item));
13547
+ this.prevSelectionRefs.push(this._items.trackBy(item));
13534
13548
  });
13535
13549
  }
13536
13550
  }
@@ -13540,7 +13554,7 @@ class Selection {
13540
13554
  //
13541
13555
  // The both loops below that goes over updatedItems could be combined into one.
13542
13556
  updatedItems.forEach((item, index) => {
13543
- const ref = trackBy(index, item);
13557
+ const ref = this._items.trackBy(item, index);
13544
13558
  if (this.lockedRefs.indexOf(ref) > -1) {
13545
13559
  updateLockedRef.push(ref);
13546
13560
  }
@@ -13550,7 +13564,7 @@ class Selection {
13550
13564
  // the if statement below results in broken behavior.
13551
13565
  if (leftOver.length > 0) {
13552
13566
  updatedItems.forEach((item, index) => {
13553
- const ref = trackBy(index, item);
13567
+ const ref = this._items.trackBy(item, index);
13554
13568
  // Look in current selected refs array if item is selected, and update actual value
13555
13569
  const selectedIndex = this.prevSelectionRefs.indexOf(ref);
13556
13570
  if (selectedIndex > -1) {
@@ -13626,9 +13640,8 @@ class Selection {
13626
13640
  return;
13627
13641
  }
13628
13642
  this._currentSingle = value;
13629
- if (this._items.all && this._items.trackBy && value) {
13630
- const lookup = this._items.all.findIndex(maybe => maybe === value);
13631
- this.prevSingleSelectionRef = this._items.trackBy(lookup, value);
13643
+ if (this._items.canTrackBy() && value) {
13644
+ this.prevSingleSelectionRef = this._items.trackBy(value);
13632
13645
  }
13633
13646
  this.emitChange();
13634
13647
  }
@@ -13673,10 +13686,9 @@ class Selection {
13673
13686
  */
13674
13687
  selectItem(item) {
13675
13688
  this.current = this.current.concat(item);
13676
- if (this._items.trackBy && this._items.all) {
13689
+ if (this._items.canTrackBy()) {
13677
13690
  // Push selected ref onto array
13678
- const lookup = this._items.all.findIndex(maybe => maybe === item);
13679
- this.prevSelectionRefs.push(this._items.trackBy(lookup, item));
13691
+ this.prevSelectionRefs.push(this._items.trackBy(item));
13680
13692
  }
13681
13693
  }
13682
13694
  /**
@@ -13684,7 +13696,7 @@ class Selection {
13684
13696
  */
13685
13697
  deselectItem(indexOfItem) {
13686
13698
  this.current = this.current.slice(0, indexOfItem).concat(this.current.slice(indexOfItem + 1));
13687
- if (this._items.trackBy && indexOfItem < this.prevSelectionRefs.length) {
13699
+ if (indexOfItem < this.prevSelectionRefs.length) {
13688
13700
  // Keep selected refs array in sync
13689
13701
  const removedItems = this.prevSelectionRefs.splice(indexOfItem, 1);
13690
13702
  // locked reference is no longer needed (if any)
@@ -13734,21 +13746,16 @@ class Selection {
13734
13746
  }
13735
13747
  /**
13736
13748
  * Make sure that it could be locked
13737
- *
13738
- * @remark
13739
- * Check also is items.all an array, if not there is no nothing to lock or compare to
13740
- *
13741
13749
  */
13742
13750
  canItBeLocked() {
13743
- // We depend on the trackBy and all so there are part of the requirement of is item could be locked
13744
- return this._selectionType !== SelectionType.None && Array.isArray(this._items.all);
13751
+ return this._selectionType !== SelectionType.None && this._items.canTrackBy();
13745
13752
  }
13746
13753
  /**
13747
13754
  * Lock and unlock item
13748
13755
  */
13749
13756
  lockItem(item, lock) {
13750
13757
  if (this.canItBeLocked()) {
13751
- const ref = this._items.trackBy(this._items.all.findIndex(maybe => maybe === item), item);
13758
+ const ref = this._items.trackBy(item);
13752
13759
  if (lock === true) {
13753
13760
  // Add to lockedRef
13754
13761
  this.lockedRefs.push(ref);
@@ -13768,7 +13775,7 @@ class Selection {
13768
13775
  * into the array when there is no need for that.
13769
13776
  */
13770
13777
  if (this.canItBeLocked()) {
13771
- const ref = this._items.trackBy(this._items.all.findIndex(maybe => maybe === item), item);
13778
+ const ref = this._items.trackBy(item);
13772
13779
  return this.lockedRefs.indexOf(ref) > -1;
13773
13780
  }
13774
13781
  return false;
@@ -13893,6 +13900,8 @@ class ClrDatagridRow {
13893
13900
  this.SELECTION_TYPE = SelectionType;
13894
13901
  this.expandAnimationTrigger = false;
13895
13902
  this._selected = false;
13903
+ // By default, every item is selectable; it becomes not selectable only if it's explicitly set to false
13904
+ this._selectable = true;
13896
13905
  this.selectedChanged = new EventEmitter(false);
13897
13906
  this.expandedChange = new EventEmitter(false);
13898
13907
  this._detailOpenLabel = '';
@@ -13919,6 +13928,16 @@ class ClrDatagridRow {
13919
13928
  }
13920
13929
  }));
13921
13930
  }
13931
+ /**
13932
+ * Model of the row, to use for selection
13933
+ */
13934
+ set item(item) {
13935
+ this._item = item;
13936
+ this.clrDgSelectable = this._selectable;
13937
+ }
13938
+ get item() {
13939
+ return this._item;
13940
+ }
13922
13941
  /**
13923
13942
  * The default behavior in Chrome and Firefox for shift-clicking on a label is to perform text-selection.
13924
13943
  * This prevents our intended range-selection, because this text-selection overrides our shift-click event.
@@ -13962,9 +13981,12 @@ class ClrDatagridRow {
13962
13981
  this.selection.setSelected(this.item, value);
13963
13982
  }
13964
13983
  }
13965
- // By default every item is selectable; it becomes not selectable only if it's explicitly set to false
13966
13984
  set clrDgSelectable(value) {
13967
- this.selection.lockItem(this.item, value === false);
13985
+ if (this.item) {
13986
+ this.selection.lockItem(this.item, value === 'false' || value === false);
13987
+ }
13988
+ // Store this value locally, to be initialized when item is initialized
13989
+ this._selectable = value;
13968
13990
  }
13969
13991
  get clrDgSelectable() {
13970
13992
  return !this.selection.isLocked(this.item);
@@ -14085,7 +14107,7 @@ ClrDatagridRow.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version
14085
14107
  DatagridIfExpandService,
14086
14108
  { provide: IfExpandService, useExisting: DatagridIfExpandService },
14087
14109
  { provide: LoadingListener, useExisting: DatagridIfExpandService },
14088
- ], queries: [{ propertyName: "dgCells", predicate: ClrDatagridCell }], viewQueries: [{ propertyName: "expandAnimation", first: true, predicate: ClrExpandableAnimation, descendants: true }, { propertyName: "detailButton", first: true, predicate: ["detailButton"], descendants: true }, { propertyName: "_stickyCells", first: true, predicate: ["stickyCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_scrollableCells", first: true, predicate: ["scrollableCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_calculatedCells", first: true, predicate: ["calculatedCells"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<!--\n We need to wrap the #rowContent in label element if we are in rowSelectionMode.\n Clicking of that wrapper label will equate to clicking on the whole row, which triggers the checkbox to toggle.\n-->\n<label class=\"datagrid-row-clickable clr-col-null\" *ngIf=\"selection.rowSelectionMode\" (mousedown)=\"clearRanges($event)\">\n <clr-expandable-animation [clrExpandTrigger]=\"expandAnimationTrigger\" *ngIf=\"expand.expandable\">\n <ng-template [ngTemplateOutlet]=\"rowContent\"></ng-template>\n </clr-expandable-animation>\n <ng-template [ngTemplateOutlet]=\"rowContent\" *ngIf=\"!expand.expandable\"></ng-template>\n</label>\n\n<clr-expandable-animation\n *ngIf=\"!selection.rowSelectionMode && expand.expandable\"\n [clrExpandTrigger]=\"expandAnimationTrigger\"\n>\n <ng-template [ngTemplateOutlet]=\"rowContent\"></ng-template>\n</clr-expandable-animation>\n\n<ng-template *ngIf=\"!selection.rowSelectionMode && !expand.expandable\" [ngTemplateOutlet]=\"rowContent\"></ng-template>\n\n<!--\n We need the \"project into template\" hacks because we need this in 2 different places\n depending on whether the details replace the row or not.\n-->\n<ng-template #detail>\n <ng-content select=\"clr-dg-row-detail\"></ng-content>\n</ng-template>\n\n<ng-template #rowContent>\n <div\n role=\"row\"\n [id]=\"id\"\n class=\"datagrid-row-master datagrid-row-flex\"\n [class.datagrid-row-detail-open]=\"detailService.isRowOpen(item)\"\n >\n <div class=\"datagrid-row-sticky\">\n <!-- Sticky elements here -->\n <ng-container #stickyCells>\n <div\n *ngIf=\"selection.selectionType === SELECTION_TYPE.Multi\"\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <div class=\"clr-checkbox-wrapper\">\n <input\n type=\"checkbox\"\n [ngModel]=\"selected\"\n (ngModelChange)=\"toggle($event)\"\n [id]=\"checkboxId\"\n [attr.disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-label]=\"clrDgRowAriaLabel\"\n />\n <!-- Usage of class clr-col-null here prevents clr-col-* classes from being added when a datagrid is wrapped inside clrForm -->\n <label [for]=\"checkboxId\" class=\"clr-control-label clr-col-null\" (click)=\"clearRanges($event)\">\n <span class=\"clr-sr-only\">{{commonStrings.keys.select}}</span>\n </label>\n </div>\n </div>\n <div\n *ngIf=\"selection.selectionType === SELECTION_TYPE.Single\"\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <!-- TODO: it would be better if in addition to the generic \"Select\" label, we could add aria-labelledby\n to label the radio by the first cell in the row (typically an id or name).\n It's pretty easy to label it with the whole row since we already have an id for it, but in most\n cases the row is far too long to serve as a label, the screenreader reads every single cell content. -->\n <input\n type=\"radio\"\n clrRadio\n [id]=\"radioId\"\n [name]=\"selection.id + '-radio'\"\n [value]=\"item\"\n [(ngModel)]=\"selection.currentSingle\"\n [checked]=\"selection.currentSingle === item\"\n [attr.disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-label]=\"clrDgRowAriaLabel\"\n />\n </div>\n <div\n *ngIf=\"rowActionService.hasActionableRow\"\n class=\"datagrid-row-actions datagrid-fixed-column datagrid-cell\"\n role=\"gridcell\"\n >\n <ng-content select=\"clr-dg-action-overflow\"></ng-content>\n </div>\n <div\n *ngIf=\"globalExpandable.hasExpandableRow\"\n class=\"datagrid-expandable-caret datagrid-fixed-column datagrid-cell\"\n role=\"gridcell\"\n >\n <ng-container *ngIf=\"expand.expandable\">\n <button\n *ngIf=\"!expand.loading\"\n (click)=\"toggleExpand()\"\n type=\"button\"\n class=\"datagrid-expandable-caret-button\"\n [attr.aria-expanded]=\"expand.expanded\"\n [attr.aria-label]=\"expand.expanded ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-controls]=\"expandableId\"\n >\n <cds-icon\n shape=\"angle\"\n class=\"datagrid-expandable-caret-icon\"\n [attr.direction]=\"expand.expanded ? 'down' : 'right'\"\n [attr.title]=\"expand.expanded ? commonStrings.keys.collapse : commonStrings.keys.expand\"\n ></cds-icon>\n </button>\n <clr-spinner *ngIf=\"expand.loading\" clrSmall>{{ commonStrings.keys.loading }}</clr-spinner>\n </ng-container>\n </div>\n <div *ngIf=\"detailService.enabled\" class=\"datagrid-detail-caret datagrid-fixed-column datagrid-cell\">\n <button\n (click)=\"detailService.toggle(item, detailButton)\"\n type=\"button\"\n #detailButton\n class=\"datagrid-detail-caret-button\"\n [class.is-open]=\"detailService.isRowOpen(item)\"\n [attr.aria-label]=\"detailService.isRowOpen(item) ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-expanded]=\"detailService.isOpen\"\n [attr.aria-controls]=\"detailService.id\"\n aria-haspopup=\"dialog\"\n >\n <cds-icon\n shape=\"angle-double\"\n [attr.direction]=\"detailService.isRowOpen(item) ? 'left' : 'right'\"\n class=\"datagrid-detail-caret-icon\"\n [attr.title]=\"detailService.isRowOpen(item) ? commonStrings.keys.close: commonStrings.keys.open\"\n ></cds-icon>\n </button>\n </div>\n </ng-container>\n <!-- placeholder for projecting other sticky cells as pinned-->\n </div>\n <div class=\"datagrid-row-scrollable\" [ngClass]=\"{'is-replaced': replaced && expanded}\">\n <div class=\"datagrid-scrolling-cells\">\n <ng-content select=\"clr-dg-cell\"></ng-content>\n <ng-container #scrollableCells></ng-container>\n </div>\n <!-- details here when replace, re-visit when sticky container is used for pinned cells -->\n <ng-template *ngIf=\"replaced && !expand.loading\" [ngTemplateOutlet]=\"detail\"></ng-template>\n <ng-template *ngIf=\"!replaced && !expand.loading\" [ngTemplateOutlet]=\"detail\"></ng-template>\n </div>\n </div>\n</ng-template>\n\n<ng-container #calculatedCells></ng-container>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: CdsIconCustomTag, selector: "cds-icon" }, { kind: "directive", type: ClrLabel, selector: "label", inputs: ["for"] }, { kind: "directive", type: ClrRadio, selector: "[clrRadio]" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ClrExpandableAnimation, selector: "clr-expandable-animation", inputs: ["clrExpandTrigger"] }, { kind: "component", type: ClrSpinner, selector: "clr-spinner", inputs: ["clrInline", "clrInverse", "clrSmall", "clrMedium"] }, { kind: "directive", type: ClrDatagridSelectionCellDirective, selector: ".datagrid-select" }] });
14110
+ ], queries: [{ propertyName: "dgCells", predicate: ClrDatagridCell }], viewQueries: [{ propertyName: "expandAnimation", first: true, predicate: ClrExpandableAnimation, descendants: true }, { propertyName: "detailButton", first: true, predicate: ["detailButton"], descendants: true }, { propertyName: "_stickyCells", first: true, predicate: ["stickyCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_scrollableCells", first: true, predicate: ["scrollableCells"], descendants: true, read: ViewContainerRef }, { propertyName: "_calculatedCells", first: true, predicate: ["calculatedCells"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<!--\n We need to wrap the #rowContent in label element if we are in rowSelectionMode.\n Clicking of that wrapper label will equate to clicking on the whole row, which triggers the checkbox to toggle.\n-->\n<label class=\"datagrid-row-clickable clr-col-null\" *ngIf=\"selection.rowSelectionMode\" (mousedown)=\"clearRanges($event)\">\n <clr-expandable-animation [clrExpandTrigger]=\"expandAnimationTrigger\" *ngIf=\"expand.expandable\">\n <ng-template [ngTemplateOutlet]=\"rowContent\"></ng-template>\n </clr-expandable-animation>\n <ng-template [ngTemplateOutlet]=\"rowContent\" *ngIf=\"!expand.expandable\"></ng-template>\n</label>\n\n<clr-expandable-animation\n *ngIf=\"!selection.rowSelectionMode && expand.expandable\"\n [clrExpandTrigger]=\"expandAnimationTrigger\"\n>\n <ng-template [ngTemplateOutlet]=\"rowContent\"></ng-template>\n</clr-expandable-animation>\n\n<ng-template *ngIf=\"!selection.rowSelectionMode && !expand.expandable\" [ngTemplateOutlet]=\"rowContent\"></ng-template>\n\n<!--\n We need the \"project into template\" hacks because we need this in 2 different places\n depending on whether the details replace the row or not.\n-->\n<ng-template #detail>\n <ng-content select=\"clr-dg-row-detail\"></ng-content>\n</ng-template>\n\n<ng-template #rowContent>\n <div\n role=\"row\"\n [id]=\"id\"\n class=\"datagrid-row-master datagrid-row-flex\"\n [class.datagrid-row-detail-open]=\"detailService.isRowOpen(item)\"\n >\n <div class=\"datagrid-row-sticky\">\n <!-- Sticky elements here -->\n <ng-container #stickyCells>\n <div\n *ngIf=\"selection.selectionType === SELECTION_TYPE.Multi\"\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <div class=\"clr-checkbox-wrapper\">\n <input\n type=\"checkbox\"\n [ngModel]=\"selected\"\n (ngModelChange)=\"toggle($event)\"\n [id]=\"checkboxId\"\n [disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-label]=\"clrDgRowAriaLabel\"\n />\n <!-- Usage of class clr-col-null here prevents clr-col-* classes from being added when a datagrid is wrapped inside clrForm -->\n <label [for]=\"checkboxId\" class=\"clr-control-label clr-col-null\" (click)=\"clearRanges($event)\">\n <span class=\"clr-sr-only\">{{commonStrings.keys.select}}</span>\n </label>\n </div>\n </div>\n <div\n *ngIf=\"selection.selectionType === SELECTION_TYPE.Single\"\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <!-- TODO: it would be better if in addition to the generic \"Select\" label, we could add aria-labelledby\n to label the radio by the first cell in the row (typically an id or name).\n It's pretty easy to label it with the whole row since we already have an id for it, but in most\n cases the row is far too long to serve as a label, the screenreader reads every single cell content. -->\n <input\n type=\"radio\"\n clrRadio\n [id]=\"radioId\"\n [name]=\"selection.id + '-radio'\"\n [value]=\"item\"\n [(ngModel)]=\"selection.currentSingle\"\n [checked]=\"selection.currentSingle === item\"\n [disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-label]=\"clrDgRowAriaLabel\"\n />\n </div>\n <div\n *ngIf=\"rowActionService.hasActionableRow\"\n class=\"datagrid-row-actions datagrid-fixed-column datagrid-cell\"\n role=\"gridcell\"\n >\n <ng-content select=\"clr-dg-action-overflow\"></ng-content>\n </div>\n <div\n *ngIf=\"globalExpandable.hasExpandableRow\"\n class=\"datagrid-expandable-caret datagrid-fixed-column datagrid-cell\"\n role=\"gridcell\"\n >\n <ng-container *ngIf=\"expand.expandable\">\n <button\n *ngIf=\"!expand.loading\"\n (click)=\"toggleExpand()\"\n type=\"button\"\n class=\"datagrid-expandable-caret-button\"\n [attr.aria-expanded]=\"expand.expanded\"\n [attr.aria-label]=\"expand.expanded ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-controls]=\"expandableId\"\n >\n <cds-icon\n shape=\"angle\"\n class=\"datagrid-expandable-caret-icon\"\n [attr.direction]=\"expand.expanded ? 'down' : 'right'\"\n [attr.title]=\"expand.expanded ? commonStrings.keys.collapse : commonStrings.keys.expand\"\n ></cds-icon>\n </button>\n <clr-spinner *ngIf=\"expand.loading\" clrSmall>{{ commonStrings.keys.loading }}</clr-spinner>\n </ng-container>\n </div>\n <div *ngIf=\"detailService.enabled\" class=\"datagrid-detail-caret datagrid-fixed-column datagrid-cell\">\n <button\n (click)=\"detailService.toggle(item, detailButton)\"\n type=\"button\"\n #detailButton\n class=\"datagrid-detail-caret-button\"\n [class.is-open]=\"detailService.isRowOpen(item)\"\n [attr.aria-label]=\"detailService.isRowOpen(item) ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-expanded]=\"detailService.isOpen\"\n [attr.aria-controls]=\"detailService.id\"\n aria-haspopup=\"dialog\"\n >\n <cds-icon\n shape=\"angle-double\"\n [attr.direction]=\"detailService.isRowOpen(item) ? 'left' : 'right'\"\n class=\"datagrid-detail-caret-icon\"\n [attr.title]=\"detailService.isRowOpen(item) ? commonStrings.keys.close: commonStrings.keys.open\"\n ></cds-icon>\n </button>\n </div>\n </ng-container>\n <!-- placeholder for projecting other sticky cells as pinned-->\n </div>\n <div class=\"datagrid-row-scrollable\" [ngClass]=\"{'is-replaced': replaced && expanded}\">\n <div class=\"datagrid-scrolling-cells\">\n <ng-content select=\"clr-dg-cell\"></ng-content>\n <ng-container #scrollableCells></ng-container>\n </div>\n <!-- details here when replace, re-visit when sticky container is used for pinned cells -->\n <ng-template *ngIf=\"replaced && !expand.loading\" [ngTemplateOutlet]=\"detail\"></ng-template>\n <ng-template *ngIf=\"!replaced && !expand.loading\" [ngTemplateOutlet]=\"detail\"></ng-template>\n </div>\n </div>\n</ng-template>\n\n<ng-container #calculatedCells></ng-container>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: CdsIconCustomTag, selector: "cds-icon" }, { kind: "directive", type: ClrLabel, selector: "label", inputs: ["for"] }, { kind: "directive", type: ClrRadio, selector: "[clrRadio]" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ClrExpandableAnimation, selector: "clr-expandable-animation", inputs: ["clrExpandTrigger"] }, { kind: "component", type: ClrSpinner, selector: "clr-spinner", inputs: ["clrInline", "clrInverse", "clrSmall", "clrMedium"] }, { kind: "directive", type: ClrDatagridSelectionCellDirective, selector: ".datagrid-select" }] });
14089
14111
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ClrDatagridRow, decorators: [{
14090
14112
  type: Component,
14091
14113
  args: [{ selector: 'clr-dg-row', host: {
@@ -14097,7 +14119,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImpor
14097
14119
  DatagridIfExpandService,
14098
14120
  { provide: IfExpandService, useExisting: DatagridIfExpandService },
14099
14121
  { provide: LoadingListener, useExisting: DatagridIfExpandService },
14100
- ], template: "<!--\n We need to wrap the #rowContent in label element if we are in rowSelectionMode.\n Clicking of that wrapper label will equate to clicking on the whole row, which triggers the checkbox to toggle.\n-->\n<label class=\"datagrid-row-clickable clr-col-null\" *ngIf=\"selection.rowSelectionMode\" (mousedown)=\"clearRanges($event)\">\n <clr-expandable-animation [clrExpandTrigger]=\"expandAnimationTrigger\" *ngIf=\"expand.expandable\">\n <ng-template [ngTemplateOutlet]=\"rowContent\"></ng-template>\n </clr-expandable-animation>\n <ng-template [ngTemplateOutlet]=\"rowContent\" *ngIf=\"!expand.expandable\"></ng-template>\n</label>\n\n<clr-expandable-animation\n *ngIf=\"!selection.rowSelectionMode && expand.expandable\"\n [clrExpandTrigger]=\"expandAnimationTrigger\"\n>\n <ng-template [ngTemplateOutlet]=\"rowContent\"></ng-template>\n</clr-expandable-animation>\n\n<ng-template *ngIf=\"!selection.rowSelectionMode && !expand.expandable\" [ngTemplateOutlet]=\"rowContent\"></ng-template>\n\n<!--\n We need the \"project into template\" hacks because we need this in 2 different places\n depending on whether the details replace the row or not.\n-->\n<ng-template #detail>\n <ng-content select=\"clr-dg-row-detail\"></ng-content>\n</ng-template>\n\n<ng-template #rowContent>\n <div\n role=\"row\"\n [id]=\"id\"\n class=\"datagrid-row-master datagrid-row-flex\"\n [class.datagrid-row-detail-open]=\"detailService.isRowOpen(item)\"\n >\n <div class=\"datagrid-row-sticky\">\n <!-- Sticky elements here -->\n <ng-container #stickyCells>\n <div\n *ngIf=\"selection.selectionType === SELECTION_TYPE.Multi\"\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <div class=\"clr-checkbox-wrapper\">\n <input\n type=\"checkbox\"\n [ngModel]=\"selected\"\n (ngModelChange)=\"toggle($event)\"\n [id]=\"checkboxId\"\n [attr.disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-label]=\"clrDgRowAriaLabel\"\n />\n <!-- Usage of class clr-col-null here prevents clr-col-* classes from being added when a datagrid is wrapped inside clrForm -->\n <label [for]=\"checkboxId\" class=\"clr-control-label clr-col-null\" (click)=\"clearRanges($event)\">\n <span class=\"clr-sr-only\">{{commonStrings.keys.select}}</span>\n </label>\n </div>\n </div>\n <div\n *ngIf=\"selection.selectionType === SELECTION_TYPE.Single\"\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <!-- TODO: it would be better if in addition to the generic \"Select\" label, we could add aria-labelledby\n to label the radio by the first cell in the row (typically an id or name).\n It's pretty easy to label it with the whole row since we already have an id for it, but in most\n cases the row is far too long to serve as a label, the screenreader reads every single cell content. -->\n <input\n type=\"radio\"\n clrRadio\n [id]=\"radioId\"\n [name]=\"selection.id + '-radio'\"\n [value]=\"item\"\n [(ngModel)]=\"selection.currentSingle\"\n [checked]=\"selection.currentSingle === item\"\n [attr.disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-label]=\"clrDgRowAriaLabel\"\n />\n </div>\n <div\n *ngIf=\"rowActionService.hasActionableRow\"\n class=\"datagrid-row-actions datagrid-fixed-column datagrid-cell\"\n role=\"gridcell\"\n >\n <ng-content select=\"clr-dg-action-overflow\"></ng-content>\n </div>\n <div\n *ngIf=\"globalExpandable.hasExpandableRow\"\n class=\"datagrid-expandable-caret datagrid-fixed-column datagrid-cell\"\n role=\"gridcell\"\n >\n <ng-container *ngIf=\"expand.expandable\">\n <button\n *ngIf=\"!expand.loading\"\n (click)=\"toggleExpand()\"\n type=\"button\"\n class=\"datagrid-expandable-caret-button\"\n [attr.aria-expanded]=\"expand.expanded\"\n [attr.aria-label]=\"expand.expanded ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-controls]=\"expandableId\"\n >\n <cds-icon\n shape=\"angle\"\n class=\"datagrid-expandable-caret-icon\"\n [attr.direction]=\"expand.expanded ? 'down' : 'right'\"\n [attr.title]=\"expand.expanded ? commonStrings.keys.collapse : commonStrings.keys.expand\"\n ></cds-icon>\n </button>\n <clr-spinner *ngIf=\"expand.loading\" clrSmall>{{ commonStrings.keys.loading }}</clr-spinner>\n </ng-container>\n </div>\n <div *ngIf=\"detailService.enabled\" class=\"datagrid-detail-caret datagrid-fixed-column datagrid-cell\">\n <button\n (click)=\"detailService.toggle(item, detailButton)\"\n type=\"button\"\n #detailButton\n class=\"datagrid-detail-caret-button\"\n [class.is-open]=\"detailService.isRowOpen(item)\"\n [attr.aria-label]=\"detailService.isRowOpen(item) ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-expanded]=\"detailService.isOpen\"\n [attr.aria-controls]=\"detailService.id\"\n aria-haspopup=\"dialog\"\n >\n <cds-icon\n shape=\"angle-double\"\n [attr.direction]=\"detailService.isRowOpen(item) ? 'left' : 'right'\"\n class=\"datagrid-detail-caret-icon\"\n [attr.title]=\"detailService.isRowOpen(item) ? commonStrings.keys.close: commonStrings.keys.open\"\n ></cds-icon>\n </button>\n </div>\n </ng-container>\n <!-- placeholder for projecting other sticky cells as pinned-->\n </div>\n <div class=\"datagrid-row-scrollable\" [ngClass]=\"{'is-replaced': replaced && expanded}\">\n <div class=\"datagrid-scrolling-cells\">\n <ng-content select=\"clr-dg-cell\"></ng-content>\n <ng-container #scrollableCells></ng-container>\n </div>\n <!-- details here when replace, re-visit when sticky container is used for pinned cells -->\n <ng-template *ngIf=\"replaced && !expand.loading\" [ngTemplateOutlet]=\"detail\"></ng-template>\n <ng-template *ngIf=\"!replaced && !expand.loading\" [ngTemplateOutlet]=\"detail\"></ng-template>\n </div>\n </div>\n</ng-template>\n\n<ng-container #calculatedCells></ng-container>\n" }]
14122
+ ], template: "<!--\n We need to wrap the #rowContent in label element if we are in rowSelectionMode.\n Clicking of that wrapper label will equate to clicking on the whole row, which triggers the checkbox to toggle.\n-->\n<label class=\"datagrid-row-clickable clr-col-null\" *ngIf=\"selection.rowSelectionMode\" (mousedown)=\"clearRanges($event)\">\n <clr-expandable-animation [clrExpandTrigger]=\"expandAnimationTrigger\" *ngIf=\"expand.expandable\">\n <ng-template [ngTemplateOutlet]=\"rowContent\"></ng-template>\n </clr-expandable-animation>\n <ng-template [ngTemplateOutlet]=\"rowContent\" *ngIf=\"!expand.expandable\"></ng-template>\n</label>\n\n<clr-expandable-animation\n *ngIf=\"!selection.rowSelectionMode && expand.expandable\"\n [clrExpandTrigger]=\"expandAnimationTrigger\"\n>\n <ng-template [ngTemplateOutlet]=\"rowContent\"></ng-template>\n</clr-expandable-animation>\n\n<ng-template *ngIf=\"!selection.rowSelectionMode && !expand.expandable\" [ngTemplateOutlet]=\"rowContent\"></ng-template>\n\n<!--\n We need the \"project into template\" hacks because we need this in 2 different places\n depending on whether the details replace the row or not.\n-->\n<ng-template #detail>\n <ng-content select=\"clr-dg-row-detail\"></ng-content>\n</ng-template>\n\n<ng-template #rowContent>\n <div\n role=\"row\"\n [id]=\"id\"\n class=\"datagrid-row-master datagrid-row-flex\"\n [class.datagrid-row-detail-open]=\"detailService.isRowOpen(item)\"\n >\n <div class=\"datagrid-row-sticky\">\n <!-- Sticky elements here -->\n <ng-container #stickyCells>\n <div\n *ngIf=\"selection.selectionType === SELECTION_TYPE.Multi\"\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <div class=\"clr-checkbox-wrapper\">\n <input\n type=\"checkbox\"\n [ngModel]=\"selected\"\n (ngModelChange)=\"toggle($event)\"\n [id]=\"checkboxId\"\n [disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-label]=\"clrDgRowAriaLabel\"\n />\n <!-- Usage of class clr-col-null here prevents clr-col-* classes from being added when a datagrid is wrapped inside clrForm -->\n <label [for]=\"checkboxId\" class=\"clr-control-label clr-col-null\" (click)=\"clearRanges($event)\">\n <span class=\"clr-sr-only\">{{commonStrings.keys.select}}</span>\n </label>\n </div>\n </div>\n <div\n *ngIf=\"selection.selectionType === SELECTION_TYPE.Single\"\n class=\"datagrid-select datagrid-fixed-column datagrid-cell\"\n [ngClass]=\"{ 'clr-form-control-disabled': !clrDgSelectable }\"\n role=\"gridcell\"\n >\n <!-- TODO: it would be better if in addition to the generic \"Select\" label, we could add aria-labelledby\n to label the radio by the first cell in the row (typically an id or name).\n It's pretty easy to label it with the whole row since we already have an id for it, but in most\n cases the row is far too long to serve as a label, the screenreader reads every single cell content. -->\n <input\n type=\"radio\"\n clrRadio\n [id]=\"radioId\"\n [name]=\"selection.id + '-radio'\"\n [value]=\"item\"\n [(ngModel)]=\"selection.currentSingle\"\n [checked]=\"selection.currentSingle === item\"\n [disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-disabled]=\"clrDgSelectable ? null : true\"\n [attr.aria-label]=\"clrDgRowAriaLabel\"\n />\n </div>\n <div\n *ngIf=\"rowActionService.hasActionableRow\"\n class=\"datagrid-row-actions datagrid-fixed-column datagrid-cell\"\n role=\"gridcell\"\n >\n <ng-content select=\"clr-dg-action-overflow\"></ng-content>\n </div>\n <div\n *ngIf=\"globalExpandable.hasExpandableRow\"\n class=\"datagrid-expandable-caret datagrid-fixed-column datagrid-cell\"\n role=\"gridcell\"\n >\n <ng-container *ngIf=\"expand.expandable\">\n <button\n *ngIf=\"!expand.loading\"\n (click)=\"toggleExpand()\"\n type=\"button\"\n class=\"datagrid-expandable-caret-button\"\n [attr.aria-expanded]=\"expand.expanded\"\n [attr.aria-label]=\"expand.expanded ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-controls]=\"expandableId\"\n >\n <cds-icon\n shape=\"angle\"\n class=\"datagrid-expandable-caret-icon\"\n [attr.direction]=\"expand.expanded ? 'down' : 'right'\"\n [attr.title]=\"expand.expanded ? commonStrings.keys.collapse : commonStrings.keys.expand\"\n ></cds-icon>\n </button>\n <clr-spinner *ngIf=\"expand.loading\" clrSmall>{{ commonStrings.keys.loading }}</clr-spinner>\n </ng-container>\n </div>\n <div *ngIf=\"detailService.enabled\" class=\"datagrid-detail-caret datagrid-fixed-column datagrid-cell\">\n <button\n (click)=\"detailService.toggle(item, detailButton)\"\n type=\"button\"\n #detailButton\n class=\"datagrid-detail-caret-button\"\n [class.is-open]=\"detailService.isRowOpen(item)\"\n [attr.aria-label]=\"detailService.isRowOpen(item) ? clrDgDetailCloseLabel : clrDgDetailOpenLabel\"\n [attr.aria-expanded]=\"detailService.isOpen\"\n [attr.aria-controls]=\"detailService.id\"\n aria-haspopup=\"dialog\"\n >\n <cds-icon\n shape=\"angle-double\"\n [attr.direction]=\"detailService.isRowOpen(item) ? 'left' : 'right'\"\n class=\"datagrid-detail-caret-icon\"\n [attr.title]=\"detailService.isRowOpen(item) ? commonStrings.keys.close: commonStrings.keys.open\"\n ></cds-icon>\n </button>\n </div>\n </ng-container>\n <!-- placeholder for projecting other sticky cells as pinned-->\n </div>\n <div class=\"datagrid-row-scrollable\" [ngClass]=\"{'is-replaced': replaced && expanded}\">\n <div class=\"datagrid-scrolling-cells\">\n <ng-content select=\"clr-dg-cell\"></ng-content>\n <ng-container #scrollableCells></ng-container>\n </div>\n <!-- details here when replace, re-visit when sticky container is used for pinned cells -->\n <ng-template *ngIf=\"replaced && !expand.loading\" [ngTemplateOutlet]=\"detail\"></ng-template>\n <ng-template *ngIf=\"!replaced && !expand.loading\" [ngTemplateOutlet]=\"detail\"></ng-template>\n </div>\n </div>\n</ng-template>\n\n<ng-container #calculatedCells></ng-container>\n" }]
14101
14123
  }], ctorParameters: function () {
14102
14124
  return [{ type: Selection }, { type: RowActionService }, { type: ExpandableRowsCount }, { type: DatagridIfExpandService }, { type: DetailService }, { type: DisplayModeService }, { type: i0.ViewContainerRef }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: ClrCommonStringsService }, { type: Items }, { type: undefined, decorators: [{
14103
14125
  type: Inject,
@@ -14547,6 +14569,9 @@ class ClrDatagrid {
14547
14569
  set rowSelectionMode(value) {
14548
14570
  this.selection.rowSelectionMode = value;
14549
14571
  }
14572
+ set trackBy(value) {
14573
+ this.items.datagridTrackBy = value;
14574
+ }
14550
14575
  /**
14551
14576
  * Indicates if all currently displayed items are selected
14552
14577
  */
@@ -14585,9 +14610,9 @@ class ClrDatagrid {
14585
14610
  });
14586
14611
  // Try to update only when there is something cached and its open.
14587
14612
  if (this.detailService.state && this.detailService.isOpen) {
14588
- const row = this.rows.find((row, index) => {
14589
- return this.items.trackBy(index, row.item) === this.items.trackBy(index, this.detailService.state);
14590
- });
14613
+ const row = this.items.canTrackBy()
14614
+ ? this.rows.find(row => this.items.trackBy(row.item) === this.items.trackBy(this.detailService.state))
14615
+ : undefined;
14591
14616
  /**
14592
14617
  * Reopen updated row or close it
14593
14618
  */
@@ -14680,7 +14705,7 @@ class ClrDatagrid {
14680
14705
  }
14681
14706
  }
14682
14707
  ClrDatagrid.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.2", ngImport: i0, type: ClrDatagrid, deps: [{ token: DatagridRenderOrganizer }, { token: Items }, { token: ExpandableRowsCount }, { token: Selection }, { token: RowActionService }, { token: StateProvider }, { token: DisplayModeService }, { token: i0.Renderer2 }, { token: DetailService }, { token: DOCUMENT }, { token: i0.ElementRef }, { token: Page }, { token: ClrCommonStringsService }, { token: ColumnsService }, { token: KeyNavigationGridController }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
14683
- ClrDatagrid.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.2", type: ClrDatagrid, selector: "clr-datagrid", inputs: { loading: ["clrDgLoading", "loading"], selected: ["clrDgSelected", "selected"], singleSelected: ["clrDgSingleSelected", "singleSelected"], clrDgSingleSelectionAriaLabel: "clrDgSingleSelectionAriaLabel", clrDgSingleActionableAriaLabel: "clrDgSingleActionableAriaLabel", clrDetailExpandableAriaLabel: "clrDetailExpandableAriaLabel", clrDgDisablePageFocus: "clrDgDisablePageFocus", clrDgPreserveSelection: "clrDgPreserveSelection", rowSelectionMode: ["clrDgRowSelection", "rowSelectionMode"] }, outputs: { refresh: "clrDgRefresh", selectedChanged: "clrDgSelectedChange", singleSelectedChanged: "clrDgSingleSelectedChange" }, host: { properties: { "class.datagrid-host": "true", "class.datagrid-detail-open": "detailService.isOpen" } }, providers: [
14708
+ ClrDatagrid.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.2", type: ClrDatagrid, selector: "clr-datagrid", inputs: { loading: ["clrDgLoading", "loading"], selected: ["clrDgSelected", "selected"], singleSelected: ["clrDgSingleSelected", "singleSelected"], clrDgSingleSelectionAriaLabel: "clrDgSingleSelectionAriaLabel", clrDgSingleActionableAriaLabel: "clrDgSingleActionableAriaLabel", clrDetailExpandableAriaLabel: "clrDetailExpandableAriaLabel", clrDgDisablePageFocus: "clrDgDisablePageFocus", clrDgPreserveSelection: "clrDgPreserveSelection", rowSelectionMode: ["clrDgRowSelection", "rowSelectionMode"], trackBy: ["clrDgItemsTrackBy", "trackBy"] }, outputs: { refresh: "clrDgRefresh", selectedChanged: "clrDgSelectedChange", singleSelectedChanged: "clrDgSingleSelectedChange" }, host: { properties: { "class.datagrid-host": "true", "class.datagrid-detail-open": "detailService.isOpen" } }, providers: [
14684
14709
  Selection,
14685
14710
  Sort,
14686
14711
  FiltersProvider,
@@ -14758,6 +14783,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImpor
14758
14783
  }], rowSelectionMode: [{
14759
14784
  type: Input,
14760
14785
  args: ['clrDgRowSelection']
14786
+ }], trackBy: [{
14787
+ type: Input,
14788
+ args: ['clrDgItemsTrackBy']
14761
14789
  }], placeholder: [{
14762
14790
  type: ContentChild,
14763
14791
  args: [ClrDatagridPlaceholder]
@@ -14958,6 +14986,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.2", ngImpor
14958
14986
  args: ['clrDgActionOverflowOpenChange']
14959
14987
  }] } });
14960
14988
 
14989
+ /*
14990
+ * Copyright (c) 2016-2023 VMware, Inc. All Rights Reserved.
14991
+ * This software is released under MIT license.
14992
+ * The full license information can be found in LICENSE in the root directory of this project.
14993
+ */
14994
+ const columnToggleTrackByFn = index => index;
14995
+
14961
14996
  /*
14962
14997
  * Copyright (c) 2016-2023 VMware, Inc. All Rights Reserved.
14963
14998
  * This software is released under MIT license.
@@ -14968,8 +15003,18 @@ class ClrDatagridItemsTrackBy {
14968
15003
  this._items = _items;
14969
15004
  }
14970
15005
  set trackBy(value) {
15006
+ /**
15007
+ * This is a workaround to prevent the items `trackBy` function from
15008
+ * being replaced when the "manage columns" button is clicked. This is
15009
+ * not a complete solution. If there is another `ngForTrackBy` function
15010
+ * within the datagrid in application code, it could sill replace the
15011
+ * items `trackBy` function whether it is the row iterator or not.
15012
+ */
15013
+ if (value === columnToggleTrackByFn) {
15014
+ return;
15015
+ }
14971
15016
  if (this._items) {
14972
- this._items.trackBy = value;
15017
+ this._items.iteratorTrackBy = value;
14973
15018
  }
14974
15019
  }
14975
15020
  }
@@ -15067,7 +15112,7 @@ class ClrDatagridColumnToggle {
15067
15112
  };
15068
15113
  // Without tracking the checkboxes get rerendered on model update, which leads
15069
15114
  // to loss of focus after checkbox toggle.
15070
- this.trackByFn = index => index;
15115
+ this.trackByFn = columnToggleTrackByFn;
15071
15116
  this.subscription = popoverToggleService.openChange.subscribe(change => (this.openState = change));
15072
15117
  }
15073
15118
  get allColumnsVisible() {