diff --git a/CHANGELOG.md b/CHANGELOG.md index 9565b5331b2..b07453d56fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,28 @@ All notable changes for each version of this project will be documented in this file. -## 12.1.6 +## 12.2.0 + +### General +- `igxGrid`, `igxHierarchicalGrid`, `igxTreeGrid` + - 'oddRowCSS' and 'evenRowCSS' properties has been deprecated ### New Features - `igxGrid`, `igxHierarchicalGrid`, `igxTreeGrid` + - Added two public methods that spawn the add row UI for an arbitrary record in the current data view. One that accepts a rowID to use as the row the UI spawns under and the other accepting an index that has a distinct implementation for `IgxTreeGrid`. Please, refer to the official documentation for more information:[Grid Row Adding](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/row-adding) and [Tree Grid Row Adding](https://www.infragistics.com/products/ignite-ui-angular/angular/components/treegrid/row-adding). + + _Note:_ That the new record is still added at the end of the data view, after the end-user submits it. + ```typescript + this.grid.beginAddRowById('ALFKI'); // spawns the add row UI under the row with PK 'ALFKI' + this.grid.beginAddRowById(null); // spawns the add row UI as the first record + this.grid.beginAddRowByIndex(10); // spawns the add row UI at index 10 + this.grid.beginAddRowByIndex(0); // spawns the add row UI as the first record + this.treeGrid.beginAddRowById('ALFKI', true); // spawns the add row UI to add a child for the row with PK 'ALFKI' + this.treeGrid.beginAddRowByIndex(10, true); // spawns the add row UI to add a child for the row at index 10 + this.treeGrid.beginAddRowByIndex(null); // spawns the add row UI as the first record + ``` - Added capability to restore the state of multi column headers with `IgxGridStateDirective`. + - Introduced new 'rowStyles' and 'rowClasses' grid properties which allows to define a custom styling on each grid row ## 12.1.3 @@ -69,7 +86,7 @@ All notable changes for each version of this project will be documented in this - `IgxGridCellComponent`, `IgxTreeGridCellComponent`, `IgxHierarchicalGridCellComponent` are no longer exposed in the public API. Instead, a new class `IgxGridCell` replaces all of these. It is a facade class which exposes only the public API of the above mentioned. Automatic migration will change these imports with `CellType`, which is the interface implemented by `IgxGridCell` - **Behavioral changes** - `getCellByKey`, `getCellByColumn`, `getCellByColumnVisibleIndex`, `row.cells`, `column.cells`, `grid.selectedCells` now return an `IgxGridCell` the `CellType` interface. - - `cell` in `IGridCellEventArgs` is now `CellType`. `IGridCellEventArgs` are emitetd in `cellClick`, `selected`, `contextMenu` and `doubleClick` events. + - `cell` in `IGridCellEventArgs` is now `CellType`. `IGridCellEventArgs` are emitted in `cellClick`, `selected`, `contextMenu` and `doubleClick` events. - `let-cell` property in cell template is now `CellType`. - `getCellByColumnVisibleIndex` is now deprecated and will be removed in next major version. Use `getCellByKey`, `getCellByColumn` instead. diff --git a/projects/igniteui-angular-i18n/src/i18n/DA/grid-resources.ts b/projects/igniteui-angular-i18n/src/i18n/DA/grid-resources.ts index be7ae6e6505..b936efe9069 100644 --- a/projects/igniteui-angular-i18n/src/i18n/DA/grid-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/DA/grid-resources.ts @@ -6,7 +6,7 @@ const GridResourceStringsDA_: ExpandRequire = { igx_grid_groupByArea_select_message: 'Vælg alle rækker i gruppen med navnet {0} og værdi {1}.', igx_grid_groupByArea_deselect_message: 'Fravælg alle rækker i gruppen med navnet {0} og værdi {1}.', igx_grid_emptyFilteredGrid_message: 'Ingen poster fundet', - igx_grid_emptyGrid_message: 'Gitter har ingen data', + igx_grid_emptyGrid_message: 'Tabel har ingen data', igx_grid_filter: 'Filter', igx_grid_filter_row_close: 'Luk', igx_grid_filter_row_reset: 'Nulstil', diff --git a/projects/igniteui-angular-i18n/src/i18n/NB/calendar-resources.ts b/projects/igniteui-angular-i18n/src/i18n/NB/calendar-resources.ts new file mode 100644 index 00000000000..47991d0c2c1 --- /dev/null +++ b/projects/igniteui-angular-i18n/src/i18n/NB/calendar-resources.ts @@ -0,0 +1,24 @@ +import { ICalendarResourceStrings } from 'igniteui-angular'; + +// exported below as re-cast to create declaration type with expanded properties +const CalendarResourceStringsNB_: ExpandRequire = { + igx_calendar_previous_month: 'Forrige måned', + igx_calendar_next_month: 'Neste måned', + igx_calendar_select_month: 'Velg måned', + igx_calendar_select_year: 'Velg år', + igx_calendar_range_start: 'Rekkevidde start', + igx_calendar_range_end: 'Rekkevidde slutt', + igx_calendar_selected_month_is: 'Valgt måned er ', + igx_calendar_first_picker_of: 'Den første plukkeren på {0} starter fra', + igx_calendar_multi_selection: 'Flervalgskalender med {0} datovelgere', + igx_calendar_range_selection: 'Områdevalgskalender med {0} datovelgere', + igx_calendar_single_selection: 'Kalender med {0} datovelgere', + igx_calendar_singular_multi_selection: 'Kalender med flere valg', + igx_calendar_singular_range_selection: 'Områdevalgskalender', + igx_calendar_singular_single_selection: 'Kalender' +}; + +/** + * Norwegian resource strings for IgxCalendar + */ +export const CalendarResourceStringsNB = CalendarResourceStringsNB_ as ExpandRequire; diff --git a/projects/igniteui-angular-i18n/src/i18n/NB/carousel-resources.ts b/projects/igniteui-angular-i18n/src/i18n/NB/carousel-resources.ts new file mode 100644 index 00000000000..0e1a1e899c7 --- /dev/null +++ b/projects/igniteui-angular-i18n/src/i18n/NB/carousel-resources.ts @@ -0,0 +1,14 @@ +import { ICarouselResourceStrings } from 'igniteui-angular'; + +// exported below as re-cast to create declaration type with expanded properties +const CarouselResourceStringsNB_: ExpandRequire = { + igx_carousel_of: 'av', + igx_carousel_slide: 'lysbilde', + igx_carousel_previous_slide: 'forrige lysbilde', + igx_carousel_next_slide: 'neste lysbilde' +}; + +/** + * Norwegian resource strings for IgxCarousel + */ +export const CarouselResourceStringsNB = CarouselResourceStringsNB_ as ExpandRequire; diff --git a/projects/igniteui-angular-i18n/src/i18n/NB/date-picker-resources.ts b/projects/igniteui-angular-i18n/src/i18n/NB/date-picker-resources.ts new file mode 100644 index 00000000000..2d415e5bfaf --- /dev/null +++ b/projects/igniteui-angular-i18n/src/i18n/NB/date-picker-resources.ts @@ -0,0 +1,12 @@ +import { IDatePickerResourceStrings } from 'igniteui-angular'; + +// exported below as re-cast to create declaration type with expanded properties +const DatePickerResourceStringsNB_: ExpandRequire = { + igx_date_picker_change_date: 'Endre dato', + igx_date_picker_choose_date: 'Velg dato' +}; + +/** + * Portuguese resource strings for IgxDatePicker + */ +export const DatePickerResourceStringsNB = DatePickerResourceStringsNB_ as ExpandRequire; diff --git a/projects/igniteui-angular-i18n/src/i18n/NB/date-range-picker-resources.ts b/projects/igniteui-angular-i18n/src/i18n/NB/date-range-picker-resources.ts new file mode 100644 index 00000000000..f8db0b592c9 --- /dev/null +++ b/projects/igniteui-angular-i18n/src/i18n/NB/date-range-picker-resources.ts @@ -0,0 +1,12 @@ +import { IDateRangePickerResourceStrings } from 'igniteui-angular'; + +// exported below as re-cast to create declaration type with expanded properties +const DateRangePickerResourceStringsNB_: ExpandRequire = { + igx_date_range_picker_date_separator: 'til', + igx_date_range_picker_done_button: 'Ferdig' +}; + +/** + * Norwegian resource strings for IgxDateRangePicker + */ +export const DateRangePickerResourceStringsNB = DateRangePickerResourceStringsNB_ as ExpandRequire; diff --git a/projects/igniteui-angular-i18n/src/i18n/NB/grid-resources.ts b/projects/igniteui-angular-i18n/src/i18n/NB/grid-resources.ts new file mode 100644 index 00000000000..ef969195657 --- /dev/null +++ b/projects/igniteui-angular-i18n/src/i18n/NB/grid-resources.ts @@ -0,0 +1,141 @@ +import { IGridResourceStrings } from 'igniteui-angular'; + +// exported below as re-cast to create declaration type with expanded properties +const GridResourceStringsNB_: ExpandRequire = { + igx_grid_groupByArea_message: 'Dra en kolonneoverskrift og slipp den her for å gruppere etter den kolonnen.', + igx_grid_groupByArea_select_message: 'Velg alle radene i gruppen med feltnavn {0} og verdi {1}.', + igx_grid_groupByArea_deselect_message: 'Opphev valg av alle radene i gruppen med feltnavn {0} og verdi {1}.', + igx_grid_emptyFilteredGrid_message: 'Ingen opptak funnet.', + igx_grid_emptyGrid_message: 'Rutenettet har ingen data.', + igx_grid_filter: 'Filter', + igx_grid_filter_row_close: 'Lukk', + igx_grid_filter_row_reset: 'Nullstille', + igx_grid_filter_row_placeholder: 'Legg til filterverdi', + igx_grid_filter_row_boolean_placeholder: 'Alle', + igx_grid_filter_row_date_placeholder: 'Hentedato', + igx_grid_filter_row_time_placeholder: 'Hentetid', + igx_grid_filter_operator_and: 'Og', + igx_grid_filter_operator_or: 'Eller', + igx_grid_complex_filter: 'Kompleks filter', + igx_grid_filter_contains: 'Inneholder', + igx_grid_filter_doesNotContain: 'Inneholder ikke', + igx_grid_filter_startsWith: 'Begynner med', + igx_grid_filter_endsWith: 'Slutter med', + igx_grid_filter_equals: 'Er lik', + igx_grid_filter_doesNotEqual: 'Er ikke lik', + igx_grid_filter_empty: 'Tømme', + igx_grid_filter_notEmpty: 'Ikke tom', + igx_grid_filter_null: 'Null', + igx_grid_filter_notNull: 'Ikke null', + igx_grid_filter_before: 'Før', + igx_grid_filter_after: 'Etter', + igx_grid_filter_at: 'På', + igx_grid_filter_not_at: 'Ikke på', + igx_grid_filter_at_before: 'Kl. eller før', + igx_grid_filter_at_after: 'Kl. eller etter', + igx_grid_filter_today: 'I dag', + igx_grid_filter_yesterday: 'I går', + igx_grid_filter_thisMonth: 'Denne måneden', + igx_grid_filter_lastMonth: 'Forrige måned', + igx_grid_filter_nextMonth: 'Neste måned', + igx_grid_filter_thisYear: 'I år', + igx_grid_filter_lastYear: 'I fjor', + igx_grid_filter_nextYear: 'Neste år', + igx_grid_filter_greaterThan: 'Større enn', + igx_grid_filter_lessThan: 'Mindre enn', + igx_grid_filter_greaterThanOrEqualTo: 'Større enn eller lik', + igx_grid_filter_lessThanOrEqualTo: 'Mindre enn eller lik', + igx_grid_filter_true: 'True', + igx_grid_filter_false: 'False', + igx_grid_filter_all: 'Alle', + igx_grid_filter_condition_placeholder: 'Velg filter', + igx_grid_summary_count: 'Telle', + igx_grid_summary_min: 'Min', + igx_grid_summary_max: 'Maks', + igx_grid_summary_sum: 'Sum', + igx_grid_summary_average: 'Gj.sn', + igx_grid_summary_earliest: 'Tidligst', + igx_grid_summary_latest: 'Siste', + igx_grid_excel_filter_moving_left: 'gå til venstre', + igx_grid_excel_filter_moving_left_short: 'venstre', + igx_grid_excel_filter_moving_right: 'Flytt til høyre', + igx_grid_excel_filter_moving_right_short: 'Ikke sant', + igx_grid_excel_filter_moving_header: 'bevege seg', + igx_grid_excel_filter_sorting_asc: 'stigende', + igx_grid_excel_filter_sorting_asc_short: 'stige', + igx_grid_excel_filter_sorting_desc: 'synkende', + igx_grid_excel_filter_sorting_desc_short: 'synk', + igx_grid_excel_filter_sorting_header: 'sortere', + igx_grid_excel_filter_clear: 'Fjern kolonnefiltre', + igx_grid_excel_custom_dialog_add: 'legg til filter', + igx_grid_excel_custom_dialog_clear: 'Tøm filteret', + igx_grid_excel_custom_dialog_header: 'Egendefinert automatisk filtrering i kolonnen: ', + igx_grid_excel_cancel: 'avbryt', + igx_grid_excel_apply: 'søke om', + igx_grid_excel_search_placeholder: 'Søk', + igx_grid_excel_select_all: 'Velg alle', + igx_grid_excel_select_all_search_results: 'Velg alle søkeresultatene', + igx_grid_excel_add_to_filter: 'Legg til gjeldende valg for å filtrere', + igx_grid_excel_blanks: '(Tomme)', + igx_grid_excel_hide: 'Skjul kolonne', + igx_grid_excel_show: 'Vis kolonne', + igx_grid_excel_pin: 'Fest kolonne', + igx_grid_excel_unpin: 'Løsne kolonnen', + igx_grid_excel_select: 'Velg kolonne', + igx_grid_excel_deselect: 'Opphev valg av kolonne', + igx_grid_excel_text_filter: 'Tekstfilter', + igx_grid_excel_number_filter: 'Nummerfilter', + igx_grid_excel_date_filter: 'Datofilter', + igx_grid_excel_boolean_filter: 'Boolsk filter', + igx_grid_excel_currency_filter: 'Valutafilter', + igx_grid_excel_custom_filter: 'Tilpasset filter...', + igx_grid_advanced_filter_title: 'Avansert filtrering', + igx_grid_advanced_filter_and_group: '"Og"-gruppe', + igx_grid_advanced_filter_or_group: '"Eller"-gruppe', + igx_grid_advanced_filter_end_group: 'Sluttgruppe', + igx_grid_advanced_filter_create_and_group: 'Opprett "Og"-gruppe', + igx_grid_advanced_filter_create_or_group: 'Opprett "Eller"-gruppe', + igx_grid_advanced_filter_and_label: 'og', + igx_grid_advanced_filter_or_label: 'eller', + igx_grid_advanced_filter_add_condition: 'Tilstand', + igx_grid_advanced_filter_ungroup: 'Opphev gruppering', + igx_grid_advanced_filter_delete: 'Slett', + igx_grid_advanced_filter_delete_filters: 'Slett filtre', + igx_grid_advanced_filter_initial_text: 'Start med å opprette en gruppe forhold knyttet til "Og" eller "Eller"', + igx_grid_advanced_filter_column_placeholder: 'Velg kolonne', + igx_grid_advanced_filter_value_placeholder: 'Verdi', + igx_grid_pinned_row_indicator: 'Festet', + igx_grid_hiding_check_all_label: 'Gjem alle', + igx_grid_hiding_uncheck_all_label: 'Vis alt', + igx_grid_pinning_check_all_label: 'Fest alle', + igx_grid_pinning_uncheck_all_label: 'Løsne alle', + igx_grid_row_edit_btn_done: 'Ferdig', + igx_grid_row_edit_btn_cancel: 'Avbryt', + igx_grid_toolbar_actions_filter_prompt: 'Filtrer kolonneliste...', + igx_grid_toolbar_pinning_button_tooltip: 'Åpne rullegardinmenyen for kolonnefester', + igx_grid_toolbar_hiding_button_tooltip: 'Åpne kolonne som skjuler rullegardinmenyen', + igx_grid_toolbar_pinning_title: 'Festede kolonner', + igx_grid_toolbar_hiding_title: 'Synlige kolonner', + igx_grid_toolbar_advanced_filtering_button_tooltip: 'Åpne avansert filtreringsdialogboks', + igx_grid_toolbar_advanced_filtering_button_label: 'Avansert filtrering', + igx_grid_toolbar_exporter_button_tooltip: 'Åpne rullegardinmenyen for eksportør', + igx_grid_toolbar_exporter_button_label: 'Eksporter', + igx_grid_toolbar_exporter_excel_entry_text: 'Eksporter til Excel', + igx_grid_toolbar_exporter_csv_entry_text: 'Eksporter til CSV', + igx_grid_snackbar_addrow_label: 'Rad lagt til', + igx_grid_snackbar_addrow_actiontext: 'FORESTILLING', + igx_grid_actions_edit_label: 'Redigere', + igx_grid_actions_add_label: 'Legge til', + igx_grid_add_row_label: 'LEGG TIL RAD', + igx_grid_actions_add_child_label: 'Legg til barn', + igx_grid_actions_delete_label: 'Slett', + igx_grid_actions_pin_label: 'Fest', + igx_grid_actions_unpin_label: 'Løsne', + igx_grid_actions_jumpUp_label: 'Hoppe opp', + igx_grid_actions_jumpDown_label: 'Hopp ned' +}; + +/** + * Norwegian resource strings for IgxGrid + */ +export const GridResourceStringsNB = GridResourceStringsNB_ as ExpandRequire; diff --git a/projects/igniteui-angular-i18n/src/i18n/NB/list-resources.ts b/projects/igniteui-angular-i18n/src/i18n/NB/list-resources.ts new file mode 100644 index 00000000000..65a2e747e0d --- /dev/null +++ b/projects/igniteui-angular-i18n/src/i18n/NB/list-resources.ts @@ -0,0 +1,12 @@ +import { IListResourceStrings } from 'igniteui-angular'; + +// exported below as re-cast to create declaration type with expanded properties +const ListResourceStringsNB_: ExpandRequire = { + igx_list_no_items: 'Det er ingen elementer på listen.', + igx_list_loading: 'Laster inn data fra serveren...' +}; + +/** + * Norwegian resource strings for IgxList + */ +export const ListResourceStringsNB = ListResourceStringsNB_ as ExpandRequire; diff --git a/projects/igniteui-angular-i18n/src/i18n/NB/paginator-resources.ts b/projects/igniteui-angular-i18n/src/i18n/NB/paginator-resources.ts new file mode 100644 index 00000000000..8b89db6262d --- /dev/null +++ b/projects/igniteui-angular-i18n/src/i18n/NB/paginator-resources.ts @@ -0,0 +1,16 @@ +import { IPaginatorResourceStrings } from 'igniteui-angular'; + +// exported below as re-cast to create declaration type with expanded properties +const PaginatorResourceStringsNB_: ExpandRequire = { + igx_paginator_label: 'Elementer per side', + igx_paginator_pager_text: 'av', + igx_paginator_first_page_button_text: 'Gå til første side', + igx_paginator_previous_page_button_text: 'Forrige side', + igx_paginator_last_page_button_text: 'Gå til siste side', + igx_paginator_next_page_button_text: 'Neste side' +}; + +/** + * Norwegian resource strings for IgxPaginator + */ +export const PaginatorResourceStringsNB = PaginatorResourceStringsNB_ as ExpandRequire; diff --git a/projects/igniteui-angular-i18n/src/i18n/NB/resources.ts b/projects/igniteui-angular-i18n/src/i18n/NB/resources.ts new file mode 100644 index 00000000000..955174c335a --- /dev/null +++ b/projects/igniteui-angular-i18n/src/i18n/NB/resources.ts @@ -0,0 +1,24 @@ +import { GridResourceStringsNB } from './grid-resources'; +import { PaginatorResourceStringsNB } from './paginator-resources'; +import { TimePickerResourceStringsNB } from './time-picker-resources'; +import { DatePickerResourceStringsNB } from './date-picker-resources'; +import { DateRangePickerResourceStringsNB } from './date-range-picker-resources'; +import { CarouselResourceStringsNB } from './carousel-resources'; +import { ListResourceStringsNB } from './list-resources'; +import { CalendarResourceStringsNB } from './calendar-resources'; +import { TreeResourceStringsNB } from './tree-resources'; + +/** + * Norwegian resource strings for all components + */ +export const IgxResourceStringsNB = { + ...GridResourceStringsNB, + ...PaginatorResourceStringsNB, + ...TimePickerResourceStringsNB, + ...DatePickerResourceStringsNB, + ...DateRangePickerResourceStringsNB, + ...CarouselResourceStringsNB, + ...ListResourceStringsNB, + ...CalendarResourceStringsNB, + ...TreeResourceStringsNB +}; diff --git a/projects/igniteui-angular-i18n/src/i18n/NB/time-picker-resources.ts b/projects/igniteui-angular-i18n/src/i18n/NB/time-picker-resources.ts new file mode 100644 index 00000000000..8997e417ac2 --- /dev/null +++ b/projects/igniteui-angular-i18n/src/i18n/NB/time-picker-resources.ts @@ -0,0 +1,14 @@ +import { ITimePickerResourceStrings } from 'igniteui-angular'; + +// exported below as re-cast to create declaration type with expanded properties +const TimePickerResourceStringsNB_: ExpandRequire = { + igx_time_picker_ok: 'OK', + igx_time_picker_cancel: 'Avbryt', + igx_time_picker_change_time: 'Endre tid', + igx_time_picker_choose_time: 'Velg tid' +}; + +/** + * Norwegian resource strings for IgxTimePicker + */ +export const TimePickerResourceStringsNB = TimePickerResourceStringsNB_ as ExpandRequire; diff --git a/projects/igniteui-angular-i18n/src/i18n/NB/tree-resources.ts b/projects/igniteui-angular-i18n/src/i18n/NB/tree-resources.ts new file mode 100644 index 00000000000..468c045b483 --- /dev/null +++ b/projects/igniteui-angular-i18n/src/i18n/NB/tree-resources.ts @@ -0,0 +1,12 @@ +import { ITreeResourceStrings } from 'igniteui-angular'; + +// exported below as re-cast to create declaration type with expanded properties +const TreeResourceStringsNB_: ExpandRequire = { + igx_expand: 'Vis', + igx_collapse: 'Skjul' +}; + +/** + * Norwegian resource strings for IgxTree + */ +export const TreeResourceStringsNB = TreeResourceStringsNB_ as ExpandRequire; diff --git a/projects/igniteui-angular-i18n/src/index.ts b/projects/igniteui-angular-i18n/src/index.ts index f63d91a793f..cb5ecb33a5a 100644 --- a/projects/igniteui-angular-i18n/src/index.ts +++ b/projects/igniteui-angular-i18n/src/index.ts @@ -198,3 +198,14 @@ export * from './i18n/TR/carousel-resources'; export * from './i18n/TR/list-resources'; export * from './i18n/TR/tree-resources'; export * from './i18n/TR/resources'; +// Norwegian (NB) +export * from './i18n/NB/calendar-resources'; +export * from './i18n/NB/grid-resources'; +export * from './i18n/NB/paginator-resources'; +export * from './i18n/NB/time-picker-resources'; +export * from './i18n/NB/date-picker-resources'; +export * from './i18n/NB/date-range-picker-resources'; +export * from './i18n/NB/carousel-resources'; +export * from './i18n/NB/list-resources'; +export * from './i18n/NB/tree-resources'; +export * from './i18n/NB/resources'; diff --git a/projects/igniteui-angular/src/lib/core/styles/components/dialog/_dialog-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/dialog/_dialog-theme.scss index 320d33de67f..edc73c5f7f4 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/dialog/_dialog-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/dialog/_dialog-theme.scss @@ -221,5 +221,9 @@ @include igx-type-style($type-scale, $content) { margin: 0; } + + > * { + letter-spacing: normal; + } } } diff --git a/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.directive.ts b/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.directive.ts index 6b72e1c5d4e..e577d848e0f 100644 --- a/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.directive.ts +++ b/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.directive.ts @@ -1211,10 +1211,18 @@ export class IgxDragDirective implements AfterContentInit, OnDestroy { originalEvent }; - const elementsFromPoint = this.getElementsAtPoint(pageX, pageY); + let elementsFromPoint = this.getElementsAtPoint(pageX, pageY); + + // Check for shadowRoot instance and use it if present + for (const elFromPoint of elementsFromPoint) { + if (elFromPoint?.shadowRoot !== null) { + elementsFromPoint = elFromPoint.shadowRoot.elementsFromPoint(pageX, pageY); + } + } + for (const element of elementsFromPoint) { if (element.getAttribute('droppable') === 'true' && - element !== this.ghostElement && element !== this.element.nativeElement) { + element !== this.ghostElement && element !== this.element.nativeElement) { topDropArea = element; break; } diff --git a/projects/igniteui-angular/src/lib/grids/api.service.ts b/projects/igniteui-angular/src/lib/grids/api.service.ts index 6caf115f56d..452df1cbbab 100644 --- a/projects/igniteui-angular/src/lib/grids/api.service.ts +++ b/projects/igniteui-angular/src/lib/grids/api.service.ts @@ -96,6 +96,21 @@ export class GridBaseAPIService { return this.grid.rowList.find((row) => row.index === rowIndex); } + /** + * Gets the rowID of the record at the specified data view index + * + * @param index + * @param dataCollection + */ + public get_rec_id_by_index(index: number, dataCollection?: any[]): any { + dataCollection = dataCollection || this.grid.data; + if (index >= 0 && index < dataCollection.length) { + const rec = dataCollection[index]; + return this.grid.primaryKey ? rec[this.grid.primaryKey] : rec; + } + return null; + } + public get_cell_by_key(rowSelector: any, field: string): IgxGridCellComponent { const row = this.get_row_by_key(rowSelector); if (row && row.cells) { @@ -393,6 +408,17 @@ export class GridBaseAPIService { return this.grid.primaryKey ? this.getRowData(rowID) : rowID; } + /** + * Returns the index of the record in the data view by pk or -1 if not found or primaryKey is not set. + * + * @param pk + * @param dataCollection + */ + public get_rec_index_by_id(pk: string | number, dataCollection?: any[]): number { + dataCollection = dataCollection || this.grid.data; + return this.grid.primaryKey ? dataCollection.findIndex(rec => rec[this.grid.primaryKey] === pk) : -1; + } + public allow_expansion_state_change(rowID, expanded) { return this.grid.expansionStates.get(rowID) !== expanded; } diff --git a/projects/igniteui-angular/src/lib/grids/common/crud.service.ts b/projects/igniteui-angular/src/lib/grids/common/crud.service.ts index 1f3f9c26430..fb5ce90e063 100644 --- a/projects/igniteui-angular/src/lib/grids/common/crud.service.ts +++ b/projects/igniteui-angular/src/lib/grids/common/crud.service.ts @@ -436,9 +436,8 @@ export class IgxRowAddCrudState extends IgxRowCrudState { * @hidden @internal */ public createAddRowParent(row: IgxRowDirective, newRowAsChild?: boolean) { - const rowIndex = row ? row.index : this.grid.rowList.length - 1; - const rowId = row ? row.rowID : (rowIndex >= 0 ? this.grid.rowList.last.rowID : null); - + const rowIndex = row ? row.index : -1; + const rowId = row ? row.rowID : null; const isInPinnedArea = this.grid.isRecordPinnedByViewIndex(rowIndex); const pinIndex = this.grid.pinnedRecords.findIndex(x => x[this.primaryKey] === rowId); const unpinIndex = this.grid.getUnpinnedIndexById(rowId); @@ -580,6 +579,7 @@ export class IgxGridCRUDService extends IgxRowAddCrudState { this.grid.navigateTo(this.row.index, -1); const dummyRow = this.grid.gridAPI.get_row_by_index(this.row.index); dummyRow.triggerAddAnimation(); + dummyRow.cdr.detectChanges(); dummyRow.addAnimationEnd.pipe(first()).subscribe(() => { const cell = dummyRow.cells.find(c => c.editable); if (cell) { diff --git a/projects/igniteui-angular/src/lib/grids/common/grid-pipes.module.ts b/projects/igniteui-angular/src/lib/grids/common/grid-pipes.module.ts index 0e7f189e9f8..6bbdcadeec4 100644 --- a/projects/igniteui-angular/src/lib/grids/common/grid-pipes.module.ts +++ b/projects/igniteui-angular/src/lib/grids/common/grid-pipes.module.ts @@ -20,6 +20,8 @@ import { IgxSummaryFormatterPipe, IgxGridAddRowPipe, IgxHeaderGroupWidthPipe, + IgxGridRowClassesPipe, + IgxGridRowStylesPipe, IgxHeaderGroupStylePipe } from './pipes'; @@ -44,6 +46,8 @@ import { IgxColumnFormatterPipe, IgxSummaryFormatterPipe, IgxHeaderGroupWidthPipe, + IgxGridRowClassesPipe, + IgxGridRowStylesPipe, IgxHeaderGroupStylePipe ], exports: [ @@ -66,6 +70,8 @@ import { IgxColumnFormatterPipe, IgxSummaryFormatterPipe, IgxHeaderGroupWidthPipe, + IgxGridRowClassesPipe, + IgxGridRowStylesPipe, IgxHeaderGroupStylePipe ], imports: [ diff --git a/projects/igniteui-angular/src/lib/grids/common/pipes.ts b/projects/igniteui-angular/src/lib/grids/common/pipes.ts index 998e863199c..0e4cee9f97b 100644 --- a/projects/igniteui-angular/src/lib/grids/common/pipes.ts +++ b/projects/igniteui-angular/src/lib/grids/common/pipes.ts @@ -7,8 +7,16 @@ import { GridType } from './grid.interface'; import { IgxColumnComponent } from '../columns/column.component'; import { ColumnDisplayOrder } from './enums'; import { IgxColumnActionsComponent } from '../column-actions/column-actions.component'; -import { IgxSummaryOperand, IgxSummaryResult } from '../grid/public_api'; import { IgxAddRow } from './crud.service'; +import { IgxGridRow } from '../grid-public-row'; +import { IgxTreeGridRowComponent } from '../tree-grid/tree-grid-row.component'; +import { IgxGridRowComponent } from '../grid/grid-row.component'; +import { IgxHierarchicalRowComponent } from '../hierarchical-grid/hierarchical-row.component'; +import { IgxSummaryOperand, IgxSummaryResult } from '../summaries/grid-summary'; + +interface CSSProp { + [prop: string]: any; +} /** * @hidden @@ -19,7 +27,7 @@ import { IgxAddRow } from './crud.service'; }) export class IgxGridCellStyleClassesPipe implements PipeTransform { - public transform(cssClasses: { [prop: string]: any }, _: any, data: any, field: string, index: number, __: number): string { + public transform(cssClasses: CSSProp, _: any, data: any, field: string, index: number, __: number): string { if (!cssClasses) { return ''; } @@ -48,8 +56,7 @@ export class IgxGridCellStyleClassesPipe implements PipeTransform { }) export class IgxGridCellStylesPipe implements PipeTransform { - public transform(styles: { [prop: string]: any }, _: any, data: any, field: string, index: number, __: number): - { [prop: string]: any } { + public transform(styles: CSSProp, _: any, data: any, field: string, index: number, __: number): CSSProp { const css = {}; if (!styles) { return css; @@ -64,6 +71,87 @@ export class IgxGridCellStylesPipe implements PipeTransform { } } +type _RowType = IgxGridRowComponent | IgxTreeGridRowComponent | IgxHierarchicalRowComponent; + +/** + * @hidden + * @internal + */ +@Pipe({ name: 'igxGridRowClasses' }) +export class IgxGridRowClassesPipe implements PipeTransform { + public row: IgxGridRow; + + constructor(private gridAPI: GridBaseAPIService) { + this.row = new IgxGridRow(this.gridAPI.grid as any, -1, {}); + } + + public transform( + cssClasses: CSSProp, + row: _RowType, + editMode: boolean, + selected: boolean, + dirty: boolean, + deleted: boolean, + dragging: boolean, + index: number, + mrl: boolean, + filteredOut: boolean, + _: number + ) { + const result = new Set(['igx-grid__tr', index % 2 ? row.grid.evenRowCSS : row.grid.oddRowCSS]); + const mapping = [ + [selected, 'igx-grid__tr--selected'], + [editMode, 'igx-grid__tr--edit'], + [dirty, 'igx-grid__tr--edited'], + [deleted, 'igx-grid__tr--deleted'], + [dragging, 'igx-grid__tr--drag'], + [mrl, 'igx-grid__tr--mrl'], + // Tree grid only + [filteredOut, 'igx-grid__tr--filtered'] + ]; + + for (const [state, _class] of mapping) { + if (state) { + result.add(_class as string); + } + } + + for (const cssClass of Object.keys(cssClasses ?? {})) { + const callbackOrValue = cssClasses[cssClass]; + this.row.index = index; + (this.row as any)._data = row.rowData; + const apply = typeof callbackOrValue === 'function' ? callbackOrValue(this.row) : callbackOrValue; + if (apply) { + result.add(cssClass); + } + } + return result; + } +} + +/** + * @hidden + * @internal + */ +@Pipe({ name: 'igxGridRowStyles' }) +export class IgxGridRowStylesPipe implements PipeTransform { + + constructor(private gridAPI: GridBaseAPIService) { } + + public transform(styles: CSSProp, rowData: any, index: number, __: number): CSSProp { + const css = {}; + if (!styles) { + return css; + } + for (const prop of Object.keys(styles)) { + const cb = styles[prop]; + const row = new IgxGridRow((this.gridAPI.grid as any), index, rowData); + css[prop] = typeof cb === 'function' ? cb(row) : cb; + } + return css; + } +} + /** * @hidden * @internal @@ -341,7 +429,7 @@ export class IgxGridAddRowPipe implements PipeTransform { @Pipe({ name: 'igxHeaderGroupWidth' }) export class IgxHeaderGroupWidthPipe implements PipeTransform { - public transform(width: any, minWidth: any, hasLayout: boolean ) { + public transform(width: any, minWidth: any, hasLayout: boolean) { return hasLayout ? '' : `${Math.max(parseFloat(width), minWidth)}px`; } } diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-clear-filters.component.html b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-clear-filters.component.html index 15729aea30d..daf5c34339d 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-clear-filters.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-clear-filters.component.html @@ -2,7 +2,8 @@ tabindex="0" [ngClass]="clearFilterClass()" (keydown)="onClearFilterKeyDown($event)" - (click)="clearFilter()"> + (click)="clearFilter()" + role="menuitem"> {{ esf.grid.resourceStrings.igx_grid_excel_filter_clear }} clear diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-conditional-filter.component.html b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-conditional-filter.component.html index fd9125e0c44..367febf178b 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-conditional-filter.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-conditional-filter.component.html @@ -3,7 +3,9 @@ class="igx-excel-filter__actions-filter" (keydown)="onTextFilterKeyDown($event)" (click)="onTextFilterClick($event)" - [igxDropDownItemNavigation]="subMenu"> + [igxDropDownItemNavigation]="subMenu" + role="menuitem" + aria-haspopup="true"> {{ subMenuText }} keyboard_arrow_right diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-hiding.component.html b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-hiding.component.html index 0321b6daa08..a2b9f676415 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-hiding.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-hiding.component.html @@ -1,7 +1,8 @@
+ (click)="esf.onHideToggle()" + role="menuitem"> {{ esf.column.hidden ? esf.grid.resourceStrings.igx_grid_excel_show : esf.grid.resourceStrings.igx_grid_excel_hide }} {{ esf.column.hidden ? 'visibility' : 'visibility_off' }}
diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-pinning.component.html b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-pinning.component.html index 20bb7280e9b..7074ecacff6 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-pinning.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-pinning.component.html @@ -1,7 +1,8 @@
+ tabindex="0" + role="menuitem"> {{ esf.column.pinned ? esf.grid.resourceStrings.igx_grid_excel_unpin : esf.grid.resourceStrings.igx_grid_excel_pin }}
diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-selecting.component.html b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-selecting.component.html index ce1438f7783..88f2274c60b 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-selecting.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-selecting.component.html @@ -1,7 +1,9 @@
+ (click)="esf.onSelect()" + role="button" + [attr.aria-pressed]="esf.column.selected"> {{esf.grid.resourceStrings.igx_grid_excel_select }} done
diff --git a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts index 343032b04ae..3b516951edd 100644 --- a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts +++ b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts @@ -343,6 +343,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements * * ``` */ + @DeprecateProperty('`evenRowCSS` is deprecated. We suggest using `rowClasses` property instead.') @Input() public evenRowCSS = 'igx-grid__tr--even'; @@ -354,9 +355,47 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements * * ``` */ + @DeprecateProperty('`oddRowCSS` is deprecated. We suggest using `rowClasses` property instead.') @Input() public oddRowCSS = 'igx-grid__tr--odd'; + /** + * Sets a conditional class selector to the grid's row element. + * Accepts an object literal, containing key-value pairs, + * where the key is the name of the CSS class and the value is + * either a callback function that returns a boolean, or boolean, like so: + * ```typescript + * callback = (row: RowType) => { return row.selected > 6; } + * rowClasses = { 'className' : this.callback }; + * ``` + * ```html + * + * ``` + * + * @memberof IgxColumnComponent + */ + @Input() + public rowClasses: any; + + /** + * Sets conditional style properties on the grid row element. + * It accepts an object literal where the keys are + * the style properties and the value is an expression to be evaluated. + * ```typescript + * styles = { + * background: 'yellow', + * color: (row: RowType) => row.selected : 'red': 'white' + * } + * ``` + * ```html + * + * ``` + * + * @memberof IgxColumnComponent + */ + @Input() + public rowStyles = null; + /** * Gets/Sets the primary key. * @@ -5966,6 +6005,92 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements this.crudService.endEdit(commit, event); } + /** + * Enters add mode by spawning the UI under the specified row by rowID. + * + * @remarks + * If null is passed as rowID, the row adding UI is spawned as the first record in the data view + * @remarks + * Spawning the UI to add a child for a record only works if you provide a rowID + * @example + * ```typescript + * this.grid.beginAddRowById('ALFKI'); + * this.grid.beginAddRowById('ALFKI', true); + * this.grid.beginAddRowById(null); + * ``` + * @param rowID - The rowID to spawn the add row UI for, or null to spawn it as the first record in the data view + * @param asChild - Whether the record should be added as a child. Only applicable to igxTreeGrid. + */ + public beginAddRowById(rowID: any, asChild?: boolean): void { + let index = rowID; + if (rowID == null) { + if (asChild) { + console.warn('The record cannot be added as a child to an unspecified record.'); + return; + } + index = 0; + } else { + // find the index of the record with that PK + index = this.gridAPI.get_rec_index_by_id(rowID, this.dataView); + rowID = index; + if (index === -1) { + console.warn('No row with the specified ID was found.'); + return; + } + } + if (!this.dataView.length) { + this.beginAddRowForIndex(rowID, asChild); + return; + } + // check if the index is valid - won't support anything outside the data view + if (index >= 0 && index < this.dataView.length) { + // check if the index is in the view port + if ((index < this.virtualizationState.startIndex || + index >= this.virtualizationState.startIndex + this.virtualizationState.chunkSize) && + !this.isRecordPinnedByViewIndex(index)) { + this.verticalScrollContainer.chunkLoad + .pipe(first(), takeUntil(this.destroy$)) + .subscribe(() => { + this.beginAddRowForIndex(rowID, asChild); + }); + this.navigateTo(index); + this.notifyChanges(true); + return; + } + this.beginAddRowForIndex(rowID, asChild); + } else { + console.warn('The row with the specified PK or index is outside of the current data view.'); + } + } + + /** + * Enters add mode by spawning the UI at the specified index. + * + * @remarks + * Accepted values for index are integers from 0 to this.grid.dataView.length + * @example + * ```typescript + * this.grid.beginAddRowByIndex(0); + * ``` + * @param index - The index to spawn the UI at. Accepts integers from 0 to this.grid.dataView.length + */ + public beginAddRowByIndex(index: number): void { + if (index === 0) { + return this.beginAddRowById(null); + } + return this.beginAddRowById(this.gridAPI.get_rec_id_by_index(index - 1, this.dataView)); + } + + protected beginAddRowForIndex(index: number, asChild: boolean = false) { + const row: IgxRowDirective = index == null ? + null : this.rowList.find(r => r.index === index); + if (row !== undefined) { + this.crudService.enterAddRowMode(row, asChild); + } else { + console.warn('No row with the specified PK or index was found.'); + } + } + protected switchTransactionService(val: boolean) { if (val) { this._transactions = this.transactionFactory.create(TRANSACTION_TYPE.Base); diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-add-row.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-add-row.spec.ts index 0607e79880c..b66d83ad032 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-add-row.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-add-row.spec.ts @@ -1,6 +1,6 @@ import { IgxGridModule, IgxGridComponent } from './public_api'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { TestBed, fakeAsync } from '@angular/core/testing'; +import { TestBed, fakeAsync, tick } from '@angular/core/testing'; import { configureTestSuite } from '../../test-utils/configure-suite'; import { DebugElement } from '@angular/core'; import { GridFunctions, GridSummaryFunctions } from '../../test-utils/grid-functions.spec'; @@ -22,6 +22,8 @@ import { IgxGridRowComponent } from './grid-row.component'; import { takeUntil, first } from 'rxjs/operators'; import { Subject } from 'rxjs'; +const DEBOUNCETIME = 30; + describe('IgxGrid - Row Adding #grid', () => { const GRID_ROW = 'igx-grid-row'; const DISPLAY_CONTAINER = 'igx-display-container'; @@ -479,6 +481,35 @@ describe('IgxGrid - Row Adding #grid', () => { expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBeTrue(); }); + + it('Should scroll and start adding a row as the first one when using the public API method', async () => { + await wait(DEBOUNCETIME); + fixture.detectChanges(); + + grid.navigateTo(20, 0); + + await wait(DEBOUNCETIME); + fixture.detectChanges(); + + grid.beginAddRowById(null); + + await wait(DEBOUNCETIME); + fixture.detectChanges(); + + expect(grid.gridAPI.get_row_by_index(0).addRowUI).toBeTrue(); + }); + + xit('Should scroll and start adding a row as for a row that is not in view', async () => { + await wait(DEBOUNCETIME); + fixture.detectChanges(); + + grid.beginAddRowById('FAMIA'); + + await wait(DEBOUNCETIME); + fixture.detectChanges(); + + expect(grid.gridAPI.get_row_by_index(8).addRowUI).toBeTrue(); + }); }); describe('Exit add row mode tests', () => { diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-row-pinning.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-row-pinning.spec.ts index 534a8066853..248514873bd 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-row-pinning.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-row-pinning.spec.ts @@ -10,13 +10,12 @@ import { IPinningConfig } from '../grid.common'; import { SampleTestData } from '../../test-utils/sample-test-data.spec'; import { GridFunctions } from '../../test-utils/grid-functions.spec'; import { SortingDirection } from '../../data-operations/sorting-expression.interface'; -import { IgxGridTransaction } from '../tree-grid/public_api'; -import { IgxTransactionService } from '../../services/public_api'; import { GridSummaryFunctions } from '../../test-utils/grid-functions.spec'; import { IgxStringFilteringOperand } from '../../data-operations/filtering-condition'; import { IgxPaginatorComponent } from '../../paginator/paginator.component'; import { wait, UIInteractions } from '../../test-utils/ui-interactions.spec'; import { setupGridScrollDetection } from '../../test-utils/helper-utils.spec'; +import { GridRowConditionalStylingComponent } from '../../test-utils/grid-base-components.spec'; describe('Row Pinning #grid', () => { const FIXED_ROW_CONTAINER = '.igx-grid__tr--pinned '; @@ -33,7 +32,8 @@ describe('Row Pinning #grid', () => { GridRowPinningWithMRLComponent, GridRowPinningWithMDVComponent, GridRowPinningWithTransactionsComponent, - GridRowPinningWithInitialPinningComponent + GridRowPinningWithInitialPinningComponent, + GridRowConditionalStylingComponent ], imports: [ NoopAnimationsModule, @@ -1265,6 +1265,50 @@ describe('Row Pinning #grid', () => { expect(grid.hasPinnedRecords).toBeTrue(); }); }); + + describe('Conditional row styling', () => { + + beforeEach(fakeAsync(() => { + fix = TestBed.createComponent(GridRowConditionalStylingComponent); + fix.detectChanges(); + grid = fix.componentInstance.grid; + tick(); + fix.detectChanges(); + })); + + it('Shoud be able to conditionally style rows. Check is the class present in the row native element class list', () => { + fix.detectChanges(); + const firstRow = grid.gridAPI.get_row_by_index(0); + const fourthRow = grid.gridAPI.get_row_by_index(3); + + expect(firstRow).toBeDefined(); + expect(firstRow.element.nativeElement.classList.contains('eventRow')).toBeTrue(); + expect(firstRow.element.nativeElement.classList.contains('oddRow')).toBeFalse(); + expect(fourthRow.element.nativeElement.classList.contains('eventRow')).toBeFalse(); + expect(fourthRow.element.nativeElement.classList.contains('oddRow')).toBeTrue(); + }); + + it('Should apply custom CSS bindings to the grid cells/rows. Check the style attribute to match each binding', () => { + const evenColStyles = { + background: (row) => row.index % 2 === 0 ? 'gray' : 'white', + animation: '0.75s popin' + }; + + fix.detectChanges(); + grid.rowStyles = evenColStyles; + grid.notifyChanges(true); + fix.detectChanges(); + const firstRow = grid.gridAPI.get_row_by_index(0); + const fourthRow = grid.gridAPI.get_row_by_index(3); + + const expectedEvenStyles = 'background: gray; animation: 0.75s ease 0s 1 normal none running popin;'; + const expectedOddStyles = 'background: white; animation: 0.75s ease 0s 1 normal none running popin;'; + + expect(firstRow.element.nativeElement.style.cssText).toEqual(expectedEvenStyles); + expect(fourthRow.element.nativeElement.style.cssText).toEqual(expectedOddStyles); + }); + + }); }); @Component({ diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-row.component.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-row.component.ts index de3dc2a6689..8e2f592c0b7 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-row.component.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-row.component.ts @@ -1,4 +1,4 @@ -import { Component, forwardRef, ChangeDetectionStrategy, HostBinding } from '@angular/core'; +import { Component, forwardRef, ChangeDetectionStrategy } from '@angular/core'; import { IgxGridComponent } from './grid.component'; import { IgxRowDirective } from '../row.directive'; @@ -10,11 +10,6 @@ import { IgxRowDirective } from '../row.directive'; }) export class IgxGridRowComponent extends IgxRowDirective { - @HostBinding('class.igx-grid__tr--mrl') - public get hasColumnLayouts(): boolean { - return this.grid.hasColumnLayouts; - } - public getContext(col, row) { return { $implicit: col, diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.component.html b/projects/igniteui-angular/src/lib/grids/grid/grid.component.html index 316f948f582..fcc9b789609 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.component.html +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.component.html @@ -93,11 +93,15 @@ - + - + diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.html b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.html index 79169693fab..4a701566e31 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.html +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.html @@ -67,12 +67,16 @@ - + - + diff --git a/projects/igniteui-angular/src/lib/grids/row.directive.ts b/projects/igniteui-angular/src/lib/grids/row.directive.ts index 06df8fd35ae..b9d7d50491e 100644 --- a/projects/igniteui-angular/src/lib/grids/row.directive.ts +++ b/projects/igniteui-angular/src/lib/grids/row.directive.ts @@ -211,14 +211,6 @@ export class IgxRowDirective implemen return this.index; } - /** - * @hidden - */ - @HostBinding('class') - get styleClasses(): string { - return this.resolveClasses(); - } - /** * @hidden */ @@ -583,21 +575,6 @@ export class IgxRowDirective implemen this.addAnimationEnd.emit(this); } - /** - * @hidden - */ - protected resolveClasses(): string { - const indexClass = this.index % 2 ? this.grid.evenRowCSS : this.grid.oddRowCSS; - const selectedClass = this.selected ? 'igx-grid__tr--selected' : ''; - const editClass = this.inEditMode ? 'igx-grid__tr--edit' : ''; - const dirtyClass = this.dirty ? 'igx-grid__tr--edited' : ''; - const deletedClass = this.deleted ? 'igx-grid__tr--deleted' : ''; - const mrlClass = this.grid.hasColumnLayouts ? 'igx-grid__tr--mrl' : ''; - const dragClass = this.dragging ? 'igx-grid__tr--drag' : ''; - return `${this.defaultCssClass} ${indexClass} ${selectedClass} ${editClass} ${dirtyClass} - ${deletedClass} ${mrlClass} ${dragClass}`.trim(); - } - /** * @hidden */ diff --git a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-api.service.ts b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-api.service.ts index df3ba497ed5..92d45d10a51 100644 --- a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-api.service.ts +++ b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-api.service.ts @@ -169,6 +169,32 @@ export class IgxTreeGridAPIService extends GridBaseAPIService= 0 && index < dataCollection.length) { + const rec = dataCollection[index]; + return this.grid.primaryKey ? rec.data[this.grid.primaryKey] : rec.data; + } + return null; + } + + /** + * Returns the index of the record in the data view by pk or -1 if not found or primaryKey is not set. + * + * @param pk + * @param dataCollection + */ + public get_rec_index_by_id(pk: string | number, dataCollection?: any[]): number { + dataCollection = dataCollection || this.grid.data; + return this.grid.primaryKey ? dataCollection.findIndex(rec => rec.data[this.grid.primaryKey] === pk) : -1; + } + public addRowToData(data: any, parentRowID?: any) { if (parentRowID !== undefined && parentRowID !== null) { diff --git a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-row.component.ts b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-row.component.ts index aeff4edbc16..a150bcd45d9 100644 --- a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-row.component.ts +++ b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-row.component.ts @@ -159,13 +159,4 @@ export class IgxTreeGridRowComponent extends IgxRowDirective - + - + diff --git a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.ts b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.ts index efc47f3611b..c452f399732 100644 --- a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.ts +++ b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.ts @@ -605,6 +605,32 @@ export class IgxTreeGridComponent extends IgxGridBaseDirective implements GridTy this.notifyChanges(); } + /** + * Enters add mode by spawning the UI with the context of the specified row by index. + * + * @remarks + * Accepted values for index are integers from 0 to this.grid.dataView.length + * @remarks + * When adding the row as a child, the parent row is the specified row. + * @remarks + * To spawn the UI on top, call the function with index = null or a negative number. + * In this case trying to add this row as a child will result in error. + * @example + * ```typescript + * this.grid.beginAddRowByIndex(10); + * this.grid.beginAddRowByIndex(10, true); + * this.grid.beginAddRowByIndex(null); + * ``` + * @param index - The index to spawn the UI at. Accepts integers from 0 to this.grid.dataView.length + * @param asChild - Whether the record should be added as a child. Only applicable to igxTreeGrid. + */ + public beginAddRowByIndex(index: number, asChild?: boolean): void { + if (index === null || index < 0) { + return this.beginAddRowById(null, asChild); + } + return this.beginAddRowById(this.gridAPI.get_rec_id_by_index(index, this.dataView), asChild); + } + /** * @hidden */ diff --git a/projects/igniteui-angular/src/lib/test-utils/grid-base-components.spec.ts b/projects/igniteui-angular/src/lib/test-utils/grid-base-components.spec.ts index e9b68fca1c7..c3d6a200e0e 100644 --- a/projects/igniteui-angular/src/lib/test-utils/grid-base-components.spec.ts +++ b/projects/igniteui-angular/src/lib/test-utils/grid-base-components.spec.ts @@ -118,6 +118,22 @@ export class GridWithToolbarComponent extends GridWithSizeComponent { public data = SampleTestData.contactInfoData(); } +@Component({ + template: GridTemplateStrings.declareGrid(` [autoGenerate]="true" [rowClasses]="rowClasses"`, + '', '') +}) +export class GridRowConditionalStylingComponent extends GridWithSizeComponent { + + public data = SampleTestData.contactInfoData(); + public evenRowCondition = (row) => row.index % 2 === 0; + public oddRowCondition = (row) => row.index % 2 !== 0; + + // eslint-disable-next-line @typescript-eslint/member-ordering + public rowClasses = { + eventRow: this.evenRowCondition, + oddRow: this.oddRowCondition + }; +} @Component({ template: `
diff --git a/src/app/gird-cell-styling/grid-cell-styling.sample.html b/src/app/gird-cell-styling/grid-cell-styling.sample.html index b7431557c0f..68ea50b0308 100644 --- a/src/app/gird-cell-styling/grid-cell-styling.sample.html +++ b/src/app/gird-cell-styling/grid-cell-styling.sample.html @@ -31,6 +31,35 @@ > +

Grid sample with rowClasses property applied based on row ID

+ + + + + + + + row.cells.some(s => s.active); + + // eslint-disable-next-line @typescript-eslint/member-ordering + public rowClasses = { + pinnedClass: this.rowCondition, + selected: this.selectedRowCondition + }; + public condition(rowData: any): boolean { return rowData[this.grid1.primaryKey] === 'BLONP'; } @@ -57,6 +67,10 @@ export class GridCellStylingSampleComponent implements OnInit { return rowData[columnKey] > 6; } + public rowCondition(row: RowType) { + return row.pinned; + } + public ngOnInit(): void { this.columns = [ { field: 'ID' }, diff --git a/src/app/grid-add-row/grid-add-row.sample.html b/src/app/grid-add-row/grid-add-row.sample.html index 426b8e9a441..3433f7a8fe9 100644 --- a/src/app/grid-add-row/grid-add-row.sample.html +++ b/src/app/grid-add-row/grid-add-row.sample.html @@ -43,6 +43,17 @@

Settings

{{value}} + + + + + + + + + + +
diff --git a/src/app/grid-add-row/grid-add-row.sample.ts b/src/app/grid-add-row/grid-add-row.sample.ts index 8ad9c580d4c..6edce1304be 100644 --- a/src/app/grid-add-row/grid-add-row.sample.ts +++ b/src/app/grid-add-row/grid-add-row.sample.ts @@ -1,4 +1,5 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, ViewChild } from '@angular/core'; +import { IgxGridComponent } from 'igniteui-angular'; @Component({ selector: 'app-grid-add-row', @@ -6,6 +7,10 @@ import { Component, OnInit } from '@angular/core'; templateUrl: `grid-add-row.sample.html` }) export class GridAddRowSampleComponent implements OnInit { + + @ViewChild(IgxGridComponent) + public grid: IgxGridComponent; + public data: any[]; public dataFull: any[]; public columns: any[]; @@ -69,4 +74,17 @@ export class GridAddRowSampleComponent implements OnInit { this.data = []; /* eslint-enable max-len */ } + + public beginAddRowAtIndex(index: string) { + const numeric = parseInt(index, 10); + this.grid.beginAddRowByIndex(numeric); + } + + public beginAddRowStart() { + this.grid.beginAddRowById(null); + } + + public beginAddRowById(string: string) { + this.grid.beginAddRowById(string); + } } diff --git a/src/app/tree-grid-add-row/tree-grid-add-row.sample.html b/src/app/tree-grid-add-row/tree-grid-add-row.sample.html index 169b8fca1df..d538c964ab4 100644 --- a/src/app/tree-grid-add-row/tree-grid-add-row.sample.html +++ b/src/app/tree-grid-add-row/tree-grid-add-row.sample.html @@ -1,14 +1,33 @@
- - - - - - - - -
+ + + + + + + + + +
+
+ +
+
+ + + + + +
+
+ + + + + +
+
\ No newline at end of file diff --git a/src/app/tree-grid-add-row/tree-grid-add-row.sample.scss b/src/app/tree-grid-add-row/tree-grid-add-row.sample.scss new file mode 100644 index 00000000000..1b78b63822b --- /dev/null +++ b/src/app/tree-grid-add-row/tree-grid-add-row.sample.scss @@ -0,0 +1,16 @@ +.three-columns { + display: flex; + width: 900px; +} + +.column { + flex-grow: 1; + height: 150px; + display: flex; + flex-direction: column; + justify-content: space-around; +} + +.column + .column { + margin-left: 2%; +} \ No newline at end of file diff --git a/src/app/tree-grid-add-row/tree-grid-add-row.sample.ts b/src/app/tree-grid-add-row/tree-grid-add-row.sample.ts index d3962ab5ebc..b9eccf09a1e 100644 --- a/src/app/tree-grid-add-row/tree-grid-add-row.sample.ts +++ b/src/app/tree-grid-add-row/tree-grid-add-row.sample.ts @@ -1,11 +1,15 @@ -import { Component, OnInit } from '@angular/core'; -import { ColumnPinningPosition, RowPinningPosition } from 'igniteui-angular'; +import { Component, OnInit, ViewChild } from '@angular/core'; +import { ColumnPinningPosition, IgxTreeGridComponent, RowPinningPosition } from 'igniteui-angular'; @Component({ selector: 'app-tree-grid-add-row', + styleUrls: ['tree-grid-add-row.sample.scss'], templateUrl: `tree-grid-add-row.sample.html` }) export class TreeGridAddRowSampleComponent implements OnInit { + @ViewChild(IgxTreeGridComponent) + public grid: IgxTreeGridComponent; + public result: string; public data: any[]; @@ -41,8 +45,10 @@ export class TreeGridAddRowSampleComponent implements OnInit { { Salary: 2500, employeeID: 3, PID: -1, firstName: 'Steven', lastName: 'Buchanan', Title: 'CTO' }, // sub of ID 0 { Salary: 2500, employeeID: 4, PID: 0, firstName: 'Janet', lastName: 'Leverling', Title: 'Sales Manager' }, - { Salary: 3500, employeeID: 5, PID: 0, firstName: 'Laura', lastName: 'Callahan', - Title: 'Inside Sales Coordinator' }, + { + Salary: 3500, employeeID: 5, PID: 0, firstName: 'Laura', lastName: 'Callahan', + Title: 'Inside Sales Coordinator' + }, { Salary: 1500, employeeID: 6, PID: 0, firstName: 'Margaret', lastName: 'Peacock', Title: 'Sales Representative' }, { Salary: 2500, employeeID: 7, PID: 0, firstName: 'Michael', lastName: 'Suyama', Title: 'Sales Representative' }, // sub of ID 4 @@ -61,14 +67,33 @@ export class TreeGridAddRowSampleComponent implements OnInit { { Salary: 3500, employeeID: 17, PID: 15, firstName: 'Armand', lastName: 'Ross', Title: 'Product Owner' }, { Salary: 1500, employeeID: 18, PID: 15, firstName: 'Dane', lastName: 'Rodriquez', Title: 'Team Leader' }, // sub of ID 19 - { Salary: 2500, employeeID: 19, PID: 18, firstName: 'Declan', lastName: 'Lester', - Title: 'Senior Software Developer' }, - { Salary: 3500, employeeID: 20, PID: 18, firstName: 'Bernard', lastName: 'Jarvis', - Title: 'Senior Software Developer' }, + { + Salary: 2500, employeeID: 19, PID: 18, firstName: 'Declan', lastName: 'Lester', + Title: 'Senior Software Developer' + }, + { + Salary: 3500, employeeID: 20, PID: 18, firstName: 'Bernard', lastName: 'Jarvis', + Title: 'Senior Software Developer' + }, { Salary: 1500, employeeID: 21, PID: 18, firstName: 'Jason', lastName: 'Clark', Title: 'QA' }, { Salary: 1500, employeeID: 22, PID: 18, firstName: 'Mark', lastName: 'Young', Title: 'QA' }, // sub of ID 20 { Salary: 1500, employeeID: 23, PID: 20, firstName: 'Jeremy', lastName: 'Donaldson', Title: 'Software Developer' } ]; } + + + public beginAddRowAtIndex(index: string) { + const numeric = parseInt(index, 10); + this.grid.beginAddRowByIndex(numeric); + } + + public beginAddRowStart() { + this.grid.beginAddRowById(null); + } + + public beginAddRowById(string: string) { + const numeric = parseInt(string, 10); + this.grid.beginAddRowById(numeric); + } }