diff --git a/.vscode/settings.json b/.vscode/settings.json index 2097d67919d..fbf56ae5502 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,9 @@ { "git.ignoreLimitWarning": true, "javascript.preferences.quoteStyle": "single", - "typescript.preferences.quoteStyle": "single" + "typescript.preferences.quoteStyle": "single", + "cSpell.words": [ + "ghostclass", + "ungroup" + ] } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b02a8488ae..cafd6fa1621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,42 @@ All notable changes for each version of this project will be documented in this - Introduced a new `expanded` input property, enabling dynamic control over the banner's state. The banner can now be programmatically set to expanded (visible) or collapsed (hidden) both initially and at runtime. Animations will trigger during runtime updates — the **open animation** plays when `expanded` is set to `true`, and the **close animation** plays when set to `false`. However, no animations will trigger when the property is set initially. - The banner's event lifecycle (`opening`, `opened`, `closing`, `closed`) only triggers through **user interactions** (e.g., clicking to open/close). Programmatic updates using the `expanded` property will not fire any events. - If the `expanded` property changes during an ongoing animation, the current animation will **stop** and the opposite animation will begin from the **point where the previous animation left off**. For instance, if the open animation (10 seconds) is interrupted at 6 seconds and `expanded` is set to `false`, the close animation (5 seconds) will start from its 3rd second. +- `IgxQueryBuilder` has new design that comes with updated appearance and new functionality + - `IgxQueryBuilderComponent` + - Introduced the ability to create nested queries by specifying IN/NOT IN operators. + - Introduced the ability to reposition condition chips by dragging or using `Arrow Up/Down`. + - Added the `entities` property that accepts an array of `EntityType` objects describing an entity with its name and an array of fields. The `fields` input property has been deprecated and will be removed in a future version. Automatic migrations are available and will be applied on `ng update`. + - Added `disableEntityChange` property that can be used to disable the entity select on root level after the initial selection. Defaults to `false`. + - Added `disableReturnFieldsChange` property that can be used to disable the fields combo on root level. Defaults to `false`. + - Added the `canCommit`, `commit` and `discard` public methods that allows the user to save/discard the current state of the expression tree. + - Added option to template the search value input: + ``` + + @if (selectedField?.field === 'Id' && selectedCondition === 'equals'){ + + } @else { + + } + + ``` + - **Behavioral Changes** + - Expression enters edit mode on single click, `Enter` or `Space`. + - Selecting conditions inside the `IgxQueryBuilderComponent` is no longer supported. Grouping/ungrouping expressions is now achieved via the newly exposed Drag & Drop functionality. + - Deleting multiple expressions through the context menu is no longer supported. + - `IgxQueryBuilderHeaderComponent` + - **Behavioral Change** + - Legend is no longer shown. + - If the `title` input property is not set, by default it would be empty string. + - **Deprecation** + - The `showLegend` and `resourceStrings` input properties have been deprecated and will be removed in a future version. Automatic migrations are available and will be applied on `ng update`. +- `IFilteringExpression` + - A new optional property called `conditionName` has been introduced. This would generally be equal to the existing `condition.name`. +- `IFilteringOperation` + - A new optional property called `isNestedQuery` has been introduced. It's used to indicate whether the condition leads to a nested query creation. ## 19.0.0 ### General diff --git a/package-lock.json b/package-lock.json index 158e800c4cf..4b3ad44fd3e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,23 +9,23 @@ "version": "0.0.0", "hasInstallScript": true, "dependencies": { - "@angular/animations": "^19.1.2", - "@angular/common": "^19.1.2", - "@angular/compiler": "^19.1.2", - "@angular/core": "^19.1.2", - "@angular/elements": "^19.1.2", - "@angular/forms": "^19.1.2", - "@angular/platform-browser": "^19.1.2", - "@angular/platform-browser-dynamic": "^19.1.2", - "@angular/platform-server": "^19.1.2", - "@angular/router": "^19.1.2", - "@angular/ssr": "^19.1.3", + "@angular/animations": "^19.1.6", + "@angular/common": "^19.1.6", + "@angular/compiler": "^19.1.6", + "@angular/core": "^19.1.6", + "@angular/elements": "^19.1.6", + "@angular/forms": "^19.1.6", + "@angular/platform-browser": "^19.1.6", + "@angular/platform-browser-dynamic": "^19.1.6", + "@angular/platform-server": "^19.1.6", + "@angular/router": "^19.1.6", + "@angular/ssr": "^19.1.7", "@igniteui/material-icons-extended": "^3.1.0", "@lit-labs/ssr-dom-shim": "^1.2.1", "@types/source-map": "0.5.2", "express": "^4.21.1", "fflate": "^0.8.1", - "igniteui-theming": "^14.3.1", + "igniteui-theming": "^15.0.0", "igniteui-trial-watermark": "^3.0.2", "lodash-es": "^4.17.21", "rxjs": "^7.8.0", @@ -33,22 +33,22 @@ "zone.js": "~0.15.0" }, "devDependencies": { - "@angular-devkit/build-angular": "^19.1.3", - "@angular-devkit/schematics": "^19.1.3", - "@angular-eslint/builder": "^19.0.2", - "@angular-eslint/eslint-plugin": "^19.0.2", - "@angular-eslint/eslint-plugin-template": "^19.0.2", - "@angular-eslint/schematics": "^19.0.2", - "@angular-eslint/template-parser": "^19.0.2", - "@angular/cli": "^19.1.3", - "@angular/compiler-cli": "^19.1.2", - "@angular/language-service": "^19.1.2", + "@angular-devkit/build-angular": "^19.1.7", + "@angular-devkit/schematics": "^19.1.7", + "@angular-eslint/builder": "^19.1.0", + "@angular-eslint/eslint-plugin": "^19.1.0", + "@angular-eslint/eslint-plugin-template": "^19.1.0", + "@angular-eslint/schematics": "^19.1.0", + "@angular-eslint/template-parser": "^19.1.0", + "@angular/cli": "^19.1.7", + "@angular/compiler-cli": "^19.1.6", + "@angular/language-service": "^19.1.6", "@angularclass/hmr": "^3.0.0", "@microsoft/signalr": "^7.0.12", "@types/estree": "^1.0.0", "@types/express": "^5.0.0", "@types/hammerjs": "^2.0.46", - "@types/jasmine": "^5.1.1", + "@types/jasmine": "^5.1.6", "@types/jasminewd2": "^2.0.10", "@types/node": "^20.17.6", "@types/sass-true": "^6.0.2", @@ -69,11 +69,11 @@ "hammer-simulator": "0.0.1", "hammerjs": "^2.0.8", "ig-typedoc-theme": "^6.0.0", - "igniteui-dockmanager": "^1.15.2", + "igniteui-dockmanager": "^1.16.0", "igniteui-sassdoc-theme": "^1.2.3", "igniteui-webcomponents": "5.2.0", - "jasmine": "^5.5.0", - "jasmine-core": "~5.5.0", + "jasmine": "^5.6.0", + "jasmine-core": "^5.6.0", "karma": "^6.4.4", "karma-chrome-launcher": "~3.2.0", "karma-coverage": "^2.0.3", @@ -82,11 +82,11 @@ "karma-parallel": "^0.3.1", "karma-spec-reporter": "^0.0.36", "lit-html": "^3.2.1", - "ng-packagr": "^19.1.0", + "ng-packagr": "^19.1.2", "postcss": "^8.5.1", "postcss-scss": "^4.0.6", "prettier": "^3.3.3", - "puppeteer": "^23.11.1", + "puppeteer": "^24.2.1", "sass-embedded": "^1.83.4", "sass-true": "^8.1.0", "sassdoc": "^2.7.4", @@ -122,13 +122,13 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1901.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1901.3.tgz", - "integrity": "sha512-bXhcSP23MKGRuKjI0j+JEDssuFwyprVS0czIeNswj2VTuWyx9y8GjnH2kJXeDETbX0pNbUjThkMsk8cZ5b2YTg==", + "version": "0.1901.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1901.7.tgz", + "integrity": "sha512-qltyebfbej7joIKZVH8EFfrVDrkw0p9N9ja3A0XeU1sl2vlepHNAQdVm0Os8Vy2XjjyHvT5bXWE3G3/221qEKw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.1.3", + "@angular-devkit/core": "19.1.7", "rxjs": "7.8.1" }, "engines": { @@ -138,17 +138,17 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-19.1.3.tgz", - "integrity": "sha512-k9ZLXmtWFDxj/RN4RPKJ+tKDz1rUds7TZeqTvtfvOobgNzT5gSj0ZGlAlnMxcW3HJF7MuCTnAYua51tlJ5aTXw==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-19.1.7.tgz", + "integrity": "sha512-CMl3D5cpXoY0WuvdYtuOU2TetCwqxNsYM2jpuGG/kuuTEASAOI1cs9OhGwny1A/63bB8eyL33eLe82ON2Oemow==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1901.3", - "@angular-devkit/build-webpack": "0.1901.3", - "@angular-devkit/core": "19.1.3", - "@angular/build": "19.1.3", + "@angular-devkit/architect": "0.1901.7", + "@angular-devkit/build-webpack": "0.1901.7", + "@angular-devkit/core": "19.1.7", + "@angular/build": "19.1.7", "@babel/core": "7.26.0", "@babel/generator": "7.26.3", "@babel/helper-annotate-as-pure": "7.25.9", @@ -159,7 +159,7 @@ "@babel/preset-env": "7.26.0", "@babel/runtime": "7.26.0", "@discoveryjs/json-ext": "0.6.3", - "@ngtools/webpack": "19.1.3", + "@ngtools/webpack": "19.1.7", "@vitejs/plugin-basic-ssl": "1.2.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.20", @@ -213,7 +213,7 @@ "@angular/localize": "^19.0.0", "@angular/platform-server": "^19.0.0", "@angular/service-worker": "^19.0.0", - "@angular/ssr": "^19.1.3", + "@angular/ssr": "^19.1.7", "@web/test-runner": "^0.19.0", "browser-sync": "^3.0.2", "jest": "^29.5.0", @@ -221,7 +221,7 @@ "karma": "^6.3.0", "ng-packagr": "^19.0.0", "protractor": "^7.0.0", - "tailwindcss": "^2.0.0 || ^3.0.0", + "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", "typescript": ">=5.5 <5.8" }, "peerDependenciesMeta": { @@ -293,13 +293,13 @@ } }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1901.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1901.3.tgz", - "integrity": "sha512-sv5rL1/xdMuPxJskG+5FVyVpDH8/NMfvHn/bKUvdrYMcTowwepP5EVQ5MZDSfwWrksuCyqrIOxd0K2zIRohNSQ==", + "version": "0.1901.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1901.7.tgz", + "integrity": "sha512-g7xPN7unBnqP9HsgFvEV1DIhNYmVwmWR9ZiSP0xJq+EjpjWlz2vmgru4a5WKwGeuLsP8vg7RKV0kCH3bunOmFA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1901.3", + "@angular-devkit/architect": "0.1901.7", "rxjs": "7.8.1" }, "engines": { @@ -313,9 +313,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.3.tgz", - "integrity": "sha512-of/TKfJ/vL+/qvr4PbDTtqbFJGFHPfu6bEJrIZsLMYA+Mej8SyTx3kDm4LLnKQBtWVYDqkrxvcpOb4+NmHNLfA==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.7.tgz", + "integrity": "sha512-q0I6L9KTqyQ7D5M8H+fWLT+yjapvMNb7SRdfU6GzmexO66Dpo83q4HDzuDKIPDF29Yl0ELs9ICJqe9yUXh6yDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -341,13 +341,13 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.1.3.tgz", - "integrity": "sha512-DfN45eJQtfXXeQwjb7vDqSJ+8e6BW3rXUB2i6IC2CbOYrLWhMBgfv3/uTm++IbCFW2zX3Yk3yqq3d4yua2no7w==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.1.7.tgz", + "integrity": "sha512-AP6FvhMybCYs3gs+vzEAzSU1K//AFT3SVTRFv+C3WMO5dLeAHeGzM8I2dxD5EHQQtqIE/8apP6CxGrnpA5YlFg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.1.3", + "@angular-devkit/core": "19.1.7", "jsonc-parser": "3.3.1", "magic-string": "0.30.17", "ora": "5.4.1", @@ -360,9 +360,9 @@ } }, "node_modules/@angular-eslint/builder": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-19.0.2.tgz", - "integrity": "sha512-BdmMSndQt2fSBiTVniskUcUpQaeweUapbsL0IDfQ7a13vL0NVXpc3K89YXuVE/xsb08uHtqphuwxPAAj6kX3OA==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-19.1.0.tgz", + "integrity": "sha512-LWdQMTES/7GySlpTNFJn3k33ZGmjjWlHI/+IHV7B3xHQ9hj4MPK4ACmE/PNOAIQ9LwQm7sKS+3cTMxOZQ/cvSg==", "dev": true, "license": "MIT", "dependencies": { @@ -375,21 +375,21 @@ } }, "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-19.0.2.tgz", - "integrity": "sha512-HPmp92r70SNO/0NdIaIhxrgVSpomqryuUk7jszvNRtu+OzYCJGcbLhQD38T3dbBWT/AV0QXzyzExn6/2ai9fEw==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-19.1.0.tgz", + "integrity": "sha512-HUJyukRvnh8Z9lIdxdblBRuBaPYEVv4iAYZMw3d+dn4rrM27Nt5oh3/zkwYrrPkt36tZdeXdDWrOuz9jgjVN5w==", "dev": true, "license": "MIT" }, "node_modules/@angular-eslint/eslint-plugin": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-19.0.2.tgz", - "integrity": "sha512-DLuNVVGGFicSThOcMSJyNje+FZSPdG0B3lCBRiqcgKH/16kfM4pV8MobPM7RGK2NhaOmmZ4zzJNwpwWPSgi+Lw==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-19.1.0.tgz", + "integrity": "sha512-TDO0+Ry+oNkxnaLHogKp1k2aey6IkJef5d7hathE4UFT6owjRizltWaRoX6bGw7Qu1yagVLL8L2Se8SddxSPAQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "19.0.2", - "@angular-eslint/utils": "19.0.2" + "@angular-eslint/bundled-angular-compiler": "19.1.0", + "@angular-eslint/utils": "19.1.0" }, "peerDependencies": { "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", @@ -398,14 +398,14 @@ } }, "node_modules/@angular-eslint/eslint-plugin-template": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-19.0.2.tgz", - "integrity": "sha512-f/OCF9ThnxQ8m0eNYPwnCrySQPhYfCOF6STL7F9LnS8Bs3ZeW3/oT1yLaMIZ1Eg0ogIkgxksMAJZjrJPUPBD1Q==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-19.1.0.tgz", + "integrity": "sha512-bIUizkCY40mnU8oAO1tLV7uN2H/cHf1evLlhpqlb9JYwc5dT2moiEhNDo61OtOgkJmDGNuThAeO9Xk9hGQc7nA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "19.0.2", - "@angular-eslint/utils": "19.0.2", + "@angular-eslint/bundled-angular-compiler": "19.1.0", + "@angular-eslint/utils": "19.1.0", "aria-query": "5.3.2", "axobject-query": "4.1.0" }, @@ -417,38 +417,52 @@ } }, "node_modules/@angular-eslint/schematics": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-19.0.2.tgz", - "integrity": "sha512-wI4SyiAnUCrpigtK6PHRlVWMC9vWljqmlLhbsJV5O5yDajlmRdvgXvSHDefhJm0hSfvZYRXuiAARYv2+QVfnGA==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-19.1.0.tgz", + "integrity": "sha512-6S1FjmM7rZxc0u0W0KjqWYOkFQ0q89IGyjPkdUt1a8NwRnWg3VoXp4WYfeuZOjda/FEYuBS/E6rckLAMp0h6Aw==", "dev": true, "license": "MIT", "dependencies": { "@angular-devkit/core": ">= 19.0.0 < 20.0.0", "@angular-devkit/schematics": ">= 19.0.0 < 20.0.0", - "@angular-eslint/eslint-plugin": "19.0.2", - "@angular-eslint/eslint-plugin-template": "19.0.2", - "ignore": "6.0.2", - "semver": "7.6.3", + "@angular-eslint/eslint-plugin": "19.1.0", + "@angular-eslint/eslint-plugin-template": "19.1.0", + "ignore": "7.0.3", + "semver": "7.7.1", "strip-json-comments": "3.1.1" } }, "node_modules/@angular-eslint/schematics/node_modules/ignore": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-6.0.2.tgz", - "integrity": "sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz", + "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } }, + "node_modules/@angular-eslint/schematics/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@angular-eslint/template-parser": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-19.0.2.tgz", - "integrity": "sha512-z3rZd2sBfuYcFf9rGDsB2zz2fbGX8kkF+0ftg9eocyQmzWrlZHFmuw9ha7oP/Mz8gpblyCS/aa1U/Srs6gz0UQ==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-19.1.0.tgz", + "integrity": "sha512-wbMi7adlC+uYqZo7NHNBShpNhFJRZsXLqihqvFpAUt1Ei6uDX8HR6MyMEDZ9tUnlqtPVW5nmbedPyLVG7HkjAA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "19.0.2", + "@angular-eslint/bundled-angular-compiler": "19.1.0", "eslint-scope": "^8.0.2" }, "peerDependencies": { @@ -457,13 +471,13 @@ } }, "node_modules/@angular-eslint/utils": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-19.0.2.tgz", - "integrity": "sha512-HotBT8OKr7zCaX1S9k27JuhRiTVIbbYVl6whlb3uwdMIPIWY8iOcEh1tjI4qDPUafpLfR72Dhwi5bO1E17F3/Q==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-19.1.0.tgz", + "integrity": "sha512-mcb7hPMH/u6wwUwvsewrmgb9y9NWN6ZacvpUvKlTOxF/jOtTdsu0XfV4YB43sp2A8NWzYzX0Str4c8K1xSmuBQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "19.0.2" + "@angular-eslint/bundled-angular-compiler": "19.1.0" }, "peerDependencies": { "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", @@ -472,9 +486,9 @@ } }, "node_modules/@angular/animations": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.1.2.tgz", - "integrity": "sha512-usf/TMBpQKRnVpEK/UzrcxtHrUgWvryMG1UDWOTsTxmfAKsYoLqy+gdcGOkSf9yEiNn8xBxFXeGqPbFPeA1fWQ==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.1.6.tgz", + "integrity": "sha512-iacosz3fygp0AyT57+suVpLChl10xS5RBje09TfQIKHTUY0LWkMspgaK9gwtlflpIhjedPV0UmgRIKhhFcQM1A==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -483,18 +497,19 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "19.1.2" + "@angular/core": "19.1.6" } }, "node_modules/@angular/build": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-19.1.3.tgz", - "integrity": "sha512-NRYBNAyCCn+6XEHv/guVZ+Y/Fan7klW6CL938G2aDzbVipSt5xCCRxYgXwACBv5BzieV16SFnQYldAzyNs0uUg==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-19.1.7.tgz", + "integrity": "sha512-22SjHZDTk91JHU5aFVDU2n+xkPolDosRVfsK4zs+RRXQs30LYPH9KCLiUWCYjFbRj7oYvw7sbrs94szo7dWYvw==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1901.3", + "@angular-devkit/architect": "0.1901.7", + "@angular-devkit/core": "19.1.7", "@babel/core": "7.26.0", "@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-split-export-declaration": "7.24.7", @@ -516,7 +531,7 @@ "rollup": "4.30.1", "sass": "1.83.1", "semver": "7.6.3", - "vite": "6.0.7", + "vite": "6.0.11", "watchpack": "2.4.2" }, "engines": { @@ -533,11 +548,11 @@ "@angular/localize": "^19.0.0", "@angular/platform-server": "^19.0.0", "@angular/service-worker": "^19.0.0", - "@angular/ssr": "^19.1.3", + "@angular/ssr": "^19.1.7", "less": "^4.2.0", "ng-packagr": "^19.0.0", "postcss": "^8.4.0", - "tailwindcss": "^2.0.0 || ^3.0.0", + "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", "typescript": ">=5.5 <5.8" }, "peerDependenciesMeta": { @@ -568,9 +583,9 @@ } }, "node_modules/@angular/build/node_modules/vite": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.7.tgz", - "integrity": "sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==", + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", + "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", "dev": true, "license": "MIT", "dependencies": { @@ -640,18 +655,18 @@ } }, "node_modules/@angular/cli": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-19.1.3.tgz", - "integrity": "sha512-GJGH3Xw7/zm12myA2R4Dg8+ny3p9tW00tx33YIK8vFjOUKycqgWaKfpYCe2s9egrm2Pew/DclHCD+IUwEAz1GQ==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-19.1.7.tgz", + "integrity": "sha512-qVEy0R4QKQ2QAGfpj2mPVxRxgOVst+rIgZBtLwf/mrbN9YyzJUaBKvaVslUpOqkvoW9mX5myf0iZkT5NykrIoA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1901.3", - "@angular-devkit/core": "19.1.3", - "@angular-devkit/schematics": "19.1.3", + "@angular-devkit/architect": "0.1901.7", + "@angular-devkit/core": "19.1.7", + "@angular-devkit/schematics": "19.1.7", "@inquirer/prompts": "7.2.1", "@listr2/prompt-adapter-inquirer": "2.0.18", - "@schematics/angular": "19.1.3", + "@schematics/angular": "19.1.7", "@yarnpkg/lockfile": "1.1.0", "ini": "5.0.0", "jsonc-parser": "3.3.1", @@ -674,9 +689,9 @@ } }, "node_modules/@angular/common": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.1.2.tgz", - "integrity": "sha512-6IhBXwz97pbXA+3vHw1hQlv4M0gc5NrDZSCQeffcraE6wpFMzo8vLcYAiNxpSyTFS7YLzCALdS6kYXVP2FBy1g==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.1.6.tgz", + "integrity": "sha512-FkuejwbxsOLhcyOgDM/7YEYvMG3tuyOvr+831VzPwMwYp5QO9AUYtn4ffGf698JccbA+Ocw3BAdhPU6i+YZC1A==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -685,14 +700,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "19.1.2", + "@angular/core": "19.1.6", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.1.2.tgz", - "integrity": "sha512-CThpvyims1aoPtqUA5UCB0lEI8lDnWBuY6VpMST4YCxhYuPmDWrwKcYXOJU1w/5yEeR8bAOvWIkKdA83MAEyHw==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.1.6.tgz", + "integrity": "sha512-Tl2PFEtnU8UgSqtEKG827xDUGZrErhR6S1JICeV1kbRCYmwQA4hhG25tzi+ifSAOPW7eJiyzP2LWIvOuZkq3Vw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -701,7 +716,7 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "19.1.2" + "@angular/core": "19.1.6" }, "peerDependenciesMeta": { "@angular/core": { @@ -710,9 +725,9 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-19.1.2.tgz", - "integrity": "sha512-CaZTG9arDVc9mGl/abqWsg79VbHAvo6ABtJa/Z6CJ6m2Y0HQPTJR6psiFqjnTSBUK43LRx8dDV3T8wIZa7DNpg==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-19.1.6.tgz", + "integrity": "sha512-rTpHC/tfLBj+5a3X+BA/4s2w5T/cHT6x3RgO8CYy7003Musn0/BiqjfE6VCIllQgLaOQRhCcf51T6Kerkzv8Dw==", "dev": true, "license": "MIT", "dependencies": { @@ -734,14 +749,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "19.1.2", + "@angular/compiler": "19.1.6", "typescript": ">=5.5 <5.8" } }, "node_modules/@angular/core": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.1.2.tgz", - "integrity": "sha512-WrOzn9X2LsXxS27fB1WNjYsFVUKvuDuZ0ERfesWb/t1prz09q7fi/YK0TXx7XOby9CfNe4aXjzRPQL2zgFuMWQ==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.1.6.tgz", + "integrity": "sha512-FD167URT+apxjzj9sG/MzffW5G6YyQiPQ6nrrIoYi9jeY3LYurybuOgvcXrU8PT4Z3+CKMq9k/ZnmrlHU72BpA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -755,9 +770,9 @@ } }, "node_modules/@angular/elements": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@angular/elements/-/elements-19.1.2.tgz", - "integrity": "sha512-Xgh/k4jBKavMRYvNnfZbK5CzXloGNzowSSVyFGrHxFkYVOcCd1SsaHzjgF2W0ekfBOjjbeJm47T0lbiPe5FFMQ==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/elements/-/elements-19.1.6.tgz", + "integrity": "sha512-w91zaktvx/5AWPVUrbVJ29brX2O+4otnnlHZimahd2S1f6VVDv5K5pTRte1Mij+MDqjw8GBX/ok0+tc5B3yqKA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -766,14 +781,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "19.1.2", + "@angular/core": "19.1.6", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/forms": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-19.1.2.tgz", - "integrity": "sha512-PmHoF4JkGbYK0pdBH2FwAKU9VBydAIjJQlol3anjUQF2zfkITeTqfVNmys1mFhojGR+ZppV0zZ+8MhI/501P7A==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-19.1.6.tgz", + "integrity": "sha512-uu/76KAwCAcDuhD67Vv78UvOC/tiprtFXOgqNCj0LK8vyFcvPsunb3nF/PtfF9rSHyslXAqxZhME+Ha2tU6Lpw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -782,16 +797,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "19.1.2", - "@angular/core": "19.1.2", - "@angular/platform-browser": "19.1.2", + "@angular/common": "19.1.6", + "@angular/core": "19.1.6", + "@angular/platform-browser": "19.1.6", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-19.1.2.tgz", - "integrity": "sha512-rU4Zf4RKabuv5d153umedNCZZReKLqHD+LgUaWjizvSHeI6dwyngJivEF0UgpFoDrm5q5UiyhMX8p1O4Bthtdw==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-19.1.6.tgz", + "integrity": "sha512-YIvCQRt+EFUKmms8M9K0ULDxAkCQSJqmnx4lGDJDHNK13U/C6r0d3/WMrrSDuSjax4zGSJf5xiRPpQlzPPsphA==", "dev": true, "license": "MIT", "engines": { @@ -799,9 +814,9 @@ } }, "node_modules/@angular/platform-browser": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.1.2.tgz", - "integrity": "sha512-fk/OrL4r5jUjAi1WTv9LGTm+DXWrPtDBpoX4z5Ze6Se+x3/6pTn1Rty1C4MNZvHiTjIQGQNRnq447GdiOjhg9w==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.1.6.tgz", + "integrity": "sha512-sfWU+gMpqQ6GYtE3tAfDktftC01NgtqAOKfeCQ/KY2rxRTIxYahenW0Licuzgmd+8AZtmncoZaYX0Fd/5XMqzQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -810,9 +825,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "19.1.2", - "@angular/common": "19.1.2", - "@angular/core": "19.1.2" + "@angular/animations": "19.1.6", + "@angular/common": "19.1.6", + "@angular/core": "19.1.6" }, "peerDependenciesMeta": { "@angular/animations": { @@ -821,9 +836,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.1.2.tgz", - "integrity": "sha512-QPHMWU6DJ+jMtodo12pvGf1VA6xhFUD8vh2+uCtcYMsCslcD+HjUZJ2+BVCjwhFSew/6RdgobTiFgiiIATvRIQ==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.1.6.tgz", + "integrity": "sha512-QedjG7/ctPtzgJ3LcWv4yMcSivKlwcZ8ge8zPe7eu9Ft6mDZZat65gJEjDuvevJoeNbo2dQODFDiyPJNmnNA9A==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -832,16 +847,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "19.1.2", - "@angular/compiler": "19.1.2", - "@angular/core": "19.1.2", - "@angular/platform-browser": "19.1.2" + "@angular/common": "19.1.6", + "@angular/compiler": "19.1.6", + "@angular/core": "19.1.6", + "@angular/platform-browser": "19.1.6" } }, "node_modules/@angular/platform-server": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-19.1.2.tgz", - "integrity": "sha512-h8Cz4UEWq3gvBOMuKynVWlC3oDmdkifj5e1Em9QsA9jmea+ZqSqyZcXtCc1sclxNTZHX6gpGLD4UIfOWpvAzog==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-19.1.6.tgz", + "integrity": "sha512-yCFkByyHDtxXZaaaRV+268WN8s45ie+R5bcJ9oPKYE3Td0f/7iTRUatDfTI8h7/xbYK4nRgGZmxuiREpjt6y6Q==", "license": "MIT", "dependencies": { "tslib": "^2.3.0", @@ -851,17 +866,17 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "19.1.2", - "@angular/common": "19.1.2", - "@angular/compiler": "19.1.2", - "@angular/core": "19.1.2", - "@angular/platform-browser": "19.1.2" + "@angular/animations": "19.1.6", + "@angular/common": "19.1.6", + "@angular/compiler": "19.1.6", + "@angular/core": "19.1.6", + "@angular/platform-browser": "19.1.6" } }, "node_modules/@angular/router": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-19.1.2.tgz", - "integrity": "sha512-yIz86uSTKFttwgWGnzHeFUvoHP+QNk+2w2OAR9UCbRoXpfx5oDhZj/zZQLmuqqpSAQyJ6qicqucEBUahA938pg==", + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-19.1.6.tgz", + "integrity": "sha512-TEfw3W5jVodVDMD4krhXGog1THZN3x1yoh2oZmCv3lXg22+pVC6Cp+x3vVExq0mS+g3/6uZwy/3qAYdlzqYjTg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -870,16 +885,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "19.1.2", - "@angular/core": "19.1.2", - "@angular/platform-browser": "19.1.2", + "@angular/common": "19.1.6", + "@angular/core": "19.1.6", + "@angular/platform-browser": "19.1.6", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/ssr": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-19.1.3.tgz", - "integrity": "sha512-1cxxbirXKbbW3/7D8RyBcs23nvXG2rBArR7qCI8jaHxprxDFSrjoKeSUM/8V13PMNan73XZZoL6rpH9KtmMpqw==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-19.1.7.tgz", + "integrity": "sha512-MNjjSWNv1K0E1K/U/pRgFo54n/1qyaFcYGYKSbnpwAGjtiCiHLudL3Dycke3mHTmcPFX61DniX1MdJtLhhFsVA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -4416,9 +4431,9 @@ } }, "node_modules/@ngtools/webpack": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-19.1.3.tgz", - "integrity": "sha512-O6bKP8J8w8U5NfFCA4ukO82rpmvii5JtXQCo2FCwafZBfYuV5GHw97ezbdUIaTbPML+EC7gq9Y85EuFAyUHtAg==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-19.1.7.tgz", + "integrity": "sha512-U39LVqHWj+GtKzBA3+AseHZgLPlL5YE/iRkZJ4PHQVrgW9LtyMzPuUmnW+e0XQwPFHq9xQxaoj3w8gApj4/MIg==", "dev": true, "license": "MIT", "engines": { @@ -5027,9 +5042,9 @@ } }, "node_modules/@puppeteer/browsers": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.6.1.tgz", - "integrity": "sha512-aBSREisdsGH890S2rQqK82qmQYU3uFpSH8wcZWHgHzl3LfzsxAKbLNiAG9mO8v1Y0UICBeClICxPJvyr0rcuxg==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.7.1.tgz", + "integrity": "sha512-MK7rtm8JjaxPN7Mf1JdZIZKPD2Z+W7osvrC1vjpvfOX1K0awDIHYbNi89f7eotp7eMUn2shWnt03HwVbriXtKQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5037,9 +5052,8 @@ "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", - "semver": "^7.6.3", - "tar-fs": "^3.0.6", - "unbzip2-stream": "^1.4.3", + "semver": "^7.7.0", + "tar-fs": "^3.0.8", "yargs": "^17.7.2" }, "bin": { @@ -5067,6 +5081,19 @@ } } }, + "node_modules/@puppeteer/browsers/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@rollup/plugin-json": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", @@ -5395,14 +5422,14 @@ } }, "node_modules/@schematics/angular": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.1.3.tgz", - "integrity": "sha512-LG3OKZG1Dl1lxNIc81jr82WSUaDCYlg/SEJ6A78p8AaZtTFKf14WenJTeG0XZPX45l26BdZSjn9MUTCggxQvGQ==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.1.7.tgz", + "integrity": "sha512-BB8yMGmYDZzSb8Nu+Ln0TKyeoS3++f9STCYw30NwM3IViHxJJYxu/zowzwSa9TjftIzdCpbOaPxGS0vU9UOUDQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.1.3", - "@angular-devkit/schematics": "19.1.3", + "@angular-devkit/core": "19.1.7", + "@angular-devkit/schematics": "19.1.7", "jsonc-parser": "3.3.1" }, "engines": { @@ -5965,10 +5992,11 @@ } }, "node_modules/@types/jasmine": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-5.1.4.tgz", - "integrity": "sha512-px7OMFO/ncXxixDe1zR13V1iycqWae0MxTaw62RpFlksUi5QuNWgQJFkTQjIOvrmutJbI7Fp2Y2N1F6D2R4G6w==", - "dev": true + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-5.1.6.tgz", + "integrity": "sha512-JDwKwipGFDwf021BtRTuluYe1aMDNimtO72ygPrVXnZSC8Df2V22AHeIgGa84tbF4SLkRvN+dJnlV8aMwQjkVw==", + "dev": true, + "license": "MIT" }, "node_modules/@types/jasminewd2": { "version": "2.0.13", @@ -6105,9 +6133,9 @@ "dev": true }, "node_modules/@types/ws": { - "version": "8.5.13", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", - "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz", + "integrity": "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==", "dev": true, "license": "MIT", "dependencies": { @@ -7235,9 +7263,9 @@ } }, "node_modules/bare-stream": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.4.tgz", - "integrity": "sha512-G6i3A74FjNq4nVrrSTUz5h3vgXzBJnjmWAVlBWaZETkgu+LgKd7AiyOml3EDJY1AHlIbBHKDXE+TUT53Ff8OaA==", + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.5.tgz", + "integrity": "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==", "dev": true, "license": "Apache-2.0", "optional": true, @@ -7998,14 +8026,14 @@ } }, "node_modules/chromium-bidi": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.11.0.tgz", - "integrity": "sha512-6CJWHkNRoyZyjV9Rwv2lYONZf1Xm0IuDyNq97nwSsxxP3wf5Bwy15K5rOvVKMtJ127jJBmxFUanSAOjgFRxgrA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-1.3.0.tgz", + "integrity": "sha512-G3x1bkST13kmbL7+dT/oRkNH/7C4UqG+0YQpmySrzXspyOhYgDNc6lhSGpj3cuexvH25WTENhTYq2Tt9JRXtbw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "mitt": "3.0.1", - "zod": "3.23.8" + "mitt": "^3.0.1", + "zod": "^3.24.1" }, "peerDependencies": { "devtools-protocol": "*" @@ -8437,9 +8465,9 @@ } }, "node_modules/compression": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", - "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz", + "integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==", "dev": true, "license": "MIT", "dependencies": { @@ -9350,9 +9378,9 @@ "license": "MIT" }, "node_modules/devtools-protocol": { - "version": "0.0.1367902", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1367902.tgz", - "integrity": "sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==", + "version": "0.0.1402036", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1402036.tgz", + "integrity": "sha512-JwAYQgEvm3yD45CHB+RmF5kMbWtXBaOGwuxa87sZogHcLCv8c/IqnThaoQ1y60d7pXWjSKWQphPEc+1rAScVdg==", "dev": true, "license": "BSD-3-Clause" }, @@ -12458,9 +12486,9 @@ } }, "node_modules/igniteui-dockmanager": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/igniteui-dockmanager/-/igniteui-dockmanager-1.15.2.tgz", - "integrity": "sha512-FtcWCbHhWfTuVZ1ltaiZstu88/O6NYny6BzkgVNELoLa/oqHCktjL6JoMTOC4a/QwDpoP3AMi+UmbvkQrE0fRQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/igniteui-dockmanager/-/igniteui-dockmanager-1.16.0.tgz", + "integrity": "sha512-MJj9UvqVUu6wx5mSr4xUnfFbZU9z0isUjIx5MJJt6XEQY+d7KYHyGCq4X7ahUBWAWd8KM3++KnDEA7/qJ4qNIg==", "dev": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { @@ -12490,9 +12518,10 @@ } }, "node_modules/igniteui-theming": { - "version": "14.3.1", - "resolved": "https://registry.npmjs.org/igniteui-theming/-/igniteui-theming-14.3.1.tgz", - "integrity": "sha512-bh7a9b+VlNOE1tAk6yDbmS5I7VGch3mYtOU1jUvCXrUf6/vPDJYy4AjCRlwR5i/PHYraEj59Cmk0D7N4phxorQ==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/igniteui-theming/-/igniteui-theming-15.0.0.tgz", + "integrity": "sha512-4ANFe6t3t9fEDexmB8/H7hEO1eBBWohu1tbEUFdfQPBMgUT/qqXbSlxW3FGCmZV7Oxr5rn9ZdXyScPxzwRx1lg==", + "license": "MIT", "peerDependencies": { "sass": "^1.69.5" } @@ -13371,23 +13400,23 @@ } }, "node_modules/jasmine": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-5.5.0.tgz", - "integrity": "sha512-JKlEVCVD5QBPYLsg/VE+IUtjyseDCrW8rMBu8la+9ysYashDgavMLM9Kotls1FhI6dCJLJ40dBCIfQjGLPZI1Q==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-5.6.0.tgz", + "integrity": "sha512-6frlW22jhgRjtlp68QY/DDVCUfrYqmSxDBWM13mrBzYQGx1XITfVcJltnY15bk8B5cRfN5IpKvemkDiDTSRCsA==", "dev": true, "license": "MIT", "dependencies": { "glob": "^10.2.2", - "jasmine-core": "~5.5.0" + "jasmine-core": "~5.6.0" }, "bin": { "jasmine": "bin/jasmine.js" } }, "node_modules/jasmine-core": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.5.0.tgz", - "integrity": "sha512-NHOvoPO6o9gVR6pwqEACTEpbgcH+JJ6QDypyymGbSUIFIFsMMbBJ/xsFNud8MSClfnWclXd7RQlAZBz7yVo5TQ==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.6.0.tgz", + "integrity": "sha512-niVlkeYVRwKFpmfWg6suo6H9CrNnydfBLEqefM5UjibYS+UoTjZdmvPJSiuyrRLGnFj1eYRhFd/ch+5hSlsFVA==", "dev": true, "license": "MIT" }, @@ -14092,9 +14121,9 @@ } }, "node_modules/launch-editor": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", - "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.10.0.tgz", + "integrity": "sha512-D7dBRJo/qcGX9xlvt/6wUYzQxjh5G1RvZPgPv8vi4KRU99DVQL/oW7tnVOCCTm2HGeo3C5HvGE5Yrh6UBoZ0vA==", "dev": true, "license": "MIT", "dependencies": { @@ -15894,9 +15923,9 @@ } }, "node_modules/ng-packagr": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-19.1.0.tgz", - "integrity": "sha512-i2S0tj2sQNOQGW+0bYViEftrnvzGSxW+/kDELVwEjnRh6KgAL0p6wH2w+aslCcELhruuGGCk96AaOfYwGPVsgQ==", + "version": "19.1.2", + "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-19.1.2.tgz", + "integrity": "sha512-h8YDp6YdPwAwbl7rs0lJE7vVugobY6m+JogS0hQ7P+52RmslPT8kRCgdvGLIS1JySwPrDFQkPh2PLBaSjwcRqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -15932,7 +15961,7 @@ }, "peerDependencies": { "@angular/compiler-cli": "^19.0.0 || ^19.1.0-next.0 || ^19.2.0-next.0", - "tailwindcss": "^2.0.0 || ^3.0.0", + "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", "tslib": "^2.3.0", "typescript": ">=5.5 <5.8" }, @@ -17843,18 +17872,18 @@ } }, "node_modules/puppeteer": { - "version": "23.11.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.11.1.tgz", - "integrity": "sha512-53uIX3KR5en8l7Vd8n5DUv90Ae9QDQsyIthaUFVzwV6yU750RjqRznEtNMBT20VthqAdemnJN+hxVdmMHKt7Zw==", + "version": "24.2.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.2.1.tgz", + "integrity": "sha512-Euno62ou0cd0dTkOYTNioSOsFF4VpSnz4ldD38hi9ov9xCNtr8DbhmoJRUx+V9OuPgecueZbKOohRrnrhkbg3Q==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.6.1", - "chromium-bidi": "0.11.0", + "@puppeteer/browsers": "2.7.1", + "chromium-bidi": "1.3.0", "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1367902", - "puppeteer-core": "23.11.1", + "devtools-protocol": "0.0.1402036", + "puppeteer-core": "24.2.1", "typed-query-selector": "^2.12.0" }, "bin": { @@ -17865,16 +17894,16 @@ } }, "node_modules/puppeteer-core": { - "version": "23.11.1", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.11.1.tgz", - "integrity": "sha512-3HZ2/7hdDKZvZQ7dhhITOUg4/wOrDRjyK2ZBllRB0ZCOi9u0cwq1ACHDjBB+nX+7+kltHjQvBRdeY7+W0T+7Gg==", + "version": "24.2.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.2.1.tgz", + "integrity": "sha512-bCypUh3WXzETafv1TCFAjIUnI8BiQ/d+XvEfEXDLcIMm9CAvROqnBmbt79yBjwasoDZsgfXnUmIJU7Y27AalVQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.6.1", - "chromium-bidi": "0.11.0", + "@puppeteer/browsers": "2.7.1", + "chromium-bidi": "1.3.0", "debug": "^4.4.0", - "devtools-protocol": "0.0.1367902", + "devtools-protocol": "0.0.1402036", "typed-query-selector": "^2.12.0", "ws": "^8.18.0" }, @@ -20212,16 +20241,6 @@ "websocket-driver": "^0.7.4" } }, - "node_modules/sockjs/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/socks": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", @@ -21346,13 +21365,6 @@ "tslib": "^2" } }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -21863,17 +21875,6 @@ "node": ">=0.8.0" } }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, "node_modules/unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -22224,6 +22225,16 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -22547,16 +22558,16 @@ } }, "node_modules/vite": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.10.tgz", - "integrity": "sha512-MEszunEcMo6pFsfXN1GhCFQqnE25tWRH0MA4f0Q7uanACi4y1Us+ZGpTMnITwCTnYzB2b9cpmnelTlxgTBmaBA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz", + "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "esbuild": "^0.24.2", - "postcss": "^8.4.49", - "rollup": "^4.23.0" + "postcss": "^8.5.1", + "rollup": "^4.30.1" }, "bin": { "vite": "bin/vite.js" @@ -23441,9 +23452,9 @@ } }, "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", + "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", "dev": true, "license": "MIT", "funding": { diff --git a/package.json b/package.json index 6dc029aec23..2b77eeb5aad 100644 --- a/package.json +++ b/package.json @@ -58,23 +58,23 @@ }, "private": true, "dependencies": { - "@angular/animations": "^19.1.2", - "@angular/common": "^19.1.2", - "@angular/compiler": "^19.1.2", - "@angular/core": "^19.1.2", - "@angular/elements": "^19.1.2", - "@angular/forms": "^19.1.2", - "@angular/platform-browser": "^19.1.2", - "@angular/platform-browser-dynamic": "^19.1.2", - "@angular/platform-server": "^19.1.2", - "@angular/router": "^19.1.2", - "@angular/ssr": "^19.1.3", + "@angular/animations": "^19.1.6", + "@angular/common": "^19.1.6", + "@angular/compiler": "^19.1.6", + "@angular/core": "^19.1.6", + "@angular/elements": "^19.1.6", + "@angular/forms": "^19.1.6", + "@angular/platform-browser": "^19.1.6", + "@angular/platform-browser-dynamic": "^19.1.6", + "@angular/platform-server": "^19.1.6", + "@angular/router": "^19.1.6", + "@angular/ssr": "^19.1.7", "@igniteui/material-icons-extended": "^3.1.0", "@lit-labs/ssr-dom-shim": "^1.2.1", "@types/source-map": "0.5.2", "express": "^4.21.1", "fflate": "^0.8.1", - "igniteui-theming": "^14.3.1", + "igniteui-theming": "^15.0.0", "igniteui-trial-watermark": "^3.0.2", "lodash-es": "^4.17.21", "rxjs": "^7.8.0", @@ -82,22 +82,22 @@ "zone.js": "~0.15.0" }, "devDependencies": { - "@angular-devkit/build-angular": "^19.1.3", - "@angular-devkit/schematics": "^19.1.3", - "@angular-eslint/builder": "^19.0.2", - "@angular-eslint/eslint-plugin": "^19.0.2", - "@angular-eslint/eslint-plugin-template": "^19.0.2", - "@angular-eslint/schematics": "^19.0.2", - "@angular-eslint/template-parser": "^19.0.2", - "@angular/cli": "^19.1.3", - "@angular/compiler-cli": "^19.1.2", - "@angular/language-service": "^19.1.2", + "@angular-devkit/build-angular": "^19.1.7", + "@angular-devkit/schematics": "^19.1.7", + "@angular-eslint/builder": "^19.1.0", + "@angular-eslint/eslint-plugin": "^19.1.0", + "@angular-eslint/eslint-plugin-template": "^19.1.0", + "@angular-eslint/schematics": "^19.1.0", + "@angular-eslint/template-parser": "^19.1.0", + "@angular/cli": "^19.1.7", + "@angular/compiler-cli": "^19.1.6", + "@angular/language-service": "^19.1.6", "@angularclass/hmr": "^3.0.0", "@microsoft/signalr": "^7.0.12", "@types/estree": "^1.0.0", "@types/express": "^5.0.0", "@types/hammerjs": "^2.0.46", - "@types/jasmine": "^5.1.1", + "@types/jasmine": "^5.1.6", "@types/jasminewd2": "^2.0.10", "@types/node": "^20.17.6", "@types/sass-true": "^6.0.2", @@ -118,11 +118,11 @@ "hammer-simulator": "0.0.1", "hammerjs": "^2.0.8", "ig-typedoc-theme": "^6.0.0", - "igniteui-dockmanager": "^1.15.2", + "igniteui-dockmanager": "^1.16.0", "igniteui-sassdoc-theme": "^1.2.3", "igniteui-webcomponents": "5.2.0", - "jasmine": "^5.5.0", - "jasmine-core": "~5.5.0", + "jasmine": "^5.6.0", + "jasmine-core": "^5.6.0", "karma": "^6.4.4", "karma-chrome-launcher": "~3.2.0", "karma-coverage": "^2.0.3", @@ -131,11 +131,11 @@ "karma-parallel": "^0.3.1", "karma-spec-reporter": "^0.0.36", "lit-html": "^3.2.1", - "ng-packagr": "^19.1.0", + "ng-packagr": "^19.1.2", "postcss": "^8.5.1", "postcss-scss": "^4.0.6", "prettier": "^3.3.3", - "puppeteer": "^23.11.1", + "puppeteer": "^24.2.1", "sass-embedded": "^1.83.4", "sass-true": "^8.1.0", "sassdoc": "^2.7.4", diff --git a/projects/igniteui-angular-elements/src/app/wrapper/wrapper.component.html b/projects/igniteui-angular-elements/src/app/wrapper/wrapper.component.html index 4a018a09576..8a1718cf1d2 100644 --- a/projects/igniteui-angular-elements/src/app/wrapper/wrapper.component.html +++ b/projects/igniteui-angular-elements/src/app/wrapper/wrapper.component.html @@ -1,4 +1,6 @@ - -
- {{ litRender(container, templateFunc, context) }} -
+@for (templateFunc of templateFunctions; track templateFunc) { + +
+ {{ litRender(container, templateFunc, context) }} +
+} diff --git a/projects/igniteui-angular-elements/src/app/wrapper/wrapper.component.ts b/projects/igniteui-angular-elements/src/app/wrapper/wrapper.component.ts index 4faa7636907..35ba746cd94 100644 --- a/projects/igniteui-angular-elements/src/app/wrapper/wrapper.component.ts +++ b/projects/igniteui-angular-elements/src/app/wrapper/wrapper.component.ts @@ -1,4 +1,3 @@ -import { NgFor } from '@angular/common'; import { ChangeDetectorRef, Component, QueryList, TemplateRef, ViewChildren } from '@angular/core'; import { TemplateRefWrapper } from './template-ref-wrapper'; @@ -10,7 +9,7 @@ type TemplateFunction = (arg: any) => TemplateResult; selector: 'igx-template-wrapper', templateUrl: './wrapper.component.html', styleUrls: ['./wrapper.component.scss'], - imports: [NgFor] + imports: [] }) export class TemplateWrapperComponent { @@ -18,7 +17,8 @@ export class TemplateWrapperComponent { /** * All template refs - * Warning: the first is always the root `ngFor` template. TODO(D.P.): filter it out? + * Warning: the first is always the root `@for` template + * (internally creates one like the old `>; diff --git a/projects/igniteui-angular-i18n/src/i18n/BG/grid-resources.ts b/projects/igniteui-angular-i18n/src/i18n/BG/grid-resources.ts index f373135ebae..7ec521a1efb 100644 --- a/projects/igniteui-angular-i18n/src/i18n/BG/grid-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/BG/grid-resources.ts @@ -106,7 +106,7 @@ export const GridResourceStringsBG = { igx_grid_advanced_filter_ungroup: 'Разгрупирай', igx_grid_advanced_filter_delete: 'Изтрий', igx_grid_advanced_filter_delete_filters: 'Изтрий филтрите', - igx_grid_advanced_filter_initial_text: 'Започнете със създаване не група от условия свързани с "And" или "Or".', + igx_grid_advanced_filter_initial_text: 'Започнете със създаване на група от условия свързани с "And" или "Or".', igx_grid_advanced_filter_column_placeholder: 'Избери колона', igx_grid_advanced_filter_value_placeholder: 'Стойност', igx_grid_pinned_row_indicator: 'Закачени', diff --git a/projects/igniteui-angular-i18n/src/i18n/BG/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/BG/query-builder-resources.ts index dbd9873fb4d..c131b0619d1 100644 --- a/projects/igniteui-angular-i18n/src/i18n/BG/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/BG/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsBG = { igx_query_builder_date_placeholder: 'Избери дата', igx_query_builder_time_placeholder: 'Избери време', + igx_query_builder_datetime_placeholder: 'Избери дата и час', igx_query_builder_filter_operator_and: 'And', igx_query_builder_filter_operator_or: 'Or', igx_query_builder_filter_contains: 'Съдържа', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsBG = { igx_query_builder_filter_notEmpty: 'Не е празно', igx_query_builder_filter_null: 'Null', igx_query_builder_filter_notNull: 'Не е Null', + igx_query_builder_filter_in: 'В/във', + igx_query_builder_filter_notIn: 'Не е в/във', igx_query_builder_filter_before: 'Преди', igx_query_builder_filter_after: 'След', igx_query_builder_filter_at: 'На', @@ -39,20 +42,38 @@ export const QueryBuilderResourceStringsBG = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: 'Всички', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'От', + igx_query_builder_select_label: 'Избери', + igx_query_builder_where_label: 'Където', igx_query_builder_and_group: '"And" група', igx_query_builder_or_group: '"Or" група', igx_query_builder_end_group: 'Край на групирането', igx_query_builder_and_label: 'and', igx_query_builder_or_label: 'or', - igx_query_builder_add_condition: 'Условие', - igx_query_builder_create_and_group: 'Създай "And" група', - igx_query_builder_create_or_group: 'Създай "Or" група', + igx_query_builder_switch_group: 'Премини към {0}', + igx_query_builder_add_condition: 'Добави условие', + igx_query_builder_add_group: 'Добави група', + igx_query_builder_add_condition_root: 'Условие', + igx_query_builder_add_group_root: 'Група', igx_query_builder_ungroup: 'Разгрупирай', igx_query_builder_delete: 'Изтрий', igx_query_builder_delete_filters: 'Изтрий филтрите', - igx_query_builder_initial_text: 'Започнете със създаване не група от условия свързани с "And" или "Or".', + igx_query_builder_initial_text: 'Започнете със създаване на група от условия свързани с "And" или "Or".', igx_query_builder_column_placeholder: 'Избери колона', - igx_query_builder_condition_placeholder: 'Изберете филтър', + igx_query_builder_condition_placeholder: 'Избери филтър', igx_query_builder_value_placeholder: 'Стойност', + igx_query_builder_query_value_placeholder: 'Резултати от подзаявка', + igx_query_builder_all_fields: 'Всички полета', + igx_query_builder_details: 'Детайли', + igx_query_builder_search: 'Търсене', + igx_query_builder_select_all: 'Избери всички', + igx_query_builder_select_entity: 'Избери обект', + igx_query_builder_select_return_field_single: 'Избери поле за връщане', + igx_query_builder_select_return_fields: 'Избери полета за връщане', + igx_query_builder_dialog_title: 'Потвърждение', + igx_query_builder_dialog_message: 'С промяната на обекта ще загубите текущите си настройки. Сигурни ли сте, че искате да продължите?', + igx_query_builder_dialog_checkbox_text: 'Не показвай този диалогов прозорец отново', + igx_query_builder_dialog_cancel: 'Отказ', + igx_query_builder_dialog_confirm: 'Потвърди', + igx_query_builder_drop_ghost_text: 'Пусни тук за вмъкване' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/CS/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/CS/query-builder-resources.ts index ed641423d60..c12f031c1bb 100644 --- a/projects/igniteui-angular-i18n/src/i18n/CS/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/CS/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsCS = { igx_query_builder_date_placeholder: 'Datum výdeje', igx_query_builder_time_placeholder: 'Čas vyzvednutí', + igx_query_builder_datetime_placeholder: 'Vyberte datum a čas', igx_query_builder_filter_operator_and: 'A', igx_query_builder_filter_operator_or: 'Nebo', igx_query_builder_filter_contains: 'Obsahuje', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsCS = { igx_query_builder_filter_notEmpty: 'Není prázdný', igx_query_builder_filter_null: 'Nula', igx_query_builder_filter_notNull: 'Nenulový', + igx_query_builder_filter_in: 'V', + igx_query_builder_filter_notIn: 'Není v', igx_query_builder_filter_before: 'Před', igx_query_builder_filter_after: 'Po', igx_query_builder_filter_at: 'V', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsCS = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: 'Všechno', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'Z', + igx_query_builder_select_label: 'Vybrat', + igx_query_builder_where_label: 'Kde', igx_query_builder_and_group: '"A" skupina', igx_query_builder_or_group: '"Nebo" skupina', igx_query_builder_end_group: 'Ukončit skupina', igx_query_builder_and_label: 'a', igx_query_builder_or_label: 'nebo', - igx_query_builder_add_condition: 'Stav', - igx_query_builder_create_and_group: 'Vytvořte skupinu "A"', - igx_query_builder_create_or_group: 'Vytvořte skupinu "Nebo"', + igx_query_builder_switch_group: 'Přepnout na {0}', + igx_query_builder_add_condition: 'Vytvořte stav', + igx_query_builder_add_group: 'Vytvořte skupina', + igx_query_builder_add_condition_root: 'Stav', + igx_query_builder_add_group_root: 'Skupina', igx_query_builder_ungroup: 'Oddělit', igx_query_builder_delete: 'Vymazat', igx_query_builder_delete_filters: 'Smazat filtry', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsCS = { igx_query_builder_column_placeholder: 'Vyberte sloupec', igx_query_builder_condition_placeholder: 'Vyberte filtr', igx_query_builder_value_placeholder: 'Hodnota', + igx_query_builder_query_value_placeholder: 'Výsledky dílčího dotazu', + igx_query_builder_all_fields: 'Všechna pole', + igx_query_builder_details: 'Podrobnosti', + igx_query_builder_search: 'Vyhledávání', + igx_query_builder_select_all: 'Vybrat vše', + igx_query_builder_select_entity: 'Vyberte entitu', + igx_query_builder_select_return_field_single: 'Vyberte návratové pole', + igx_query_builder_select_return_fields: 'Vyberte pole pro vrácení', + igx_query_builder_dialog_title: 'Potvrzení', + igx_query_builder_dialog_message: 'Změnou entity ztratíte svá aktuální nastavení. Opravdu to chcete udělat?', + igx_query_builder_dialog_checkbox_text: 'Tento dialog již příště nezobrazovat', + igx_query_builder_dialog_cancel: 'Zrušení', + igx_query_builder_dialog_confirm: 'Potvrdit', + igx_query_builder_drop_ghost_text: 'Přetažením sem vložíte' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/DA/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/DA/query-builder-resources.ts index 27fda75423b..0ef3bf3ec28 100644 --- a/projects/igniteui-angular-i18n/src/i18n/DA/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/DA/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsDA = { igx_query_builder_date_placeholder: 'Afhentningsdato', igx_query_builder_time_placeholder: 'Afhentningstidspunkt', + igx_query_builder_datetime_placeholder: 'Vælg dato og tid', igx_query_builder_filter_operator_and: 'Og', igx_query_builder_filter_operator_or: 'Eller', igx_query_builder_filter_contains: 'Indeholder', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsDA = { igx_query_builder_filter_notEmpty: 'Ikke tom', igx_query_builder_filter_null: 'Null', igx_query_builder_filter_notNull: 'Ikke Null', + igx_query_builder_filter_in: 'I', + igx_query_builder_filter_notIn: 'Ikke i', igx_query_builder_filter_before: 'Før', igx_query_builder_filter_after: 'Efter', igx_query_builder_filter_at: 'På', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsDA = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: 'Alle', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'Fra', + igx_query_builder_select_label: 'Vælg', + igx_query_builder_where_label: 'Hvor', igx_query_builder_and_group: '"Og" gruppe', igx_query_builder_or_group: '"Eller" gruppe', igx_query_builder_end_group: 'Afslut gruppe', igx_query_builder_and_label: 'og', igx_query_builder_or_label: 'eller', - igx_query_builder_add_condition: 'Tilstand', - igx_query_builder_create_and_group: 'Opret "Og" gruppe', - igx_query_builder_create_or_group: 'Opret "Eller" gruppe', + igx_query_builder_switch_group: 'Skift til {0}', + igx_query_builder_add_condition: 'Opret tilstand', + igx_query_builder_add_group: 'Opret gruppe', + igx_query_builder_add_condition_root: 'Tilstand', + igx_query_builder_add_group_root: 'Gruppe', igx_query_builder_ungroup: 'Fjern gruppe', igx_query_builder_delete: 'Slet', igx_query_builder_delete_filters: 'Slet filtre', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsDA = { igx_query_builder_column_placeholder: 'Vælg kolonne', igx_query_builder_condition_placeholder: 'Vælg filter', igx_query_builder_value_placeholder: 'Værdi', + igx_query_builder_query_value_placeholder: 'Underforespørgselsresultater', + igx_query_builder_all_fields: 'Alle felter', + igx_query_builder_details: 'Detaljer', + igx_query_builder_search: 'Søg', + igx_query_builder_select_all: 'Vælg alle', + igx_query_builder_select_entity: 'Vælg objekt', + igx_query_builder_select_return_field_single: 'Vælg returfelt', + igx_query_builder_select_return_fields: 'Vælg returfelter', + igx_query_builder_dialog_title: 'Bekræftelse', + igx_query_builder_dialog_message: 'Ved at ændre objektet mister du dine nuværende indstillinger. Er du sikker på, at du vil fortsætte?', + igx_query_builder_dialog_checkbox_text: 'Vis ikke denne dialogboks igen', + igx_query_builder_dialog_cancel: 'Annuller', + igx_query_builder_dialog_confirm: 'Bekræft', + igx_query_builder_drop_ghost_text: 'Slip her for at indsætte' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/DE/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/DE/query-builder-resources.ts index 040c5aab30a..9d65e4cc872 100644 --- a/projects/igniteui-angular-i18n/src/i18n/DE/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/DE/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsDE = { igx_query_builder_date_placeholder: 'Wähle Datum', igx_query_builder_time_placeholder: 'Abholungszeit', + igx_query_builder_datetime_placeholder: 'Datum und Uhrzeit auswählen', igx_query_builder_filter_operator_and: 'Und', igx_query_builder_filter_operator_or: 'Oder', igx_query_builder_filter_contains: 'Enthält', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsDE = { igx_query_builder_filter_notEmpty: 'Nicht leer', igx_query_builder_filter_null: 'Null', igx_query_builder_filter_notNull: 'Nicht Null', + igx_query_builder_filter_in: 'In', + igx_query_builder_filter_notIn: 'Nicht in', igx_query_builder_filter_before: 'Vor', igx_query_builder_filter_after: 'Nach', igx_query_builder_filter_at: 'Um', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsDE = { igx_query_builder_filter_true: 'Wahr', igx_query_builder_filter_false: 'Falsch', igx_query_builder_filter_all: 'Alle', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'Von', + igx_query_builder_select_label: 'Auswählen', + igx_query_builder_where_label: 'Wo', igx_query_builder_and_group: '"Und" Gruppe', igx_query_builder_or_group: '"Oder" Gruppe', igx_query_builder_end_group: 'Beende Gruppe', igx_query_builder_and_label: 'und', igx_query_builder_or_label: 'oder', - igx_query_builder_add_condition: 'Bedingung', - igx_query_builder_create_and_group: 'Erstelle "Und" Gruppe', - igx_query_builder_create_or_group: 'Erstelle "Oder" Gruppe', + igx_query_builder_switch_group: 'Wechseln zu {0}', + igx_query_builder_add_condition: 'Erstelle bedingung', + igx_query_builder_add_group: 'Erstelle gruppe', + igx_query_builder_add_condition_root: 'Bedingung', + igx_query_builder_add_group_root: 'Gruppe', igx_query_builder_ungroup: 'Lösche Gruppierung', igx_query_builder_delete: 'Lösche', igx_query_builder_delete_filters: 'Lösche Filter', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsDE = { igx_query_builder_column_placeholder: 'Wähle Spalte', igx_query_builder_condition_placeholder: 'Wähle Filter', igx_query_builder_value_placeholder: 'Wert', + igx_query_builder_query_value_placeholder: 'Unterabfrageergebnisse', + igx_query_builder_all_fields: 'Alle Felder', + igx_query_builder_details: 'Details', + igx_query_builder_search: 'Suchen', + igx_query_builder_select_all: 'Alle auswählen', + igx_query_builder_select_entity: 'Entität auswählen', + igx_query_builder_select_return_field_single: 'Rückgabefeld auswählen', + igx_query_builder_select_return_fields: 'Rückgabefelder auswählen', + igx_query_builder_dialog_title: 'Bestätigung', + igx_query_builder_dialog_message: 'Durch das Ändern der Entität gehen Ihre aktuellen Einstellungen verloren. Möchten Sie wirklich fortfahren?', + igx_query_builder_dialog_checkbox_text: 'Dieses Dialogfeld nicht mehr anzeigen', + igx_query_builder_dialog_cancel: 'Abbrechen', + igx_query_builder_dialog_confirm: 'Bestätigen', + igx_query_builder_drop_ghost_text: 'Hier ablegen, um einzufügen' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/ES/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/ES/query-builder-resources.ts index 8e33e074d5a..d4073ae3142 100644 --- a/projects/igniteui-angular-i18n/src/i18n/ES/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/ES/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsES = { igx_query_builder_date_placeholder: 'Elegir Fecha', igx_query_builder_time_placeholder: 'Hora de recogida', + igx_query_builder_datetime_placeholder: 'Seleccionar fecha y hora', igx_query_builder_filter_operator_and: 'Y', igx_query_builder_filter_operator_or: 'O', igx_query_builder_filter_contains: 'Contiene', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsES = { igx_query_builder_filter_notEmpty: 'No Vacío', igx_query_builder_filter_null: 'Nulo', igx_query_builder_filter_notNull: 'No Nulo', + igx_query_builder_filter_in: 'En', + igx_query_builder_filter_notIn: 'No en', igx_query_builder_filter_before: 'Antes', igx_query_builder_filter_after: 'Después', igx_query_builder_filter_at: 'A la(s)', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsES = { igx_query_builder_filter_true: 'Verdadero', igx_query_builder_filter_false: 'Falso', igx_query_builder_filter_all: 'Todo', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'Desde', + igx_query_builder_select_label: 'Seleccionar', + igx_query_builder_where_label: 'Donde', igx_query_builder_and_group: 'Grupo "Y"', igx_query_builder_or_group: '"Grupo "O"', igx_query_builder_end_group: 'Grupo Fin', igx_query_builder_and_label: 'y', igx_query_builder_or_label: 'o', - igx_query_builder_add_condition: 'Condición', - igx_query_builder_create_and_group: 'Crear grupo "Y"', - igx_query_builder_create_or_group: 'Crear grupo "O"', + igx_query_builder_switch_group: 'Cambiar a {0}', + igx_query_builder_add_condition: 'Crear condición', + igx_query_builder_add_group: 'Crear grupo', + igx_query_builder_add_condition_root: 'Condición', + igx_query_builder_add_group_root: 'Grupo', igx_query_builder_ungroup: 'Desagrupar', igx_query_builder_delete: 'Eliminar', igx_query_builder_delete_filters: 'Eliminar filtros', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsES = { igx_query_builder_column_placeholder: 'Seleccionar columna', igx_query_builder_condition_placeholder: 'Seleccionar filtro', igx_query_builder_value_placeholder: 'Valor', + igx_query_builder_query_value_placeholder: 'Resultados de la subconsulta', + igx_query_builder_all_fields: 'Todos los campos', + igx_query_builder_details: 'Detalles', + igx_query_builder_search: 'Buscar', + igx_query_builder_select_all: 'Seleccionar todo', + igx_query_builder_select_entity: 'Seleccionar entidad', + igx_query_builder_select_return_field_single: 'Seleccionar campo de devolución', + igx_query_builder_select_return_fields: 'Seleccionar campos de retorno', + igx_query_builder_dialog_title: 'Confirmación', + igx_query_builder_dialog_message: 'Al cambiar la entidad, se perderán las configuraciones actuales. ¿Está seguro de que desea continuar?', + igx_query_builder_dialog_checkbox_text: 'No volver a mostrar este cuadro de diálogo', + igx_query_builder_dialog_cancel: 'Cancelar', + igx_query_builder_dialog_confirm: 'Confirmar', + igx_query_builder_drop_ghost_text: 'Soltar aquí para insertar' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/FR/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/FR/query-builder-resources.ts index 70b28a6a99a..5c582d27c80 100644 --- a/projects/igniteui-angular-i18n/src/i18n/FR/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/FR/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsFR = { igx_query_builder_date_placeholder: 'Choisir la date', igx_query_builder_time_placeholder: 'Heure de récupération', + igx_query_builder_datetime_placeholder: 'Sélectionner la date et l\'heure', igx_query_builder_filter_operator_and: 'Et', igx_query_builder_filter_operator_or: 'Ou', igx_query_builder_filter_contains: 'Contient', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsFR = { igx_query_builder_filter_notEmpty: 'Pas vide', igx_query_builder_filter_null: 'Nul', igx_query_builder_filter_notNull: 'Pas nul', + igx_query_builder_filter_in: 'Dans', + igx_query_builder_filter_notIn: 'Pas dans', igx_query_builder_filter_before: 'Avant', igx_query_builder_filter_after: 'Après', igx_query_builder_filter_at: 'À', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsFR = { igx_query_builder_filter_true: 'Vrai', igx_query_builder_filter_false: 'Faux', igx_query_builder_filter_all: 'Tout', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'De', + igx_query_builder_select_label: 'Sélectionner', + igx_query_builder_where_label: 'Où', igx_query_builder_and_group: 'Groupe "Et"', igx_query_builder_or_group: 'Groupe "Ou"', igx_query_builder_end_group: 'Quitter le groupe', igx_query_builder_and_label: 'et', igx_query_builder_or_label: 'ou', - igx_query_builder_add_condition: 'Condition', - igx_query_builder_create_and_group: 'Créer un groupe "Et"', - igx_query_builder_create_or_group: 'Créer un groupe "Ou"', + igx_query_builder_switch_group: 'Passer à {0}', + igx_query_builder_add_condition: 'Créer un condition', + igx_query_builder_add_group: 'Créer un groupe', + igx_query_builder_add_condition_root: 'Condition', + igx_query_builder_add_group_root: 'Groupe', igx_query_builder_ungroup: 'Supprimer le regroupement', igx_query_builder_delete: 'Supprimer', igx_query_builder_delete_filters: 'Supprimer les filtres', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsFR = { igx_query_builder_column_placeholder: 'Sélectionner la colonne', igx_query_builder_condition_placeholder: 'Sélectionner le filtre', igx_query_builder_value_placeholder: 'Valeur', + igx_query_builder_query_value_placeholder: 'Résultats de la sous-requête', + igx_query_builder_all_fields: 'Tous les domaines', + igx_query_builder_details: 'Détails', + igx_query_builder_search: 'Chercher', + igx_query_builder_select_all: 'Sélectionner tout', + igx_query_builder_select_entity: 'Sélectionner une entité', + igx_query_builder_select_return_field_single: 'Sélectionnez le champ de retour', + igx_query_builder_select_return_fields: 'Sélectionner les champs de retour', + igx_query_builder_dialog_title: 'Confirmation', + igx_query_builder_dialog_message: 'En changeant l\'entité, vous perdrez vos paramètres actuels. Êtes-vous sûr de vouloir faire cela ?', + igx_query_builder_dialog_checkbox_text: 'Ne plus afficher cette boîte de dialogue', + igx_query_builder_dialog_cancel: 'Annuler', + igx_query_builder_dialog_confirm: 'Confirmer', + igx_query_builder_drop_ghost_text: 'Déposez ici pour insérer' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/HU/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/HU/query-builder-resources.ts index 49353558148..650b8c7200d 100644 --- a/projects/igniteui-angular-i18n/src/i18n/HU/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/HU/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsHU = { igx_query_builder_date_placeholder: 'Felvétel dátuma', igx_query_builder_time_placeholder: 'Felvétel időpontja', + igx_query_builder_datetime_placeholder: 'Dátum és idő kiválasztása', igx_query_builder_filter_operator_and: 'És', igx_query_builder_filter_operator_or: 'Vagy', igx_query_builder_filter_contains: 'Tartalmazza', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsHU = { igx_query_builder_filter_notEmpty: 'Nem üres', igx_query_builder_filter_null: 'Nullértékű', igx_query_builder_filter_notNull: 'Nem nullértékű', + igx_query_builder_filter_in: 'Itt', + igx_query_builder_filter_notIn: 'Nem itt', igx_query_builder_filter_before: 'Előtte', igx_query_builder_filter_after: 'Utána', igx_query_builder_filter_at: 'Ekkor', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsHU = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: 'Összes', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'Kezdete', + igx_query_builder_select_label: 'Kiválasztás', + igx_query_builder_where_label: 'Ahol', igx_query_builder_and_group: '"És" csoport', igx_query_builder_or_group: '"Vagy" Csoport', igx_query_builder_end_group: 'Vége csoport', igx_query_builder_and_label: 'és', igx_query_builder_or_label: 'vagy', - igx_query_builder_add_condition: 'Feltétel', - igx_query_builder_create_and_group: '"És" csoport létrehozása', - igx_query_builder_create_or_group: '"Vagy" csoport létrehozása', + igx_query_builder_switch_group: 'Váltás a(z) {0}', + igx_query_builder_add_condition: 'Feltétel létrehozása', + igx_query_builder_add_group: 'Csoport létrehozása', + igx_query_builder_add_condition_root: 'Feltétel', + igx_query_builder_add_group_root: 'Csoport', igx_query_builder_ungroup: 'Csoportbontás', igx_query_builder_delete: 'Törlés', igx_query_builder_delete_filters: 'Szűrők törlése', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsHU = { igx_query_builder_column_placeholder: 'Oszlop kiválasztása', igx_query_builder_condition_placeholder: 'Szűrő kiválasztása', igx_query_builder_value_placeholder: 'Érték', -} satisfies MakeRequired; + igx_query_builder_query_value_placeholder: 'Allekérdezés eredményei', + igx_query_builder_all_fields: 'Minden mező', + igx_query_builder_details: 'Részletek', + igx_query_builder_search: 'Keresés', + igx_query_builder_select_all: 'Mindet kijelöli', + igx_query_builder_select_entity: 'Entitás kiválasztása', + igx_query_builder_select_return_field_single: 'Válassza ki a visszatérési mezőt', + igx_query_builder_select_return_fields: 'Visszatérő mezők kiválasztása', + igx_query_builder_dialog_title: 'Megerősítés', + igx_query_builder_dialog_message: 'Az entitás megváltoztatásával elveszíti jelenlegi beállításait. Biztos, hogy folytatni kívánja?', + igx_query_builder_dialog_checkbox_text: 'Ne jelenjen meg többet ez a párbeszédpanel', + igx_query_builder_dialog_cancel: 'Mégse', + igx_query_builder_dialog_confirm: 'Megerősítés', + igx_query_builder_drop_ghost_text: 'Húzza ide a beszúráshoz' +} satisfies MakeRequired; \ No newline at end of file diff --git a/projects/igniteui-angular-i18n/src/i18n/IT/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/IT/query-builder-resources.ts index 02b308fcf64..bdde42dae39 100644 --- a/projects/igniteui-angular-i18n/src/i18n/IT/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/IT/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsIT = { igx_query_builder_date_placeholder: 'Data di prelievo', igx_query_builder_time_placeholder: 'Ora ritiro', + igx_query_builder_datetime_placeholder: 'Seleziona data e ora', igx_query_builder_filter_operator_and: 'E', igx_query_builder_filter_operator_or: 'O', igx_query_builder_filter_contains: 'Contiene', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsIT = { igx_query_builder_filter_notEmpty: 'Non vuoto', igx_query_builder_filter_null: 'Null', igx_query_builder_filter_notNull: 'Non null', + igx_query_builder_filter_in: 'In', + igx_query_builder_filter_notIn: 'Non in', igx_query_builder_filter_before: 'Prima', igx_query_builder_filter_after: 'Dopo', igx_query_builder_filter_at: 'A', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsIT = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: 'Tutto', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'Da', + igx_query_builder_select_label: 'Seleziona', + igx_query_builder_where_label: 'Dove', igx_query_builder_and_group: 'Gruppo "And"', igx_query_builder_or_group: 'Gruppo "Or"', igx_query_builder_end_group: 'Gruppo finale', igx_query_builder_and_label: 'e', igx_query_builder_or_label: 'oppure', - igx_query_builder_add_condition: 'Condizione', - igx_query_builder_create_and_group: 'Crea gruppo "And"', - igx_query_builder_create_or_group: 'Crea gruppo "Or"', + igx_query_builder_switch_group: 'Passa a {0}', + igx_query_builder_add_condition: 'Crea condizione', + igx_query_builder_add_group: 'Crea gruppo', + igx_query_builder_add_condition_root: 'Condizione', + igx_query_builder_add_group_root: 'Gruppo', igx_query_builder_ungroup: 'Togli dal gruppo', igx_query_builder_delete: 'Elimina', igx_query_builder_delete_filters: 'Elimina filtri', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsIT = { igx_query_builder_column_placeholder: 'Seleziona colonna', igx_query_builder_condition_placeholder: 'Seleziona filtro', igx_query_builder_value_placeholder: 'Valore', + igx_query_builder_query_value_placeholder: 'Risultati della sottoquery', + igx_query_builder_all_fields: 'Tutti i campi', + igx_query_builder_details: 'Dettagli', + igx_query_builder_search: 'Cerca', + igx_query_builder_select_all: 'Seleziona tutto', + igx_query_builder_select_entity: 'Seleziona entità', + igx_query_builder_select_return_field_single: 'Seleziona il campo di ritorno', + igx_query_builder_select_return_fields: 'Seleziona campi di ritorno', + igx_query_builder_dialog_title: 'Conferma', + igx_query_builder_dialog_message: 'Modificando l\'entità, perderai le impostazioni correnti. Procedere?', + igx_query_builder_dialog_checkbox_text: 'Non visualizzare più questo messaggio', + igx_query_builder_dialog_cancel: 'Annulla', + igx_query_builder_dialog_confirm: 'Conferma', + igx_query_builder_drop_ghost_text: 'Trascinare qui per inserire' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/JA/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/JA/query-builder-resources.ts index af954e9fe6b..89b29821a01 100644 --- a/projects/igniteui-angular-i18n/src/i18n/JA/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/JA/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsJA = { igx_query_builder_date_placeholder: '日付の選択', igx_query_builder_time_placeholder: 'ピックアップ時間', + igx_query_builder_datetime_placeholder: '日付と時間の選択', igx_query_builder_filter_operator_and: 'And', igx_query_builder_filter_operator_or: 'Or', igx_query_builder_filter_contains: 'を含む', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsJA = { igx_query_builder_filter_notEmpty: '空以外', igx_query_builder_filter_null: 'Null', igx_query_builder_filter_notNull: 'Null 以外', + igx_query_builder_filter_in: '~に含まれる', + igx_query_builder_filter_notIn: '~に含まれない', igx_query_builder_filter_before: '前', igx_query_builder_filter_after: '後', igx_query_builder_filter_at: '特定の時間', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsJA = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: 'すべて', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'から', + igx_query_builder_select_label: '選択', + igx_query_builder_where_label: '条件', igx_query_builder_and_group: '"And" グループ', igx_query_builder_or_group: '"Or" グループ', igx_query_builder_end_group: 'End グループ', igx_query_builder_and_label: 'and', igx_query_builder_or_label: 'or', - igx_query_builder_add_condition: '条件', - igx_query_builder_create_and_group: '"And" グループの作成', - igx_query_builder_create_or_group: '"Or" グループの作成', + igx_query_builder_switch_group: '{0} に切り替える', + igx_query_builder_add_condition: '条件の作成', + igx_query_builder_add_group: 'グループの作成', + igx_query_builder_add_condition_root: '条件', + igx_query_builder_add_group_root: 'グループ', igx_query_builder_ungroup: 'グループ解除', igx_query_builder_delete: '削除', igx_query_builder_delete_filters: 'フィルターの削除', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsJA = { igx_query_builder_column_placeholder: '列の選択', igx_query_builder_condition_placeholder: 'フィルターの選択', igx_query_builder_value_placeholder: '値', + igx_query_builder_query_value_placeholder: 'サブクエリの結果', + igx_query_builder_all_fields: 'すべてのフィールド', + igx_query_builder_details: '詳細', + igx_query_builder_search: '検索', + igx_query_builder_select_all: 'すべて選択', + igx_query_builder_select_entity: 'エンティティの選択', + igx_query_builder_select_return_field_single: '返却フィールドの選択', + igx_query_builder_select_return_fields: '返却フィールドの選択', + igx_query_builder_dialog_title: '確認', + igx_query_builder_dialog_message: 'エンティティを変更すると、現在の設定は失われます。続行しますか?', + igx_query_builder_dialog_checkbox_text: '今後このダイアログを表示しない', + igx_query_builder_dialog_cancel: 'キャンセル', + igx_query_builder_dialog_confirm: '確認', + igx_query_builder_drop_ghost_text: 'ここにドロップして挿入' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/KO/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/KO/query-builder-resources.ts index 3f1bee4ca3d..fe2e383f9bc 100644 --- a/projects/igniteui-angular-i18n/src/i18n/KO/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/KO/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsKO = { igx_query_builder_date_placeholder: '픽업 날짜', igx_query_builder_time_placeholder: '인도 시간', + igx_query_builder_datetime_placeholder: '날짜 및 시간 선택', igx_query_builder_filter_operator_and: '그리고', igx_query_builder_filter_operator_or: '또는', igx_query_builder_filter_contains: '포함', @@ -17,13 +18,15 @@ export const QueryBuilderResourceStringsKO = { igx_query_builder_filter_empty: '비우기', igx_query_builder_filter_notEmpty: '비우지 않음', igx_query_builder_filter_null: 'Null', - igx_query_builder_filter_notNull: 'Not Null', + igx_query_builder_filter_notNull: 'Null 아님', + igx_query_builder_filter_in: '포함', + igx_query_builder_filter_notIn: '포함 안 함', igx_query_builder_filter_before: '전에', igx_query_builder_filter_after: '후에', - igx_query_builder_filter_at: 'At', - igx_query_builder_filter_not_at: 'Not At', - igx_query_builder_filter_at_before: 'At or Before', - igx_query_builder_filter_at_after: 'At or After', + igx_query_builder_filter_at: '해당', + igx_query_builder_filter_not_at: '해당 아님', + igx_query_builder_filter_at_before: '해당 또는 이전', + igx_query_builder_filter_at_after: '해당 또는 이후', igx_query_builder_filter_today: '오늘', igx_query_builder_filter_yesterday: '어제', igx_query_builder_filter_thisMonth: '이번 달', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsKO = { igx_query_builder_filter_true: '참', igx_query_builder_filter_false: '거짓', igx_query_builder_filter_all: '모두', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: '부터', + igx_query_builder_select_label: '선택', + igx_query_builder_where_label: '선택', igx_query_builder_and_group: '그룹 "그리고"', igx_query_builder_or_group: '그룹 "또는"', igx_query_builder_end_group: '그룹 종료', igx_query_builder_and_label: '그리고', igx_query_builder_or_label: '또는', - igx_query_builder_add_condition: '조건', - igx_query_builder_create_and_group: '그룹 "그리고" 생성', - igx_query_builder_create_or_group: '그룹 "또는" 생성', + igx_query_builder_switch_group: '{0} 으로 전환', + igx_query_builder_add_condition: '생성 조건', + igx_query_builder_add_group: '그룹 생성', + igx_query_builder_add_condition_root: '조건', + igx_query_builder_add_group_root: '그룹', igx_query_builder_ungroup: '그룹 해제', igx_query_builder_delete: '삭제', igx_query_builder_delete_filters: '필터 삭제', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsKO = { igx_query_builder_column_placeholder: '열 선택', igx_query_builder_condition_placeholder: '필터 선택', igx_query_builder_value_placeholder: '값', + igx_query_builder_query_value_placeholder: '하위 쿼리 결과', + igx_query_builder_all_fields: '모든 분야', + igx_query_builder_details: '세부', + igx_query_builder_search: '검색', + igx_query_builder_select_all: '모두 선택', + igx_query_builder_select_entity: '엔터티 선택', + igx_query_builder_select_return_field_single: '반환 필드를 선택', + igx_query_builder_select_return_fields: '반환 필드 선택', + igx_query_builder_dialog_title: '반환 필드 선택', + igx_query_builder_dialog_message: '엔터티를 변경하면 현재 설정이 손실됩니다. 계속하시겠습니까?', + igx_query_builder_dialog_checkbox_text: '이 대화 상자를 다시 표시하지 않기', + igx_query_builder_dialog_cancel: '취소', + igx_query_builder_dialog_confirm: '확인', + igx_query_builder_drop_ghost_text: '삽입하려면 여기에 드롭' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/NB/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/NB/query-builder-resources.ts index 4882eef2fa7..42872b424f2 100644 --- a/projects/igniteui-angular-i18n/src/i18n/NB/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/NB/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsNB = { igx_query_builder_date_placeholder: 'Hentedato', igx_query_builder_time_placeholder: 'Hentetid', + igx_query_builder_datetime_placeholder: 'Velg dato og tid', igx_query_builder_filter_operator_and: 'Og', igx_query_builder_filter_operator_or: 'Eller', igx_query_builder_filter_contains: 'Inneholder', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsNB = { igx_query_builder_filter_notEmpty: 'Ikke tom', igx_query_builder_filter_null: 'Null', igx_query_builder_filter_notNull: 'Ikke null', + igx_query_builder_filter_in: 'I', + igx_query_builder_filter_notIn: 'Ikke i', igx_query_builder_filter_before: 'Før', igx_query_builder_filter_after: 'Etter', igx_query_builder_filter_at: 'På', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsNB = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: 'Alle', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'Fra', + igx_query_builder_select_label: 'Velg', + igx_query_builder_where_label: 'Hvor', igx_query_builder_and_group: '"Og"-gruppe', igx_query_builder_or_group: '"Eller"-gruppe', igx_query_builder_end_group: 'Sluttgruppe', igx_query_builder_and_label: 'og', igx_query_builder_or_label: 'eller', - igx_query_builder_add_condition: 'Tilstand', - igx_query_builder_create_and_group: 'Opprett "Og"-gruppe', - igx_query_builder_create_or_group: 'Opprett "Eller"-gruppe', + igx_query_builder_switch_group: 'Bytt til {0}', + igx_query_builder_add_condition: 'Opprett tilstand', + igx_query_builder_add_group: 'Opprett gruppe', + igx_query_builder_add_condition_root: 'Tilstand', + igx_query_builder_add_group_root: 'Gruppe', igx_query_builder_ungroup: 'Opphev gruppering', igx_query_builder_delete: 'Slett', igx_query_builder_delete_filters: 'Slett filtre', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsNB = { igx_query_builder_column_placeholder: 'Velg kolonne', igx_query_builder_condition_placeholder: 'Velg filter', igx_query_builder_value_placeholder: 'Verdi', + igx_query_builder_query_value_placeholder: 'Delspørringsresultater', + igx_query_builder_all_fields: 'Alle felt', + igx_query_builder_details: 'Detaljer', + igx_query_builder_search: 'Søk', + igx_query_builder_select_all: 'Velg alle', + igx_query_builder_select_entity: 'Velg enhet', + igx_query_builder_select_return_field_single: 'Velg returfelt', + igx_query_builder_select_return_fields: 'Velg returfelter', + igx_query_builder_dialog_title: 'Bekreftelse', + igx_query_builder_dialog_message: 'Ved å endre enheten vil du miste de nåværende innstillingene dine. Er du sikker på at du vil fortsette?', + igx_query_builder_dialog_checkbox_text: 'Ikke vis denne dialogboksen igjen', + igx_query_builder_dialog_cancel: 'Avbryt', + igx_query_builder_dialog_confirm: 'Bekreft', + igx_query_builder_drop_ghost_text: 'Slipp her for å sette inn' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/NL/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/NL/query-builder-resources.ts index 964aee7cba1..502e95e9396 100644 --- a/projects/igniteui-angular-i18n/src/i18n/NL/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/NL/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsNL = { igx_query_builder_date_placeholder: 'Ophaaldatum', igx_query_builder_time_placeholder: 'Ophaaltijd', + igx_query_builder_datetime_placeholder: 'Datum en tijd selecteren', igx_query_builder_filter_operator_and: 'En', igx_query_builder_filter_operator_or: 'Of', igx_query_builder_filter_contains: 'Bevat', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsNL = { igx_query_builder_filter_notEmpty: 'Niet leeg', igx_query_builder_filter_null: 'Null', igx_query_builder_filter_notNull: 'Niet null', + igx_query_builder_filter_in: 'In', + igx_query_builder_filter_notIn: 'Niet In', igx_query_builder_filter_before: 'Voor', igx_query_builder_filter_after: 'Na', igx_query_builder_filter_at: 'Op', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsNL = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: 'Alles', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'Van', + igx_query_builder_select_label: 'Selecteer', + igx_query_builder_where_label: 'Waar', igx_query_builder_and_group: 'En-groep', igx_query_builder_or_group: 'Of-groep', igx_query_builder_end_group: 'Groep beëindigen', igx_query_builder_and_label: 'en', igx_query_builder_or_label: 'of', - igx_query_builder_add_condition: 'Voorwaarde', - igx_query_builder_create_and_group: 'En-groep maken', - igx_query_builder_create_or_group: 'Of-groep maken', + igx_query_builder_switch_group: 'Overschakelen naar {0}', + igx_query_builder_add_condition: 'Voorwaarde maken', + igx_query_builder_add_group: 'Groep maken', + igx_query_builder_add_condition_root: 'Voorwaarde', + igx_query_builder_add_group_root: 'Groep', igx_query_builder_ungroup: 'Groep opheffen', igx_query_builder_delete: 'Verwijderen', igx_query_builder_delete_filters: 'Filters verwijderen', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsNL = { igx_query_builder_column_placeholder: 'Selecteer kolom', igx_query_builder_condition_placeholder: 'Selecteer filter', igx_query_builder_value_placeholder: 'Waarde', + igx_query_builder_query_value_placeholder: 'Subquery-resultaten', + igx_query_builder_all_fields: 'Alle velden', + igx_query_builder_details: 'Details', + igx_query_builder_search: 'Zoeken', + igx_query_builder_select_all: 'Alles selecteren', + igx_query_builder_select_entity: 'Entiteit selecteren', + igx_query_builder_select_return_field_single: 'Selecteer retourveld', + igx_query_builder_select_return_fields: 'Retourvelden selecteren', + igx_query_builder_dialog_title: 'Bevestiging', + igx_query_builder_dialog_message: 'Door de entiteit te wijzigen, verliest u uw huidige instellingen. Weet u zeker dat u wilt doorgaan?', + igx_query_builder_dialog_checkbox_text: 'Deze dialoog niet meer weergeven', + igx_query_builder_dialog_cancel: 'Annuleren', + igx_query_builder_dialog_confirm: 'Bevestigen', + igx_query_builder_drop_ghost_text: 'Zet hier neer om in te voegen' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/PL/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/PL/query-builder-resources.ts index 8fb19457f41..f516972b4a0 100644 --- a/projects/igniteui-angular-i18n/src/i18n/PL/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/PL/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsPL = { igx_query_builder_date_placeholder: 'Data odbioru', igx_query_builder_time_placeholder: 'Godzina odbioru', + igx_query_builder_datetime_placeholder: 'Wybierz datę i godzinę', igx_query_builder_filter_operator_and: 'I', igx_query_builder_filter_operator_or: 'Lub', igx_query_builder_filter_contains: 'Zawiera', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsPL = { igx_query_builder_filter_notEmpty: 'Niepuste', igx_query_builder_filter_null: 'Zero', igx_query_builder_filter_notNull: 'Niezerowe', + igx_query_builder_filter_in: 'W', + igx_query_builder_filter_notIn: 'Nie w', igx_query_builder_filter_before: 'Przed', igx_query_builder_filter_after: 'Po', igx_query_builder_filter_at: 'W', @@ -39,20 +42,38 @@ export const QueryBuilderResourceStringsPL = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: 'Wszystko', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'Od', + igx_query_builder_select_label: 'Wybierz', + igx_query_builder_where_label: 'Gdzie', igx_query_builder_and_group: '"I" grupuj', igx_query_builder_or_group: '"Lub" grupuj', igx_query_builder_end_group: 'Koniec grupy', igx_query_builder_and_label: 'i', igx_query_builder_or_label: 'lub', - igx_query_builder_add_condition: 'Warunek', - igx_query_builder_create_and_group: 'Utwórz "I" grupuj', - igx_query_builder_create_or_group: 'Utwórz "Lub" grupuj', + igx_query_builder_switch_group: 'Przełącz na {0}', + igx_query_builder_add_condition: 'Utwórz Warunek', + igx_query_builder_add_group: 'Utwórz grupuj', + igx_query_builder_add_condition_root: 'Warunek', + igx_query_builder_add_group_root: 'Grupuj', igx_query_builder_ungroup: 'Rozgrupuj', igx_query_builder_delete: 'Usuń', igx_query_builder_delete_filters: 'Usuń filtry', igx_query_builder_initial_text: 'Zacznij od utworzenia grupy warunków połączonych z "I" lub "Lub"', - igx_query_builder_column_placeholder: 'Zaznacz kolumnę', + igx_query_builder_column_placeholder: 'Wybierz kolumnę', igx_query_builder_condition_placeholder: 'Wybierz filtr', igx_query_builder_value_placeholder: 'Wartość', + igx_query_builder_query_value_placeholder: 'Wyniki podzapytania', + igx_query_builder_all_fields: 'Wszystkie pola', + igx_query_builder_details: 'Szczegóły', + igx_query_builder_search: 'Szukaj', + igx_query_builder_select_all: 'Wybierz wszystko', + igx_query_builder_select_entity: 'Wybierz encję', + igx_query_builder_select_return_field_single: 'Wybierz pole zwrotne', + igx_query_builder_select_return_fields: 'Wybierz pola zwrotne', + igx_query_builder_dialog_title: 'Potwierdzenie', + igx_query_builder_dialog_message: 'Zmieniając encję, stracisz swoje aktualne ustawienia. Czy na pewno chcesz to zrobić?', + igx_query_builder_dialog_checkbox_text: 'Nie pokazuj tego okna dialogowego ponownie', + igx_query_builder_dialog_cancel: 'Anuluj', + igx_query_builder_dialog_confirm: 'Potwierdź', + igx_query_builder_drop_ghost_text: 'Upuść tutaj, aby wstawić' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/PT/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/PT/query-builder-resources.ts index 3a2ab2d8f0d..f9abdc41157 100644 --- a/projects/igniteui-angular-i18n/src/i18n/PT/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/PT/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsPT = { igx_query_builder_date_placeholder: 'Data de recolha', igx_query_builder_time_placeholder: 'Hora do levantamento', + igx_query_builder_datetime_placeholder: 'Selecionar data e hora', igx_query_builder_filter_operator_and: 'E', igx_query_builder_filter_operator_or: 'Ou', igx_query_builder_filter_contains: 'Contém', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsPT = { igx_query_builder_filter_notEmpty: 'Não vazio', igx_query_builder_filter_null: 'Nulo', igx_query_builder_filter_notNull: 'Não nulo', + igx_query_builder_filter_in: 'Em', + igx_query_builder_filter_notIn: 'Não em', igx_query_builder_filter_before: 'Antes', igx_query_builder_filter_after: 'Após', igx_query_builder_filter_at: 'Em', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsPT = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: 'Todos', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'De', + igx_query_builder_select_label: 'Selecionar', + igx_query_builder_where_label: 'Onde', igx_query_builder_and_group: '"E" grupo', igx_query_builder_or_group: '"Ou" grupo', igx_query_builder_end_group: 'Terminar grupo', igx_query_builder_and_label: 'e', igx_query_builder_or_label: 'ou', - igx_query_builder_add_condition: 'Condição', - igx_query_builder_create_and_group: 'Criar grupo "E"', - igx_query_builder_create_or_group: 'Criar grupo "Ou"', + igx_query_builder_switch_group: 'Mudar para {0}', + igx_query_builder_add_condition: 'Add condição', + igx_query_builder_add_group: 'Criar grupo', + igx_query_builder_add_condition_root: 'Condição', + igx_query_builder_add_group_root: 'Grupo', igx_query_builder_ungroup: 'Desagrupar', igx_query_builder_delete: 'Eliminar', igx_query_builder_delete_filters: 'Eliminar filtros', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsPT = { igx_query_builder_column_placeholder: 'Selecionar coluna', igx_query_builder_condition_placeholder: 'Selecionar filtro', igx_query_builder_value_placeholder: 'Valor', + igx_query_builder_query_value_placeholder: 'Resultados da subconsulta', + igx_query_builder_all_fields: 'Todos os campos', + igx_query_builder_details: 'Detalhes', + igx_query_builder_search: 'Pesquisar', + igx_query_builder_select_all: 'Selecionar tudo', + igx_query_builder_select_entity: 'Selecionar entidade', + igx_query_builder_select_return_field_single: 'Selecione o campo de retorno', + igx_query_builder_select_return_fields: 'Selecionar campos de retorno', + igx_query_builder_dialog_title: 'Confirmação', + igx_query_builder_dialog_message: 'Ao alterar a entidade, você perderá suas configurações atuais. Tem a certeza que pretende continuar?', + igx_query_builder_dialog_checkbox_text: 'Não voltar a mostrar esta caixa de diálogo', + igx_query_builder_dialog_cancel: 'Cancelar', + igx_query_builder_dialog_confirm: 'Confirmar', + igx_query_builder_drop_ghost_text: 'Largar aqui para inserir' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/RO/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/RO/query-builder-resources.ts index fee9a9a6abd..2cd80af352b 100644 --- a/projects/igniteui-angular-i18n/src/i18n/RO/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/RO/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsRO = { igx_query_builder_date_placeholder: 'Data ridicării', igx_query_builder_time_placeholder: 'Ora preluării', + igx_query_builder_datetime_placeholder: 'Selectează data și ora', igx_query_builder_filter_operator_and: 'Și', igx_query_builder_filter_operator_or: 'Sau', igx_query_builder_filter_contains: 'Conține', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsRO = { igx_query_builder_filter_notEmpty: 'Nu gol', igx_query_builder_filter_null: 'Nul', igx_query_builder_filter_notNull: 'Nu nul', + igx_query_builder_filter_in: 'În', + igx_query_builder_filter_notIn: 'Nu în', igx_query_builder_filter_before: 'Înainte de', igx_query_builder_filter_after: 'După', igx_query_builder_filter_at: 'La', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsRO = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: 'Toate', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'Din', + igx_query_builder_select_label: 'Selectează', + igx_query_builder_where_label: 'Unde', igx_query_builder_and_group: '"Și" Grup', igx_query_builder_or_group: '"Sau" grup', igx_query_builder_end_group: 'Sfârșitul grupului', igx_query_builder_and_label: 'și', igx_query_builder_or_label: 'sau', - igx_query_builder_add_condition: 'Condiție', - igx_query_builder_create_and_group: 'Creați grupul "Și"', - igx_query_builder_create_or_group: 'Creați un grup "Sau"', + igx_query_builder_switch_group: 'Comută la {0}', + igx_query_builder_add_condition: 'Creați condiție', + igx_query_builder_add_group: 'Creați grupul', + igx_query_builder_add_condition_root: 'Condiție', + igx_query_builder_add_group_root: 'Grupul', igx_query_builder_ungroup: 'Anulează grupare', igx_query_builder_delete: 'Șterge', igx_query_builder_delete_filters: 'Ștergeți filtrele', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsRO = { igx_query_builder_column_placeholder: 'Selectați coloana', igx_query_builder_condition_placeholder: 'Selectați filtrul', igx_query_builder_value_placeholder: 'Valoare', + igx_query_builder_query_value_placeholder: 'Rezultatele subinterogării', + igx_query_builder_all_fields: 'Toate câmpurile', + igx_query_builder_details: 'Detalii', + igx_query_builder_search: 'Căutare', + igx_query_builder_select_all: 'Selectează tot', + igx_query_builder_select_entity: 'Selectează entitate', + igx_query_builder_select_return_field_single: 'Selectați câmpul de returnare', + igx_query_builder_select_return_fields: 'Selectează câmpuri de returnare', + igx_query_builder_dialog_title: 'Confirmare', + igx_query_builder_dialog_message: 'Prin modificarea entității, veți pierde setările curente. Ești sigur că vrei să faci asta?', + igx_query_builder_dialog_checkbox_text: 'Nu se mai afișează această casetă de dialog', + igx_query_builder_dialog_cancel: 'Anulare', + igx_query_builder_dialog_confirm: 'Confirmare', + igx_query_builder_drop_ghost_text: 'Aruncaţi aici pentru a introduce' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/SV/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/SV/query-builder-resources.ts index 055f491c3a2..e9e32f57f25 100644 --- a/projects/igniteui-angular-i18n/src/i18n/SV/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/SV/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsSV = { igx_query_builder_date_placeholder: 'Upphämtningsdatum', igx_query_builder_time_placeholder: 'Upphämtningstid', + igx_query_builder_datetime_placeholder: 'Välj datum och tid', igx_query_builder_filter_operator_and: 'Och', igx_query_builder_filter_operator_or: 'Eller', igx_query_builder_filter_contains: 'Innehåller', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsSV = { igx_query_builder_filter_notEmpty: 'Inte tom', igx_query_builder_filter_null: 'Null', igx_query_builder_filter_notNull: 'Inte null', + igx_query_builder_filter_in: 'I', + igx_query_builder_filter_notIn: 'Inte i', igx_query_builder_filter_before: 'Innan', igx_query_builder_filter_after: 'Efter', igx_query_builder_filter_at: 'Vid', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsSV = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: 'Allt', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'Från', + igx_query_builder_select_label: 'Välj', + igx_query_builder_where_label: 'Där', igx_query_builder_and_group: '"Och" -grupp', igx_query_builder_or_group: '"Eller" -grupp', igx_query_builder_end_group: 'Slutgrupp', igx_query_builder_and_label: 'och', igx_query_builder_or_label: 'eller', - igx_query_builder_add_condition: 'Villkor', - igx_query_builder_create_and_group: 'Skapa "Och" -grupp', - igx_query_builder_create_or_group: 'Skapa "Eller" -grupp', + igx_query_builder_switch_group: 'Byt till {0}', + igx_query_builder_add_condition: 'Skapa villkor', + igx_query_builder_add_group: 'Skapa grupp', + igx_query_builder_add_condition_root: 'Villkor', + igx_query_builder_add_group_root: 'Group', igx_query_builder_ungroup: 'Avgruppera', igx_query_builder_delete: 'Radera', igx_query_builder_delete_filters: 'Ta bort filter', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsSV = { igx_query_builder_column_placeholder: 'Välj kolumn', igx_query_builder_condition_placeholder: 'Välj filter', igx_query_builder_value_placeholder: 'Värde', + igx_query_builder_query_value_placeholder: 'Underfrågeresultat', + igx_query_builder_all_fields: 'Alla fält', + igx_query_builder_details: 'Detaljer', + igx_query_builder_search: 'Sök', + igx_query_builder_select_all: 'Välj alla', + igx_query_builder_select_entity: 'Välj enhet', + igx_query_builder_select_return_field_single: 'Välj returfält', + igx_query_builder_select_return_fields: 'Välj returfält', + igx_query_builder_dialog_title: 'Bekräftelse', + igx_query_builder_dialog_message: 'Genom att ändra entitet förlorar du dina nuvarande inställningar. Vill du fortsätta?', + igx_query_builder_dialog_checkbox_text: 'Visa inte den här dialogrutan igen', + igx_query_builder_dialog_cancel: 'Avbryt', + igx_query_builder_dialog_confirm: 'Bekräfta', + igx_query_builder_drop_ghost_text: 'Släpp här för att infoga' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/TR/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/TR/query-builder-resources.ts index b948b1e525f..055476f0707 100644 --- a/projects/igniteui-angular-i18n/src/i18n/TR/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/TR/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsTR = { igx_query_builder_date_placeholder: 'Alma tarihi', igx_query_builder_time_placeholder: 'Alma saati', + igx_query_builder_datetime_placeholder: 'Tarih ve saat seç', igx_query_builder_filter_operator_and: 'Ve', igx_query_builder_filter_operator_or: 'Veya', igx_query_builder_filter_contains: 'İçerir', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsTR = { igx_query_builder_filter_notEmpty: 'Boş değil', igx_query_builder_filter_null: 'Geçersiz', igx_query_builder_filter_notNull: 'Geçersiz değil', + igx_query_builder_filter_in: 'İçinde', + igx_query_builder_filter_notIn: 'İçinde değil', igx_query_builder_filter_before: 'Önce', igx_query_builder_filter_after: 'Sonra', igx_query_builder_filter_at: 'Şu zaman', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsTR = { igx_query_builder_filter_true: 'Doğru', igx_query_builder_filter_false: 'Yanlış', igx_query_builder_filter_all: 'Tümü', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: 'Başlangıç', + igx_query_builder_select_label: 'Seç', + igx_query_builder_where_label: 'Nerede', igx_query_builder_and_group: '"Ve" Grubu', igx_query_builder_or_group: '"Veya" Grubu', igx_query_builder_end_group: 'Bitiş Grubu', igx_query_builder_and_label: 've', igx_query_builder_or_label: 'veya', - igx_query_builder_add_condition: 'Koşul', - igx_query_builder_create_and_group: '"Ve" Grubu Oluştur', - igx_query_builder_create_or_group: '"Veya" Grubu Oluştur', + igx_query_builder_switch_group: 'Şura geç: {0}', + igx_query_builder_add_condition: 'Koşul oluştur', + igx_query_builder_add_group: 'Grubu oluştur', + igx_query_builder_add_condition_root: 'Koşul', + igx_query_builder_add_group_root: 'Grubu', igx_query_builder_ungroup: 'Grubu çöz', igx_query_builder_delete: 'Sil', igx_query_builder_delete_filters: 'Filtreleri sil', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsTR = { igx_query_builder_column_placeholder: 'Sütun seç', igx_query_builder_condition_placeholder: 'Filtre seç', igx_query_builder_value_placeholder: 'Değer', + igx_query_builder_query_value_placeholder: 'Alt sorgu sonuçları', + igx_query_builder_all_fields: 'Tüm alanlar', + igx_query_builder_details: 'Detaylar', + igx_query_builder_search: 'Arama', + igx_query_builder_select_all: 'Tümünü seç', + igx_query_builder_select_entity: 'Varlık seç', + igx_query_builder_select_return_field_single: 'Dönüş alanını seçin', + igx_query_builder_select_return_fields: 'Dönüş alanlarını seç', + igx_query_builder_dialog_title: 'Onay', + igx_query_builder_dialog_message: 'Varlığı değiştirdiğinizde mevcut ayarlarınızı kaybedersiniz. Devam etmek istiyor musunuz?', + igx_query_builder_dialog_checkbox_text: 'Bu iletişim kutusunu bir daha gösterme', + igx_query_builder_dialog_cancel: 'İptal', + igx_query_builder_dialog_confirm: 'Onayla', + igx_query_builder_drop_ghost_text: 'Eklemek için buraya bırakın' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/ZH-HANS/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/ZH-HANS/query-builder-resources.ts index 56351ad6ee0..38a6fac41ea 100644 --- a/projects/igniteui-angular-i18n/src/i18n/ZH-HANS/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/ZH-HANS/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsZHHANS = { igx_query_builder_date_placeholder: '选择日期', igx_query_builder_time_placeholder: '取车时间', + igx_query_builder_datetime_placeholder: '选择日期和时间', igx_query_builder_filter_operator_and: '和', igx_query_builder_filter_operator_or: '或', igx_query_builder_filter_contains: '包含', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsZHHANS = { igx_query_builder_filter_notEmpty: '非空', igx_query_builder_filter_null: 'Null', igx_query_builder_filter_notNull: '非 Null', + igx_query_builder_filter_in: '在', + igx_query_builder_filter_notIn: '不在', igx_query_builder_filter_before: '之前', igx_query_builder_filter_after: '之后', igx_query_builder_filter_at: '在', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsZHHANS = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: '全部', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: '从', + igx_query_builder_select_label: '选择', + igx_query_builder_where_label: '在哪里', igx_query_builder_and_group: '"And" 组', igx_query_builder_or_group: '"Or" 组', igx_query_builder_end_group: '结束组', igx_query_builder_and_label: '和', igx_query_builder_or_label: '或', - igx_query_builder_add_condition: '条件', - igx_query_builder_create_and_group: '创建 "And" 组', - igx_query_builder_create_or_group: '创建 "Or" 组', + igx_query_builder_switch_group: '切换至 {0}', + igx_query_builder_add_condition: '创建 条件', + igx_query_builder_add_group: '创建 组', + igx_query_builder_add_condition_root: '条件', + igx_query_builder_add_group_root: '组', igx_query_builder_ungroup: '取消分组', igx_query_builder_delete: '删除', igx_query_builder_delete_filters: '删除筛选器', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsZHHANS = { igx_query_builder_column_placeholder: '选择列', igx_query_builder_condition_placeholder: '选择筛选器', igx_query_builder_value_placeholder: '数值', + igx_query_builder_query_value_placeholder: '子查询结果', + igx_query_builder_all_fields: '所有字段', + igx_query_builder_details: '详细信息', + igx_query_builder_search: '搜索', + igx_query_builder_select_all: '全选', + igx_query_builder_select_entity: '选择实体', + igx_query_builder_select_return_field_single: '选择返回字段', + igx_query_builder_select_return_fields: '选择返回字段', + igx_query_builder_dialog_title: '确认', + igx_query_builder_dialog_message: '通过更改实体,您将丢失当前设置。确定要继续?', + igx_query_builder_dialog_checkbox_text: '不再显示此对话框', + igx_query_builder_dialog_cancel: '取消', + igx_query_builder_dialog_confirm: '确认', + igx_query_builder_drop_ghost_text: '拖放此处以插入' } satisfies MakeRequired; diff --git a/projects/igniteui-angular-i18n/src/i18n/ZH-HANT/query-builder-resources.ts b/projects/igniteui-angular-i18n/src/i18n/ZH-HANT/query-builder-resources.ts index 9cc1924bfff..0c5c5d0d080 100644 --- a/projects/igniteui-angular-i18n/src/i18n/ZH-HANT/query-builder-resources.ts +++ b/projects/igniteui-angular-i18n/src/i18n/ZH-HANT/query-builder-resources.ts @@ -6,6 +6,7 @@ import { IQueryBuilderResourceStrings } from 'igniteui-angular'; export const QueryBuilderResourceStringsZHHANT = { igx_query_builder_date_placeholder: '領取日期', igx_query_builder_time_placeholder: '取車時間', + igx_query_builder_datetime_placeholder: '選取日期和時間', igx_query_builder_filter_operator_and: '和', igx_query_builder_filter_operator_or: '或', igx_query_builder_filter_contains: '包含', @@ -18,6 +19,8 @@ export const QueryBuilderResourceStringsZHHANT = { igx_query_builder_filter_notEmpty: '不是空的', igx_query_builder_filter_null: 'Null', igx_query_builder_filter_notNull: '非 Null', + igx_query_builder_filter_in: '在', + igx_query_builder_filter_notIn: '不在', igx_query_builder_filter_before: '之前', igx_query_builder_filter_after: '之後', igx_query_builder_filter_at: '在', @@ -39,15 +42,19 @@ export const QueryBuilderResourceStringsZHHANT = { igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', igx_query_builder_filter_all: '全部', - igx_query_builder_title: 'Query Builder', + igx_query_builder_from_label: '從', + igx_query_builder_select_label: '選擇', + igx_query_builder_where_label: '在哪裡', igx_query_builder_and_group: '“And” 群組', igx_query_builder_or_group: '“Or” 群組', igx_query_builder_end_group: '結束群組', igx_query_builder_and_label: '和', igx_query_builder_or_label: '或', - igx_query_builder_add_condition: '條件', - igx_query_builder_create_and_group: '建立 "And" 群組', - igx_query_builder_create_or_group: '建立 "Or" 群組', + igx_query_builder_switch_group: '切換到 {0}', + igx_query_builder_add_condition: '建立 條件', + igx_query_builder_add_group: '建立 群組', + igx_query_builder_add_condition_root: '條件', + igx_query_builder_add_group_root: '群組', igx_query_builder_ungroup: '取消分組', igx_query_builder_delete: '刪除', igx_query_builder_delete_filters: '刪除篩選條件', @@ -55,4 +62,18 @@ export const QueryBuilderResourceStringsZHHANT = { igx_query_builder_column_placeholder: '選擇列', igx_query_builder_condition_placeholder: '選擇篩選條件', igx_query_builder_value_placeholder: '數值', + igx_query_builder_query_value_placeholder: '子查詢結果', + igx_query_builder_all_fields: '所有領域', + igx_query_builder_details: '詳細資訊', + igx_query_builder_search: '搜尋', + igx_query_builder_select_all: '全選', + igx_query_builder_select_entity: '選取實體', + igx_query_builder_select_return_field_single: '選擇返回欄位', + igx_query_builder_select_return_fields: '選取返回欄位', + igx_query_builder_dialog_title: '確認', + igx_query_builder_dialog_message: '透過變更實體,您將遺失目前設定。確定要繼續?', + igx_query_builder_dialog_checkbox_text: '不要再顯示這個對話方塊', + igx_query_builder_dialog_cancel: '取消', + igx_query_builder_dialog_confirm: '確認', + igx_query_builder_drop_ghost_text: '拖放至此處插入' } satisfies MakeRequired; diff --git a/projects/igniteui-angular/migrations/update-19_1_0/changes/inputs.json b/projects/igniteui-angular/migrations/update-19_1_0/changes/inputs.json new file mode 100644 index 00000000000..04f936ea617 --- /dev/null +++ b/projects/igniteui-angular/migrations/update-19_1_0/changes/inputs.json @@ -0,0 +1,30 @@ +{ + "$schema": "../../common/schema/binding.schema.json", + "changes": [ + { + "name": "fields", + "replaceWith": "entities", + "valueTransform": "fields_to_entities", + "owner": { + "selector": "igx-query-builder", + "type": "component" + } + }, + { + "name": "showLegend", + "remove": true, + "owner": { + "selector": "igx-query-builder-header", + "type": "component" + } + }, + { + "name": "resourceStrings", + "remove": true, + "owner": { + "selector": "igx-query-builder-header", + "type": "component" + } + } + ] +} diff --git a/projects/igniteui-angular/migrations/update-19_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-19_1_0/index.spec.ts index ff1c4c6cb06..2c205d02c54 100644 --- a/projects/igniteui-angular/migrations/update-19_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-19_1_0/index.spec.ts @@ -58,4 +58,65 @@ describe(`Update to ${version}`, () => { );` ); }); + + it('should replace Query Builder deprecated property `fields` with `entities`', async () => { + appTree.create(`/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( + ` + + ` + ); + }); + + it('should remove Query Builder Header deprecated `showLegend` and `resourceStrings` properties', async () => { + appTree.create(`/testSrc/appPrefix/component/test.component.html`, + ` + + ` + ); + + const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( + ` + + ` + ); + }); + + it('should remove igx_query_builder_title from resources ', async () => { + appTree.create(`/testSrc/appPrefix/component/test.component.ts`, + ` + export class TestComponent { + public resourceStrings = { + igx_query_builder_add_condition: '+ Add Condition', + igx_query_builder_title: 'Query Builder Title', + igx_query_builder_add_group: '+ Add Group', + igx_query_builder_create_and_group: 'My create and group', + igx_query_builder_create_or_group: 'My create or group' + }; + } + ` + ); + + const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual( + ` + export class TestComponent { + public resourceStrings = { + igx_query_builder_add_condition: '+ Add Condition', + igx_query_builder_add_group: '+ Add Group' + }; + } + ` + ); + }); }); diff --git a/projects/igniteui-angular/migrations/update-19_1_0/index.ts b/projects/igniteui-angular/migrations/update-19_1_0/index.ts index a68173f3b55..0449798742c 100644 --- a/projects/igniteui-angular/migrations/update-19_1_0/index.ts +++ b/projects/igniteui-angular/migrations/update-19_1_0/index.ts @@ -3,12 +3,32 @@ import type { SchematicContext, Tree } from '@angular-devkit/schematics'; -import { UpdateChanges } from '../common/UpdateChanges'; +import { BoundPropertyObject, InputPropertyType, UpdateChanges } from '../common/UpdateChanges'; const version = '19.1.0'; export default (): Rule => async (host: Tree, context: SchematicContext) => { context.logger.info(`Applying migration for Ignite UI for Angular to version ${version}`); const update = new UpdateChanges(__dirname, host, context); + + update.addValueTransform('fields_to_entities', (args: BoundPropertyObject): void => { + args.bindingType = InputPropertyType.EVAL; + args.value = `[{ name: '', fields: ${args.value}}]`; + }); + + // remove igx_query_builder_title, igx_query_builder_create_and_group, igx_query_builder_create_or_group from resources + const removedRS = ['igx_query_builder_title', 'igx_query_builder_create_and_group', 'igx_query_builder_create_or_group']; + for (const entryPath of update.tsFiles) { + let content = host.read(entryPath).toString(); + for (const rs of removedRS) { + const regex = new RegExp(String.raw`,?\s*${rs}\s*:\s*'[^']*'`, 'g'); + + if (regex.test(content)) { + content = content.replace(regex, ''); + host.overwrite(entryPath, content); + } + } + } + update.applyChanges(); }; diff --git a/projects/igniteui-angular/package.json b/projects/igniteui-angular/package.json index 4c334e37943..fc8fd3df4f0 100644 --- a/projects/igniteui-angular/package.json +++ b/projects/igniteui-angular/package.json @@ -73,7 +73,7 @@ "tslib": "^2.3.0", "igniteui-trial-watermark": "^3.0.2", "lodash-es": "^4.17.21", - "igniteui-theming": "^14.3.1", + "igniteui-theming": "^15.0.0", "@igniteui/material-icons-extended": "^3.1.0" }, "peerDependencies": { diff --git a/projects/igniteui-angular/src/lib/accordion/accordion.component.spec.ts b/projects/igniteui-angular/src/lib/accordion/accordion.component.spec.ts index 9589affe459..0e3a5a85b6b 100644 --- a/projects/igniteui-angular/src/lib/accordion/accordion.component.spec.ts +++ b/projects/igniteui-angular/src/lib/accordion/accordion.component.spec.ts @@ -1,5 +1,4 @@ import { useAnimation } from '@angular/animations'; -import { NgIf } from '@angular/common'; import { Component, ViewChild } from '@angular/core'; import { waitForAsync, TestBed, fakeAsync, ComponentFixture, tick } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; @@ -401,10 +400,12 @@ describe('Rendering Tests', () => { -
+ @if (divChild) { +
+ } `, - imports: [IgxAccordionComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelBodyComponent, IgxExpansionPanelTitleDirective, NgIf] + imports: [IgxAccordionComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelBodyComponent, IgxExpansionPanelTitleDirective] }) export class IgxAccordionSampleTestComponent { @ViewChild(IgxAccordionComponent) public accordion: IgxAccordionComponent; diff --git a/projects/igniteui-angular/src/lib/action-strip/action-strip.component.html b/projects/igniteui-angular/src/lib/action-strip/action-strip.component.html index 6369fb0bcb1..65566b3f7aa 100644 --- a/projects/igniteui-angular/src/lib/action-strip/action-strip.component.html +++ b/projects/igniteui-angular/src/lib/action-strip/action-strip.component.html @@ -1,6 +1,6 @@
- + @if (menuItems.length > 0) { - + } - -
- -
-
+ @for (item of menuItems; track trackMenuItem(item)) { + +
+ +
+
+ }
diff --git a/projects/igniteui-angular/src/lib/action-strip/action-strip.component.ts b/projects/igniteui-angular/src/lib/action-strip/action-strip.component.ts index d4a2a56f4eb..56bfdf2c6f4 100644 --- a/projects/igniteui-angular/src/lib/action-strip/action-strip.component.ts +++ b/projects/igniteui-angular/src/lib/action-strip/action-strip.component.ts @@ -24,10 +24,11 @@ import { IgxIconComponent } from '../icon/icon.component'; import { IgxDropDownItemNavigationDirective } from '../drop-down/drop-down-navigation.directive'; import { IgxToggleActionDirective } from '../directives/toggle/toggle.directive'; import { IgxRippleDirective } from '../directives/ripple/ripple.directive'; -import { NgIf, NgFor, NgTemplateOutlet } from '@angular/common'; +import { NgTemplateOutlet } from '@angular/common'; import { getCurrentResourceStrings } from '../core/i18n/resources'; import { IgxIconButtonDirective } from '../directives/button/icon-button.directive'; import { IgxActionStripToken } from './token'; +import { trackByIdentity } from '../core/utils'; @Directive({ selector: '[igxActionStripMenuItem]', @@ -73,8 +74,6 @@ export class IgxActionStripMenuItemDirective { selector: 'igx-action-strip', templateUrl: 'action-strip.component.html', imports: [ - NgIf, - NgFor, NgTemplateOutlet, IgxIconButtonDirective, IgxRippleDirective, @@ -314,6 +313,9 @@ export class IgxActionStripComponent implements IgxActionStripToken, AfterConten } } + /** pin swapping w/ unpin resets the menuItems collection */ + protected trackMenuItem = trackByIdentity; + /** * Close the menu if opened * diff --git a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-action-button.component.html b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-action-button.component.html index 6cd2a12345e..6eafb5e80b0 100644 --- a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-action-button.component.html +++ b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-action-button.component.html @@ -1,16 +1,24 @@ - +@if (!asMenuItem) { - +} - + @if (asMenuItem) {
- {{iconName}} - {{iconName}} + @if (iconSet) { + {{iconName}} + } + @if (!iconSet) { + {{iconName}} + }
-
+ }
diff --git a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-action-button.component.ts b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-action-button.component.ts index 545b9065410..64771bd15f4 100644 --- a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-action-button.component.ts +++ b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-action-button.component.ts @@ -1,7 +1,6 @@ import { Component, Input, TemplateRef, ViewChild, Output, EventEmitter, ElementRef, booleanAttribute } from '@angular/core'; import { IgxIconComponent } from '../../icon/icon.component'; import { IgxRippleDirective } from '../../directives/ripple/ripple.directive'; -import { NgIf } from '@angular/common'; import { IgxIconButtonDirective } from '../../directives/button/icon-button.directive'; /* blazorElement */ @@ -10,7 +9,7 @@ import { IgxIconButtonDirective } from '../../directives/button/icon-button.dire @Component({ selector: 'igx-grid-action-button', templateUrl: 'grid-action-button.component.html', - imports: [NgIf, IgxRippleDirective, IgxIconComponent, IgxIconButtonDirective] + imports: [IgxRippleDirective, IgxIconComponent, IgxIconButtonDirective] }) export class IgxGridActionButtonComponent { diff --git a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.html b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.html index 0448b22086f..b68cf39486d 100644 --- a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.html +++ b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.html @@ -1,8 +1,16 @@ - - - - - - +@if (isRowContext) { + @if (!disabled && editRow) { + + } + @if (addRow && isRootRow) { + + } + @if (addChild && hasChildren) { + + } + @if (!disabled && deleteRow) { + + } +} diff --git a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts index d763d414e6e..1abfd40b3b6 100644 --- a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts +++ b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts @@ -1,7 +1,6 @@ import { Component, ViewChild, OnInit } from '@angular/core'; import { TestBed, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { NgFor } from '@angular/common'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { configureTestSuite } from '../../test-utils/configure-suite'; @@ -391,16 +390,18 @@ describe('igxGridEditingActions #grid ', () => { template: ` - - + @for (c of columns; track c) { + + + } `, - imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridEditingActionsComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridEditingActionsComponent] }) class IgxActionStripTestingComponent implements OnInit { @ViewChild('actionStrip', { read: IgxActionStripComponent, static: true }) @@ -468,9 +469,11 @@ class IgxActionStripTestingComponent implements OnInit { template: ` - - + @for (c of columns; track c) { + + + } @@ -479,7 +482,7 @@ class IgxActionStripTestingComponent implements OnInit { `, selector: 'igx-action-strip-pin-edit-component', - imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent, IgxGridEditingActionsComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent, IgxGridEditingActionsComponent] }) class IgxActionStripPinEditComponent extends IgxActionStripTestingComponent { } @@ -488,9 +491,11 @@ class IgxActionStripPinEditComponent extends IgxActionStripTestingComponent { template: ` - - + @for (c of columns; track c) { + + + } @@ -498,7 +503,7 @@ class IgxActionStripPinEditComponent extends IgxActionStripTestingComponent { `, selector: 'igx-action-strip-edit-menu-component', - imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridEditingActionsComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridEditingActionsComponent] }) class IgxActionStripEditMenuComponent extends IgxActionStripTestingComponent { } @@ -507,9 +512,11 @@ class IgxActionStripEditMenuComponent extends IgxActionStripTestingComponent { template: ` - - + @for (c of columns; track c) { + + + } @@ -518,7 +525,7 @@ class IgxActionStripEditMenuComponent extends IgxActionStripTestingComponent { `, selector: 'igx-action-strip-one-row-component', - imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridEditingActionsComponent, IgxGridPinningActionsComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridEditingActionsComponent, IgxGridPinningActionsComponent] }) class IgxActionStripOneRowComponent extends IgxActionStripTestingComponent { } @@ -527,9 +534,11 @@ class IgxActionStripOneRowComponent extends IgxActionStripTestingComponent { template: ` - - + @for (c of columns; track c) { + + + } @@ -537,7 +546,7 @@ class IgxActionStripOneRowComponent extends IgxActionStripTestingComponent { `, selector: 'igx-action-strip-menu-one-row-component', - imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridEditingActionsComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridEditingActionsComponent] }) class IgxActionStripMenuOneRowComponent extends IgxActionStripTestingComponent { } diff --git a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.ts b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.ts index 61f5fa39544..e48ec8745f2 100644 --- a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.ts +++ b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.ts @@ -3,7 +3,6 @@ import { IgxGridActionsBaseDirective } from './grid-actions-base.directive'; import { showMessage } from '../../core/utils'; import { addRow, addChild } from '@igniteui/material-icons-extended'; import { IgxGridActionButtonComponent } from './grid-action-button.component'; -import { NgIf } from '@angular/common'; /* blazorElement */ @@ -19,7 +18,7 @@ import { NgIf } from '@angular/common'; selector: 'igx-grid-editing-actions', templateUrl: 'grid-editing-actions.component.html', providers: [{ provide: IgxGridActionsBaseDirective, useExisting: IgxGridEditingActionsComponent }], - imports: [NgIf, IgxGridActionButtonComponent] + imports: [IgxGridActionButtonComponent] }) export class IgxGridEditingActionsComponent extends IgxGridActionsBaseDirective { diff --git a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.html b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.html index 139553d1444..bdfde5466cb 100644 --- a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.html +++ b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.html @@ -1,6 +1,14 @@ - - - - - - +@if (isRowContext) { + @if (inPinnedArea && pinnedTop) { + + } + @if (inPinnedArea && !pinnedTop) { + + } + @if (!pinned) { + + } + @if (pinned) { + + } +} diff --git a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.spec.ts b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.spec.ts index f33e55996e9..2d9efab5b96 100644 --- a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.spec.ts +++ b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.spec.ts @@ -7,7 +7,6 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { By } from '@angular/platform-browser'; import { wait } from '../../test-utils/ui-interactions.spec'; import { IgxGridPinningActionsComponent } from './grid-pinning-actions.component'; -import { NgFor } from '@angular/common'; import { IgxColumnComponent } from '../../grids/public_api'; @@ -103,16 +102,18 @@ describe('igxGridPinningActions #grid ', () => { template: ` - - + @for (c of columns; track c) { + + + } `, - imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent] }) class IgxActionStripTestingComponent implements OnInit { @ViewChild('actionStrip', { read: IgxActionStripComponent, static: true }) @@ -175,16 +176,18 @@ class IgxActionStripTestingComponent implements OnInit { template: ` - - + @for (c of columns; track c) { + + + } `, - imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent] }) class IgxActionStripPinMenuComponent extends IgxActionStripTestingComponent { } diff --git a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.ts b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.ts index 6bee97ae647..86c19ba569d 100644 --- a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.ts +++ b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-pinning-actions.component.ts @@ -2,7 +2,6 @@ import { Component, HostBinding } from '@angular/core'; import { IgxGridActionsBaseDirective } from './grid-actions-base.directive'; import { pinLeft, unpinLeft, jumpDown, jumpUp } from '@igniteui/material-icons-extended'; import { IgxGridActionButtonComponent } from './grid-action-button.component'; -import { NgIf } from '@angular/common'; /* blazorElement */ /* wcElementTag: igc-grid-pinning-actions */ @@ -17,7 +16,7 @@ import { NgIf } from '@angular/common'; selector: 'igx-grid-pinning-actions', templateUrl: 'grid-pinning-actions.component.html', providers: [{ provide: IgxGridActionsBaseDirective, useExisting: IgxGridPinningActionsComponent }], - imports: [NgIf, IgxGridActionButtonComponent] + imports: [IgxGridActionButtonComponent] }) export class IgxGridPinningActionsComponent extends IgxGridActionsBaseDirective { diff --git a/projects/igniteui-angular/src/lib/badge/badge.component.html b/projects/igniteui-angular/src/lib/badge/badge.component.html index 57461614232..14451e6100d 100644 --- a/projects/igniteui-angular/src/lib/badge/badge.component.html +++ b/projects/igniteui-angular/src/lib/badge/badge.component.html @@ -1,4 +1,10 @@ -{{value}} -{{icon}} -{{icon}} +@if (value || value === 0 && !icon) { + {{value}} +} +@if (icon && !iconSet) { + {{icon}} +} +@if (icon && iconSet) { + {{icon}} +} diff --git a/projects/igniteui-angular/src/lib/badge/badge.component.ts b/projects/igniteui-angular/src/lib/badge/badge.component.ts index 5275adb98f9..a891c1fcc85 100644 --- a/projects/igniteui-angular/src/lib/badge/badge.component.ts +++ b/projects/igniteui-angular/src/lib/badge/badge.component.ts @@ -1,4 +1,3 @@ -import { NgIf } from '@angular/common'; import { booleanAttribute, Component, HostBinding, Input } from '@angular/core'; import { mkenum } from '../core/utils'; import { IgxIconComponent } from '../icon/icon.component'; @@ -41,7 +40,7 @@ export type IgxBadgeType = (typeof IgxBadgeType)[keyof typeof IgxBadgeType]; @Component({ selector: 'igx-badge', templateUrl: 'badge.component.html', - imports: [NgIf, IgxIconComponent] + imports: [IgxIconComponent] }) export class IgxBadgeComponent { diff --git a/projects/igniteui-angular/src/lib/banner/banner.component.html b/projects/igniteui-angular/src/lib/banner/banner.component.html index c49ac46f2da..d8cf0bb0adf 100644 --- a/projects/igniteui-angular/src/lib/banner/banner.component.html +++ b/projects/igniteui-angular/src/lib/banner/banner.component.html @@ -3,22 +3,23 @@
-
- -
+ @if (bannerIcon) { +
+ +
+ }
- + @if (useDefaultTemplate) { - - + } @else { - + }
diff --git a/projects/igniteui-angular/src/lib/banner/banner.component.ts b/projects/igniteui-angular/src/lib/banner/banner.component.ts index 08fc743b568..b6055d350a1 100644 --- a/projects/igniteui-angular/src/lib/banner/banner.component.ts +++ b/projects/igniteui-angular/src/lib/banner/banner.component.ts @@ -14,7 +14,6 @@ import { IToggleView } from '../core/navigation'; import { IgxButtonDirective } from '../directives/button/button.directive'; import { IgxRippleDirective } from '../directives/ripple/ripple.directive'; import { IgxBannerActionsDirective } from './banner.directives'; -import { NgIf } from '@angular/common'; import { CancelableEventArgs, IBaseEventArgs } from '../core/utils'; import { ToggleAnimationSettings } from '../expansion-panel/toggle-animation-component'; import { IgxExpansionPanelBodyComponent } from '../expansion-panel/expansion-panel-body.component'; @@ -49,7 +48,7 @@ export interface BannerCancelEventArgs extends BannerEventArgs, CancelableEventA @Component({ selector: 'igx-banner', templateUrl: 'banner.component.html', - imports: [IgxExpansionPanelComponent, IgxExpansionPanelBodyComponent, NgIf, IgxButtonDirective, IgxRippleDirective] + imports: [IgxExpansionPanelComponent, IgxExpansionPanelBodyComponent, IgxButtonDirective, IgxRippleDirective] }) export class IgxBannerComponent implements IToggleView { /** diff --git a/projects/igniteui-angular/src/lib/buttonGroup/buttonGroup.component.ts b/projects/igniteui-angular/src/lib/buttonGroup/buttonGroup.component.ts index 5b2af8ee886..8b768bcb5b8 100644 --- a/projects/igniteui-angular/src/lib/buttonGroup/buttonGroup.component.ts +++ b/projects/igniteui-angular/src/lib/buttonGroup/buttonGroup.component.ts @@ -1,4 +1,3 @@ -import { NgFor, NgIf } from '@angular/common'; import { AfterViewInit, Component, @@ -58,7 +57,7 @@ let NEXT_ID = 0; @Component({ selector: 'igx-buttongroup', templateUrl: 'buttongroup-content.component.html', - imports: [NgFor, IgxButtonDirective, IgxRippleDirective, NgIf, IgxIconComponent] + imports: [IgxButtonDirective, IgxRippleDirective, IgxIconComponent] }) export class IgxButtonGroupComponent implements AfterViewInit, OnDestroy { /** diff --git a/projects/igniteui-angular/src/lib/buttonGroup/buttongroup-content.component.html b/projects/igniteui-angular/src/lib/buttonGroup/buttongroup-content.component.html index e86c985d859..58f674c856a 100644 --- a/projects/igniteui-angular/src/lib/buttonGroup/buttongroup-content.component.html +++ b/projects/igniteui-angular/src/lib/buttonGroup/buttongroup-content.component.html @@ -1,17 +1,23 @@
- + @for (button of values; track button) { + + }
diff --git a/projects/igniteui-angular/src/lib/buttonGroup/buttongroup.component.spec.ts b/projects/igniteui-angular/src/lib/buttonGroup/buttongroup.component.spec.ts index 2e1b9157c24..e73de82221c 100644 --- a/projects/igniteui-angular/src/lib/buttonGroup/buttongroup.component.spec.ts +++ b/projects/igniteui-angular/src/lib/buttonGroup/buttongroup.component.spec.ts @@ -5,7 +5,6 @@ import { configureTestSuite } from '../test-utils/configure-suite'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { UIInteractions, wait } from '../test-utils/ui-interactions.spec'; import { IgxButtonDirective } from '../directives/button/button.directive'; -import { NgFor } from '@angular/common'; import { IgxRadioGroupDirective } from '../directives/radio/radio-group.directive'; import { IgxRadioComponent } from '../radio/radio.component'; @@ -585,10 +584,12 @@ class ButtonGroupWithSelectedButtonComponent { @Component({ template: ` - + @for (item of items; track item) { + + } `, - imports: [IgxButtonGroupComponent, IgxButtonDirective, NgFor] + imports: [IgxButtonGroupComponent, IgxButtonDirective] }) class ButtonGroupButtonWithBoundSelectedOutputComponent { @ViewChild(IgxButtonGroupComponent, { static: true }) public buttonGroup: IgxButtonGroupComponent; @@ -605,9 +606,11 @@ class ButtonGroupButtonWithBoundSelectedOutputComponent { @Component({ template: ` - - {{ item }} - + @for (item of ['Foo', 'Bar']; track item) { + + {{ item }} + + } @@ -623,7 +626,7 @@ class ButtonGroupButtonWithBoundSelectedOutputComponent { `, - imports: [IgxButtonGroupComponent, IgxButtonDirective, NgFor, IgxRadioGroupDirective, IgxRadioComponent] + imports: [IgxButtonGroupComponent, IgxButtonDirective, IgxRadioGroupDirective, IgxRadioComponent] }) class ButtonGroupSelectionBoundToAnotherComponent { @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) public radioGroup: IgxRadioGroupDirective; diff --git a/projects/igniteui-angular/src/lib/calendar/calendar.component.html b/projects/igniteui-angular/src/lib/calendar/calendar.component.html index ff3575059ab..96410be5472 100644 --- a/projects/igniteui-angular/src/lib/calendar/calendar.component.html +++ b/projects/igniteui-angular/src/lib/calendar/calendar.component.html @@ -1,22 +1,22 @@ - + @if (selection === 'single') { {{ resourceStrings.igx_calendar_select_date }} - - + } + @if (selection === 'range') { {{ resourceStrings.igx_calendar_range_placeholder }} - + } - + @if (selection === 'single') { {{ getFormattedDate().weekday }},  {{ getFormattedDate().monthday }} - - + } + @if (selection === 'range') { {{ selectedDates.length === 0 ? 'Start' : getFormattedRange().start}}  -  {{ selectedDates.length <= 1 ? 'End' : getFormattedRange().end}} - + } @@ -35,7 +35,9 @@ - {{ formattedYear(obj.date) }} + @if (activeView === 'year') { + {{ formattedYear(obj.date) }} + } - + @if (monthsViewNumber < 2 || obj.index < 1) { + {{ monthsViewNumber > 1 ? - (resourceStrings.igx_calendar_first_picker_of.replace('{0}', monthsViewNumber.toString()) + ' ' + + (resourceStrings.igx_calendar_first_picker_of.replace('{0}', monthsViewNumber.toString()) + ' ' + (obj.date | date: 'LLLL yyyy')) : - resourceStrings.igx_calendar_selected_month_is + (obj.date | date: 'LLLL yyyy')}} - + resourceStrings.igx_calendar_selected_month_is + (obj.date | date: 'LLLL yyyy')}} + + } @@ -116,16 +120,15 @@
+ *ngTemplateOutlet="subheaderTemplate ? subheaderTemplate : defaultMonthYear; context: getContext(i)">
-
- - -
+ @if (this.orientation === 'horizontal' ? i === monthsViewNumber - 1 : i === 0) { +
+ + +
+ }
@@ -149,7 +152,7 @@
+ *ngTemplateOutlet="subheaderTemplate ? subheaderTemplate : defaultDecade;">
@@ -160,18 +163,20 @@ -
-
- -
-

- - -

-
+@if (selection === 'single' && hasHeader || selection === 'range' && hasHeader) { +
+
+ +
+

+ + +

+
+}
role="grid" > - + @if (selection === 'multi') { {{ monthsViewNumber && monthsViewNumber > 1 ? resourceStrings.igx_calendar_multi_selection.replace('{0}', monthsViewNumber.toString()) : resourceStrings.igx_calendar_singular_multi_selection}} - - + } + @if (selection === 'range') { {{ monthsViewNumber && monthsViewNumber > 1 ? resourceStrings.igx_calendar_range_selection.replace('{0}', monthsViewNumber.toString()) : resourceStrings.igx_calendar_singular_range_selection}} - - + } + @if (selection === 'single') { {{ monthsViewNumber && monthsViewNumber > 1 ? resourceStrings.igx_calendar_single_selection.replace('{0}', monthsViewNumber.toString()) : resourceStrings.igx_calendar_singular_single_selection}} - + }
- - + @if (isDefaultView) { + @for (view of monthsViewNumber | IgxMonthViewSlots; track $index; let i = $index) { - - + } + } - + @if (isYearView) { - + } - + @if (isDecadeView) { - + }
diff --git a/projects/igniteui-angular/src/lib/calendar/calendar.component.ts b/projects/igniteui-angular/src/lib/calendar/calendar.component.ts index b7f21eaa3dc..528bc28db3a 100644 --- a/projects/igniteui-angular/src/lib/calendar/calendar.component.ts +++ b/projects/igniteui-angular/src/lib/calendar/calendar.component.ts @@ -13,7 +13,7 @@ import { booleanAttribute, HostListener, } from '@angular/core'; -import { NgIf, NgTemplateOutlet, NgFor, DatePipe } from '@angular/common'; +import { NgTemplateOutlet, DatePipe } from '@angular/common'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { @@ -71,7 +71,7 @@ let NEXT_ID = 0; ], selector: 'igx-calendar', templateUrl: 'calendar.component.html', - imports: [NgIf, NgTemplateOutlet, IgxCalendarScrollPageDirective, IgxIconComponent, NgFor, IgxDaysViewComponent, IgxMonthsViewComponent, IgxYearsViewComponent, DatePipe, IgxMonthViewSlotsCalendar, IgxGetViewDateCalendar] + imports: [NgTemplateOutlet, IgxCalendarScrollPageDirective, IgxIconComponent, IgxDaysViewComponent, IgxMonthsViewComponent, IgxYearsViewComponent, DatePipe, IgxMonthViewSlotsCalendar, IgxGetViewDateCalendar] }) export class IgxCalendarComponent extends IgxCalendarBaseDirective implements AfterViewInit, OnDestroy { /** diff --git a/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.html b/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.html index e613c31623d..96a403d93b3 100644 --- a/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.html +++ b/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.html @@ -3,86 +3,86 @@ class="igx-days-view__row" [title]="weekNumberHeader.long | titlecase" > -
- - {{ weekNumberHeader.short | titlecase }} - -
- - - {{ dayName.formatted | titlecase }} + @if (showWeekNumbers) { +
+ + {{ weekNumberHeader.short | titlecase }} + +
+ } + @for (dayName of weekHeaderLabels; track dayName.long) { + + + {{ dayName.formatted | titlecase }} + -
+ }
-
+@for ( + week of monthWeeks; track rowTracker(i, week); + let isLast = $last; let i = $index +) {
- - {{ getWeekNumber(week[0]) }} - + @if (showWeekNumbers) { +
+ + {{ getWeekNumber(week[0]) }} + +
+ } + @for (day of week; track dateTracker($index, day)) { + + {{ formattedDate(day.native) }} + + }
- - - {{ formattedDate(day.native) }} - -
+} diff --git a/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.ts b/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.ts index 35151a58f37..cba03ba1379 100644 --- a/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.ts +++ b/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.ts @@ -15,7 +15,7 @@ import { ChangeDetectionStrategy, } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; -import { NgIf, NgFor, TitleCasePipe } from '@angular/common'; +import { TitleCasePipe } from '@angular/common'; import { CalendarSelection, ScrollDirection } from '../../calendar/calendar'; import { IgxDayItemComponent } from './day-item.component'; import { DateRangeType } from '../../core/dates'; @@ -45,7 +45,7 @@ let NEXT_ID = 0; selector: 'igx-days-view', templateUrl: 'days-view.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - imports: [NgIf, NgFor, IgxDayItemComponent, TitleCasePipe] + imports: [IgxDayItemComponent, TitleCasePipe] }) export class IgxDaysViewComponent extends IgxCalendarBaseDirective { #standalone = true; @@ -430,8 +430,8 @@ export class IgxDaysViewComponent extends IgxCalendarBaseDirective { /** * @hidden */ - public rowTracker(index: number, item: CalendarDay[]): string { - return `${item[index].month}${item[index].date}`; + public rowTracker(_: number, item: CalendarDay[]): string { + return `${item[0].month}${item[0].date}`; } /** diff --git a/projects/igniteui-angular/src/lib/calendar/month-picker/month-picker.component.html b/projects/igniteui-angular/src/lib/calendar/month-picker/month-picker.component.html index 60928d5fa04..e13738c8de4 100644 --- a/projects/igniteui-angular/src/lib/calendar/month-picker/month-picker.component.html +++ b/projects/igniteui-angular/src/lib/calendar/month-picker/month-picker.component.html @@ -44,7 +44,9 @@ - {{ formattedYear(obj.date) }} + @if (activeView === 'year') { + {{ formattedYear(obj.date) }} + }
- + @if (isDefaultView) { - + } - + @if (isDecadeView) { - + }
- + @if (isDefaultView) { > - + } - + @if (isDecadeView) { - + }
diff --git a/projects/igniteui-angular/src/lib/calendar/month-picker/month-picker.component.ts b/projects/igniteui-angular/src/lib/calendar/month-picker/month-picker.component.ts index 6c3e4691c49..6bda0564ec4 100644 --- a/projects/igniteui-angular/src/lib/calendar/month-picker/month-picker.component.ts +++ b/projects/igniteui-angular/src/lib/calendar/month-picker/month-picker.component.ts @@ -9,7 +9,7 @@ import { OnDestroy, OnInit, } from "@angular/core"; -import { NgIf, NgTemplateOutlet, DatePipe } from "@angular/common"; +import { NgTemplateOutlet, DatePipe } from "@angular/common"; import { NG_VALUE_ACCESSOR } from "@angular/forms"; import { IgxMonthsViewComponent } from "../months-view/months-view.component"; @@ -38,7 +38,6 @@ let NEXT_ID = 0; selector: "igx-month-picker", templateUrl: "month-picker.component.html", imports: [ - NgIf, NgTemplateOutlet, DatePipe, IgxIconComponent, diff --git a/projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.html b/projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.html index aeca84c201d..8fcda69dff5 100644 --- a/projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.html +++ b/projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.html @@ -1,21 +1,22 @@
- - + }
diff --git a/projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.ts b/projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.ts index f41f532facf..956e7acc000 100644 --- a/projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.ts +++ b/projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.ts @@ -7,7 +7,7 @@ import { Inject, } from "@angular/core"; import { IgxCalendarMonthDirective } from "../calendar.directives"; -import { NgFor, TitleCasePipe } from "@angular/common"; +import { TitleCasePipe } from "@angular/common"; import { IgxCalendarViewDirective, DAY_INTERVAL_TOKEN, @@ -33,7 +33,7 @@ let NEXT_ID = 0; ], selector: "igx-months-view", templateUrl: "months-view.component.html", - imports: [NgFor, IgxCalendarMonthDirective, TitleCasePipe] + imports: [IgxCalendarMonthDirective, TitleCasePipe] }) export class IgxMonthsViewComponent extends IgxCalendarViewDirective implements ControlValueAccessor { #standalone = true; diff --git a/projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.html b/projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.html index 28082a19ab9..2f83bea48d9 100644 --- a/projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.html +++ b/projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.html @@ -1,22 +1,23 @@
- - + }
diff --git a/projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.ts b/projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.ts index ccdc538e67c..07fd46a8de5 100644 --- a/projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.ts +++ b/projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.ts @@ -6,7 +6,6 @@ import { Inject, } from "@angular/core"; import { IgxCalendarYearDirective } from "../calendar.directives"; -import { NgFor } from "@angular/common"; import { IgxCalendarViewDirective, DAY_INTERVAL_TOKEN, @@ -30,7 +29,7 @@ import { calendarRange } from "../common/helpers"; ], selector: "igx-years-view", templateUrl: "years-view.component.html", - imports: [NgFor, IgxCalendarYearDirective] + imports: [IgxCalendarYearDirective] }) export class IgxYearsViewComponent extends IgxCalendarViewDirective implements ControlValueAccessor { #standalone = true; diff --git a/projects/igniteui-angular/src/lib/carousel/carousel.component.html b/projects/igniteui-angular/src/lib/carousel/carousel.component.html index b6e038359da..d79dc110577 100644 --- a/projects/igniteui-angular/src/lib/carousel/carousel.component.html +++ b/projects/igniteui-angular/src/lib/carousel/carousel.component.html @@ -16,43 +16,53 @@
- +@if (navigation && slides.length) { + +} - +@if (navigation && slides.length) { + +} -
- +} - +@if (showIndicatorsLabel) { + +} diff --git a/projects/igniteui-angular/src/lib/chips/chip.component.ts b/projects/igniteui-angular/src/lib/chips/chip.component.ts index 8cdcdae3cb3..06690bdc2b6 100644 --- a/projects/igniteui-angular/src/lib/chips/chip.component.ts +++ b/projects/igniteui-angular/src/lib/chips/chip.component.ts @@ -20,7 +20,7 @@ import { IBaseEventArgs, mkenum } from '../core/utils'; import { ChipResourceStringsEN, IChipResourceStrings } from '../core/i18n/chip-resources'; import { Subject } from 'rxjs'; import { IgxIconComponent } from '../icon/icon.component'; -import { NgClass, NgTemplateOutlet, NgIf, DOCUMENT } from '@angular/common'; +import { NgClass, NgTemplateOutlet, DOCUMENT } from '@angular/common'; import { getCurrentResourceStrings } from '../core/i18n/resources'; import { Size } from '../grids/common/enums'; @@ -83,7 +83,7 @@ let CHIP_ID = 0; @Component({ selector: 'igx-chip', templateUrl: 'chip.component.html', - imports: [IgxDropDirective, IgxDragDirective, NgClass, NgTemplateOutlet, NgIf, IgxIconComponent] + imports: [IgxDropDirective, IgxDragDirective, NgClass, NgTemplateOutlet, IgxIconComponent] }) export class IgxChipComponent implements OnInit, OnDestroy { diff --git a/projects/igniteui-angular/src/lib/chips/chip.spec.ts b/projects/igniteui-angular/src/lib/chips/chip.spec.ts index ce2820051f4..e518735693d 100644 --- a/projects/igniteui-angular/src/lib/chips/chip.spec.ts +++ b/projects/igniteui-angular/src/lib/chips/chip.spec.ts @@ -10,19 +10,20 @@ import { UIInteractions, wait } from '../test-utils/ui-interactions.spec'; import { configureTestSuite } from '../test-utils/configure-suite'; import { ControlsFunction } from '../test-utils/controls-functions.spec'; import { IgxIconComponent } from '../icon/icon.component'; -import { NgFor } from '@angular/common'; import { getComponentSize } from '../core/utils'; @Component({ template: ` - - {{chip.text}} - drag_indicator - + @for (chip of chipList; track chip) { + + {{chip.text}} + drag_indicator + + } Tab Chip @@ -40,7 +41,7 @@ import { getComponentSize } from '../core/utils'; `, - imports: [IgxChipComponent, IgxChipsAreaComponent, IgxIconComponent, IgxPrefixDirective, NgFor] + imports: [IgxChipComponent, IgxChipsAreaComponent, IgxIconComponent, IgxPrefixDirective] }) class TestChipComponent { @@ -68,13 +69,15 @@ class TestChipComponent { @Component({ template: ` - - label - suf - + @for (chip of chipList; track chip) { + + label + suf + + } `, - imports: [IgxChipsAreaComponent, IgxChipComponent, IgxLabelDirective, IgxSuffixDirective, NgFor] + imports: [IgxChipsAreaComponent, IgxChipComponent, IgxLabelDirective, IgxSuffixDirective] }) class TestChipsLabelAndSuffixComponent { diff --git a/projects/igniteui-angular/src/lib/chips/chips-area.spec.ts b/projects/igniteui-angular/src/lib/chips/chips-area.spec.ts index a3ce7260c12..54e5916d107 100644 --- a/projects/igniteui-angular/src/lib/chips/chips-area.spec.ts +++ b/projects/igniteui-angular/src/lib/chips/chips-area.spec.ts @@ -7,19 +7,20 @@ import { configureTestSuite } from '../test-utils/configure-suite'; import { wait, UIInteractions } from '../test-utils/ui-interactions.spec'; import { IgxIconComponent } from '../icon/icon.component'; import { IgxPrefixDirective } from './public_api'; -import { NgFor } from '@angular/common'; @Component({ template: ` - - drag_indicator - {{chip.text}} - + @for (chip of chipList; track chip) { + + drag_indicator + {{chip.text}} + + } `, - imports: [IgxChipsAreaComponent, IgxChipComponent, IgxIconComponent, IgxPrefixDirective, NgFor] + imports: [IgxChipsAreaComponent, IgxChipComponent, IgxIconComponent, IgxPrefixDirective] }) class TestChipComponent { @ViewChild('chipsArea', { read: IgxChipsAreaComponent, static: true }) @@ -58,14 +59,16 @@ class TestChipSelectComponent extends TestChipComponent { @Component({ template: ` - - drag_indicator - {{chip.text}} - + @for (chip of chipList; track chip) { + + drag_indicator + {{chip.text}} + + } `, - imports: [IgxChipsAreaComponent, IgxChipComponent, IgxIconComponent, IgxPrefixDirective, NgFor] + imports: [IgxChipsAreaComponent, IgxChipComponent, IgxIconComponent, IgxPrefixDirective] }) class TestChipReorderComponent { @ViewChild('chipsArea', { read: IgxChipsAreaComponent, static: true }) diff --git a/projects/igniteui-angular/src/lib/combo/combo-dropdown.component.ts b/projects/igniteui-angular/src/lib/combo/combo-dropdown.component.ts index bb2452ce6da..733995846f3 100644 --- a/projects/igniteui-angular/src/lib/combo/combo-dropdown.component.ts +++ b/projects/igniteui-angular/src/lib/combo/combo-dropdown.component.ts @@ -10,7 +10,7 @@ import { IgxComboAPIService } from './combo.api'; import { IgxDropDownItemBaseDirective } from '../drop-down/drop-down-item.base'; import { IgxSelectionAPIService } from '../core/selection'; import { IgxComboItemComponent } from './combo-item.component'; -import { DOCUMENT, NgIf } from '@angular/common'; +import { DOCUMENT } from '@angular/common'; import { IgxToggleDirective } from '../directives/toggle/toggle.directive'; /** @hidden */ @@ -18,7 +18,7 @@ import { IgxToggleDirective } from '../directives/toggle/toggle.directive'; selector: 'igx-combo-drop-down', templateUrl: '../drop-down/drop-down.component.html', providers: [{ provide: IGX_DROPDOWN_BASE, useExisting: IgxComboDropDownComponent }], - imports: [IgxToggleDirective, NgIf] + imports: [IgxToggleDirective] }) export class IgxComboDropDownComponent extends IgxDropDownComponent implements IDropDownBase, OnDestroy, AfterViewInit { /** @hidden @internal */ diff --git a/projects/igniteui-angular/src/lib/combo/combo-item.component.html b/projects/igniteui-angular/src/lib/combo/combo-item.component.html index 3849092698e..b467360ae0d 100644 --- a/projects/igniteui-angular/src/lib/combo/combo-item.component.html +++ b/projects/igniteui-angular/src/lib/combo/combo-item.component.html @@ -1,5 +1,5 @@ - +@if (!isHeader && !singleMode) { - +} diff --git a/projects/igniteui-angular/src/lib/combo/combo-item.component.ts b/projects/igniteui-angular/src/lib/combo/combo-item.component.ts index 1c9b4dd39de..ff74a3ebf3f 100644 --- a/projects/igniteui-angular/src/lib/combo/combo-item.component.ts +++ b/projects/igniteui-angular/src/lib/combo/combo-item.component.ts @@ -12,13 +12,12 @@ import { IgxComboAPIService } from './combo.api'; import { IgxSelectionAPIService } from '../core/selection'; import { rem } from '../core/utils'; import { IgxCheckboxComponent } from '../checkbox/checkbox.component'; -import { NgIf } from '@angular/common'; /** @hidden */ @Component({ selector: 'igx-combo-item', templateUrl: 'combo-item.component.html', - imports: [NgIf, IgxCheckboxComponent] + imports: [IgxCheckboxComponent] }) export class IgxComboItemComponent extends IgxDropDownItemComponent { diff --git a/projects/igniteui-angular/src/lib/combo/combo.component.html b/projects/igniteui-angular/src/lib/combo/combo.component.html index cde01b8b3ce..03fd08b909f 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.component.html +++ b/projects/igniteui-angular/src/lib/combo/combo.component.html @@ -9,49 +9,59 @@ + [attr.placeholder]="placeholder" [disabled]="disabled" + role="combobox" aria-haspopup="listbox" + [attr.aria-expanded]="!dropdown.collapsed" [attr.aria-controls]="dropdown.listId" + [attr.aria-labelledby]="ariaLabelledBy || label?.id || placeholder" + (blur)="onBlur()" /> - - - - - - + @if (displayValue) { + + @if (clearIconTemplate) { + + } + @if (!clearIconTemplate) { + + } + + } - + @if (toggleIconTemplate) { - - + } + @if (!toggleIconTemplate) { + + } - + @if (displaySearchInput) { + + }
- + @if (item?.isHeader) { - + } - + @if (!item?.isHeader) { - + }
-
-
- - + @if (filteredData.length === 0 || isAddButtonVisible()) { +
+ @if (filteredData.length === 0) { +
+ + +
+ } + @if (isAddButtonVisible()) { + + + + + }
- - - - -
+ } diff --git a/projects/igniteui-angular/src/lib/combo/combo.component.ts b/projects/igniteui-angular/src/lib/combo/combo.component.ts index 76543666a22..92756f24369 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.component.ts +++ b/projects/igniteui-angular/src/lib/combo/combo.component.ts @@ -1,4 +1,4 @@ -import { DOCUMENT, NgClass, NgIf, NgTemplateOutlet } from '@angular/common'; +import { DOCUMENT, NgClass, NgTemplateOutlet } from '@angular/common'; import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, OnInit, OnDestroy, Optional, Inject, Injector, ViewChild, Input, Output, EventEmitter, HostListener, DoCheck, booleanAttribute @@ -101,7 +101,6 @@ const diffInSets = (set1: Set, set2: Set): any[] => { { provide: NG_VALUE_ACCESSOR, useExisting: IgxComboComponent, multi: true } ], imports: [ - NgIf, NgTemplateOutlet, NgClass, FormsModule, diff --git a/projects/igniteui-angular/src/lib/core/i18n/query-builder-resources.ts b/projects/igniteui-angular/src/lib/core/i18n/query-builder-resources.ts index f51f52336a3..e486e6ba242 100644 --- a/projects/igniteui-angular/src/lib/core/i18n/query-builder-resources.ts +++ b/projects/igniteui-angular/src/lib/core/i18n/query-builder-resources.ts @@ -1,6 +1,7 @@ export interface IQueryBuilderResourceStrings { igx_query_builder_date_placeholder?: string; igx_query_builder_time_placeholder?: string; + igx_query_builder_datetime_placeholder?: string; igx_query_builder_filter_operator_and?: string; igx_query_builder_filter_operator_or?: string; igx_query_builder_filter_contains?: string; @@ -13,6 +14,8 @@ export interface IQueryBuilderResourceStrings { igx_query_builder_filter_notEmpty?: string; igx_query_builder_filter_null?: string; igx_query_builder_filter_notNull?: string; + igx_query_builder_filter_in?: string; + igx_query_builder_filter_notIn?: string; igx_query_builder_filter_before?: string; igx_query_builder_filter_after?: string; igx_query_builder_filter_at?: string; @@ -33,16 +36,20 @@ export interface IQueryBuilderResourceStrings { igx_query_builder_filter_lessThanOrEqualTo?: string; igx_query_builder_filter_true?: string; igx_query_builder_filter_false?: string; - igx_query_builder_filter_all?: string; - igx_query_builder_title?: string; + igx_query_builder_filter_all?: string; + igx_query_builder_from_label?: string; + igx_query_builder_select_label?: string; + igx_query_builder_where_label?: string; igx_query_builder_and_group?: string; igx_query_builder_or_group?: string; igx_query_builder_end_group?: string; igx_query_builder_and_label?: string; igx_query_builder_or_label?: string; + igx_query_builder_switch_group?: string; igx_query_builder_add_condition?: string; - igx_query_builder_create_and_group?: string; - igx_query_builder_create_or_group?: string; + igx_query_builder_add_group?: string; + igx_query_builder_add_condition_root?: string; + igx_query_builder_add_group_root?: string; igx_query_builder_ungroup?: string; igx_query_builder_delete?: string; igx_query_builder_delete_filters?: string; @@ -50,11 +57,26 @@ export interface IQueryBuilderResourceStrings { igx_query_builder_column_placeholder?: string; igx_query_builder_condition_placeholder?: string; igx_query_builder_value_placeholder?: string; + igx_query_builder_query_value_placeholder?: string; + igx_query_builder_all_fields?: string; + igx_query_builder_details?: string; + igx_query_builder_search?: string; + igx_query_builder_select_all?: string; + igx_query_builder_select_entity?: string; + igx_query_builder_select_return_field_single?: string; + igx_query_builder_select_return_fields?: string; + igx_query_builder_dialog_title?: string; + igx_query_builder_dialog_message?: string; + igx_query_builder_dialog_checkbox_text?: string; + igx_query_builder_dialog_cancel?: string; + igx_query_builder_dialog_confirm?: string; + igx_query_builder_drop_ghost_text?: string; } export const QueryBuilderResourceStringsEN: IQueryBuilderResourceStrings = { - igx_query_builder_date_placeholder: 'Pick up date', - igx_query_builder_time_placeholder: 'Pick up time', + igx_query_builder_date_placeholder: 'Select date', + igx_query_builder_time_placeholder: 'Select time', + igx_query_builder_datetime_placeholder: 'Select date & time', igx_query_builder_filter_operator_and: 'And', igx_query_builder_filter_operator_or: 'Or', igx_query_builder_filter_contains: 'Contains', @@ -67,6 +89,8 @@ export const QueryBuilderResourceStringsEN: IQueryBuilderResourceStrings = { igx_query_builder_filter_notEmpty: 'Not Empty', igx_query_builder_filter_null: 'Null', igx_query_builder_filter_notNull: 'Not Null', + igx_query_builder_filter_in: 'In', + igx_query_builder_filter_notIn: 'Not In', igx_query_builder_filter_before: 'Before', igx_query_builder_filter_after: 'After', igx_query_builder_filter_at: 'At', @@ -87,16 +111,20 @@ export const QueryBuilderResourceStringsEN: IQueryBuilderResourceStrings = { igx_query_builder_filter_lessThanOrEqualTo: 'Less Than Or Equal To', igx_query_builder_filter_true: 'True', igx_query_builder_filter_false: 'False', - igx_query_builder_filter_all: 'All', - igx_query_builder_title: 'Query Builder', + igx_query_builder_filter_all: 'All', + igx_query_builder_from_label: 'From', + igx_query_builder_select_label: 'Select', + igx_query_builder_where_label: 'Where', igx_query_builder_and_group: '"And" Group', igx_query_builder_or_group: '"Or" Group', igx_query_builder_end_group: 'End Group', igx_query_builder_and_label: 'and', igx_query_builder_or_label: 'or', - igx_query_builder_add_condition: 'Condition', - igx_query_builder_create_and_group: 'Create "And" Group', - igx_query_builder_create_or_group: 'Create "Or" Group', + igx_query_builder_switch_group: 'Switch to {0}', + igx_query_builder_add_condition: 'Add condition', + igx_query_builder_add_group: 'Add group', + igx_query_builder_add_condition_root: 'Condition', + igx_query_builder_add_group_root: 'Group', igx_query_builder_ungroup: 'Ungroup', igx_query_builder_delete: 'Delete', igx_query_builder_delete_filters: 'Delete filters', @@ -104,4 +132,18 @@ export const QueryBuilderResourceStringsEN: IQueryBuilderResourceStrings = { igx_query_builder_column_placeholder: 'Select column', igx_query_builder_condition_placeholder: 'Select filter', igx_query_builder_value_placeholder: 'Value', + igx_query_builder_query_value_placeholder: 'Sub-query results', + igx_query_builder_all_fields: 'All fields', + igx_query_builder_details: 'Details', + igx_query_builder_search: 'Search', + igx_query_builder_select_all: 'Select All', + igx_query_builder_select_entity: 'Select entity', + igx_query_builder_select_return_field_single: 'Select return field', + igx_query_builder_select_return_fields: 'Select return fields', + igx_query_builder_dialog_title: 'Confirmation', + igx_query_builder_dialog_message: 'By changing the entity, you will lose your current settings. Are you sure you want to do that?', + igx_query_builder_dialog_checkbox_text: 'Do not show this dialog again', + igx_query_builder_dialog_cancel: 'Cancel', + igx_query_builder_dialog_confirm: 'Confirm', + igx_query_builder_drop_ghost_text: 'Drop here to insert' }; \ No newline at end of file diff --git a/projects/igniteui-angular/src/lib/core/styles/components/_index.scss b/projects/igniteui-angular/src/lib/core/styles/components/_index.scss index d5bbef81f3f..f197f6628a9 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/_index.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/_index.scss @@ -25,7 +25,7 @@ @forward 'grid/pivot-data-selector-theme'; @forward 'grid-summary/grid-summary-theme'; @forward 'grid-toolbar/grid-toolbar-theme'; -@forward 'highlight/highlight-theme.scss'; +@forward 'highlight/highlight-theme'; @forward 'icon/icon-theme'; @forward 'icon-button/icon-button-theme'; @forward 'input/input-group-theme'; @@ -50,5 +50,5 @@ @forward 'time-picker/time-picker-theme'; @forward 'toast/toast-theme'; @forward 'tooltip/tooltip-theme'; -@forward 'tree/tree-theme.scss'; +@forward 'tree/tree-theme'; @forward 'watermark/watermark-theme'; diff --git a/projects/igniteui-angular/src/lib/core/styles/components/chip/_chip-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/chip/_chip-theme.scss index 0f5ebc26cf2..752f35b2d48 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/chip/_chip-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/chip/_chip-theme.scss @@ -698,7 +698,9 @@ %igx-chip__prefix, %igx-chip__suffix { - display: inline-flex; + @include ellipsis(); + + display: inline-block; vertical-align: middle; max-width: $chip-max-width; diff --git a/projects/igniteui-angular/src/lib/core/styles/components/grid/_excel-filtering-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/grid/_excel-filtering-theme.scss index 343bd37fd5b..60e1489cfb5 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/grid/_excel-filtering-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/grid/_excel-filtering-theme.scss @@ -175,7 +175,7 @@ @if $theme-variant == 'light' { background: contrast-color($color: 'gray', $variant: 900); } @else { - background: color($color: 'gray', $variant: 50); + background: color($color: 'surface', $variant: 500); } %igx-group-display { @@ -720,20 +720,14 @@ } %grid-excel-menu__secondary-footer { - padding: rem(8px) rem(16px); + --ig-size: 2; - @if $bootstrap-theme { - border-top: rem(1px) dashed color($color: 'gray', $variant: 100); - } @else { - border-top: rem(1px) dashed color($color: 'gray', $variant: 300); - } + padding-inline: if($variant != 'bootstrap', rem(24px), rem(16px)); + padding-block-end: if($variant != 'bootstrap', rem(24px), rem(16px)); - @if $variant == 'indigo' and $theme-variant == 'dark' { - border-top: rem(1px) dashed color($color: 'gray', $variant: 100); - } - - @if $variant == 'indigo' { - padding: rem(16px); + @if $bootstrap-theme { + padding-block-start: rem(16px); + border-top: rem(1px) solid color($color: 'gray', $variant: 300); } %grid-excel-filter__apply, diff --git a/projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-theme.scss index 90ce37cda12..d8d15e81f77 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-theme.scss @@ -3192,24 +3192,32 @@ @include excel-filtering($theme); %advanced-filtering-dialog { - background: var-get($theme, 'filtering-row-background'); - box-shadow: elevation(if($variant == 'indigo', if($theme-variant == 'light', 24, 23), 12)); + @if $variant == 'indigo' { + $light-variant: contrast-color($color: 'gray', $variant: 900); + $dark-variant: color($color: 'gray', $variant: 50); + background: if($theme-variant == 'light', $light-variant, $dark-variant); + } @else { + background: color($color: 'surface', $variant: 500); + } + + box-shadow: elevation(if($variant == 'indigo', if($theme-variant == 'light', 24, 23), 24)); + + @if $variant == 'material' or $variant == 'bootstrap' { + border-radius: rem(4px); + } + + @if $variant == 'fluent' { + border-radius: rem(2px); + } @if $variant == 'indigo' { border-radius: rem(10px); } igx-query-builder { - --igx-query-builder-background: #{var-get($theme, 'filtering-row-background')}; - --igx-query-builder-background-and: #{var-get($theme, 'filtering-background-and')}; - --igx-query-builder-background-and--focus: #{var-get($theme, 'filtering-background-and--focus')}; - --igx-query-builder-background-or: #{var-get($theme, 'filtering-background-or')}; - --igx-query-builder-background-or--focus: #{var-get($theme, 'filtering-background-or--focus')}; box-shadow: none; - - @if $variant == 'indigo' { - border-radius: rem(10px); - } + border: none; + border-radius: inherit; } igx-query-builder-header { diff --git a/projects/igniteui-angular/src/lib/core/styles/components/query-builder/_query-builder-component.scss b/projects/igniteui-angular/src/lib/core/styles/components/query-builder/_query-builder-component.scss index dddad37c496..62c964d2daa 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/query-builder/_query-builder-component.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/query-builder/_query-builder-component.scss @@ -4,10 +4,9 @@ /// @access private /// @author Simeon Simeonoff @mixin component { - @include _builder-legend(); @include _advanced-filtering-tree(); - @include _advanced-filtering-con-menu(); - @include _advanced-filtering-empty(); + @include _query-builder-tree(); + @include _query-builder-dialog(); @include b(igx-query-builder) { $this: bem--selector-to-string(&); @@ -30,36 +29,32 @@ @extend %advanced-filter__header !optional; } - @include e(main) { - @extend %advanced-filter__main !optional; + @include e(title) { + @extend %advanced-filter__title !optional; } - @include e(outlet) { - @extend %advanced-filter__outlet !optional; + @include e(label) { + @extend %advanced-filter__label !optional; } - @include m('inline') { - @extend %advanced-filter--inline !optional; + @include e(main) { + @extend %advanced-filter__main !optional; } - } -} -@mixin _builder-legend { - @include b(igx-builder-legend) { - @extend %filter-legend !optional; + @include e(root) { + @extend %advanced-filter__root !optional; + } - @include e(item) { - @extend %filter-legend__item !optional; + @include e(root-actions) { + @extend %advanced-filter__root-actions !optional; } - @include e(item, $m: 'and') { - @extend %filter-legend__item !optional; - @extend %filter-legend__item--and !optional; + @include e(outlet) { + @extend %advanced-filter__outlet !optional; } - @include e(item, $m: 'or') { - @extend %filter-legend__item !optional; - @extend %filter-legend__item--or !optional; + @include m('inline') { + @extend %advanced-filter--inline !optional; } } } @@ -68,6 +63,14 @@ @include b(igx-filter-tree) { @extend %filter-tree !optional; + @include e(subquery) { + @extend %filter-tree__subquery !optional; + } + + @include e(section) { + @extend %filter-tree__section !optional; + } + @include e(line) { @extend %filter-tree__line !optional; } @@ -80,22 +83,38 @@ @extend %filter-tree__line--or !optional; } - @include e(line, $mods: ('selected', 'and')) { - @extend %filter-tree__line--and-selected !optional; + @include e(button, $m: 'and') { + @extend %filter-tree__button--and !optional; } - @include e(line, $mods: ('selected', 'or')) { - @extend %filter-tree__line--or-selected !optional; + @include e(button, $m: 'or') { + @extend %filter-tree__button--or !optional; } - @include e(expression) { - @extend %filter-tree__expression !optional; + @include e(expressions) { + @extend %filter-tree__expressions !optional; + } + + @include e(expression-context-menu) { + @extend %filter-tree__expression-context-menu !optional; + } + + @include e(expression-section) { + @extend %filter-tree__expression-section !optional; } @include e(expression-item) { @extend %filter-tree__expression-item !optional; } + @include e(expression-item-ghost) { + @extend %filter-tree__expression-item-ghost !optional; + } + + @include e(expression-item-drop-ghost) { + @extend %filter-tree__expression-drop-item-ghost !optional; + } + @include e(expression-column) { @extend %filter-tree__expression-column !optional; } @@ -116,32 +135,32 @@ @extend %filter-tree__inputs !optional; } + @include e(inputs-field) { + @extend %filter-tree__inputs-field !optional; + } + @include e(inputs-actions) { @extend %filter-tree__inputs-actions !optional; } + + @include e(details-button) { + @extend %filter-tree-details-button !optional;; + } } } -@mixin _advanced-filtering-con-menu { - @include b(igx-filter-contextual-menu) { - @extend %filter-con-menu !optional; - - @include e(close-btn) { - @extend %filter-con-menu__close-btn !optional; - } +@mixin _query-builder-tree { + @include b(igx-query-builder-tree) { + @extend %query-builder-tree !optional; - @include e(delete-btn) { - @extend %filter-con-menu__delete-btn !optional; + @include m(level-0) { + @extend %query-level-0 !optional; } } } -@mixin _advanced-filtering-empty { - @include b(igx-filter-empty) { - @extend %filter-empty !optional; - - @include e(title) { - @extend %filter-empty__title !optional; - } +@mixin _query-builder-dialog { + @include b(igx-query-builder-dialog) { + @extend %query-builder-dialog !optional;; } } diff --git a/projects/igniteui-angular/src/lib/core/styles/components/query-builder/_query-builder-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/query-builder/_query-builder-theme.scss index 67872257471..ca2358f1abb 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/query-builder/_query-builder-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/query-builder/_query-builder-theme.scss @@ -9,25 +9,37 @@ /// @param {Color} header-background [null] - The background color of the query builder header. /// @param {Color} header-foreground [null] - The foreground color of the query builder header. /// @param {Color} header-border [null] - The border color of the query builder header. -/// @param {Map} background-and [null] - The background color of advanced filtering "AND" condition. -/// @param {Map} background-and--focus [null] - The background color on focus/selected of advanced filtering "AND" condition. -/// @param {Map} background-or [null] - The background color of advanced filtering "OR" condition. -/// @param {Map} background-or--focus [null] - The background color on focus/selected of advanced filtering "OR" condition. +/// +/// @param {Map} subquery-header-background [null] - The background color of the subquery header. +/// @param {Map} subquery-border-color [null] - The border color of the query block. +/// @param {Map} separator-color [null] - The separator color of the query block. +/// @param {Number} subquery-border-radius [null] - The border radius of the subquery block. +/// +/// @param {Map} label-foreground [null] - The color for query builder labels "from" & "select". +/// @param {Map} separator-color [null] - The separator color of the query builder tree block. +/// @param {Number} border-radius [null] - The border radius of the query builder. +/// +/// @param {Color} color-expression-group-and [null] - The color of advanced filtering "AND" condition group. +/// @param {Color} color-expression-group-or [null] - The color of advanced filtering "OR" condition group. +/// /// @example scss Set custom query-builder colors -/// $my-query-builder-theme: query-builder-theme($$background: red); +/// $my-query-builder-theme: query-builder-theme($background: red); /// // Pass the theme to the css-vars() mixin /// @include css-vars($my-query-builder-theme); @function query-builder-theme( $schema: $light-material-schema, - $background: null, $header-background: null, $header-foreground: null, $header-border: null, - $background-and: null, - $background-and--focus: null, - $background-or: null, - $background-or--focus: null, + $color-expression-group-and: null, + $color-expression-group-or: null, + $border-radius: null, + $subquery-header-background: null, + $subquery-border-color: null, + $subquery-border-radius: null, + $separator-color: null, + $label-foreground: null, ) { $name: 'igx-query-builder'; $selector: 'igx-query-builder'; @@ -46,21 +58,29 @@ $header-foreground: text-contrast($header-background); } + @if not($header-background) and $background { + $header-background: $background; + } + @return extend($theme, ( name: $name, selector: $selector, - background: $background, header-background: $header-background, header-foreground: $header-foreground, header-border: $header-border, - background-and: $background-and, - background-and--focus: $background-and--focus, - background-or: $background-or, - background-or--focus: $background-or--focus, + color-expression-group-and: $color-expression-group-and, + color-expression-group-or: $color-expression-group-or, + subquery-header-background: $subquery-header-background, + subquery-border-color: $subquery-border-color, + subquery-border-radius: $subquery-border-radius, + separator-color: $separator-color, + border-radius: $border-radius, + label-foreground: $label-foreground, theme: map.get($schema, '_meta', 'theme'), _meta: map.merge(if($meta, $meta, ()), ( - variant: map.get($schema, '_meta', 'theme') + variant: map.get($schema, '_meta', 'theme'), + theme-variant: map.get($schema, '_meta', 'variant') )), )); } @@ -83,18 +103,12 @@ $bootstrap-theme: $variant == 'bootstrap'; $not-bootstrap-theme: not($bootstrap-theme); - $filter-empty: ( - comfortable: rem(144px), - cosy: rem(107px), - compact: rem(92px) - ); - - $vertical-space: ( - comfortable: rem(16px), - cosy: rem(12px), - compact: rem(8px) - ); + // Custom colors alpha + $alpha-hover: .08; + $alpha-focus: .16; + $alpha-focus-hover: .24; + $border-radius: var-get($theme, 'border-radius'); $icon-size: rem(18px); %advanced-filter { @@ -103,48 +117,148 @@ width: auto; min-width: rem(660px); background-color: var-get($theme, 'background'); - border-radius: border-radius(rem(4px)); - box-shadow: elevation(12); + border-radius: $border-radius; + box-shadow: var-get($theme, 'elevation'); + overflow: hidden; + + &:has(:not(igx-query-builder-header)) { + padding-block-start: if($variant != 'bootstrap', rem(24px), rem(16px)) + } + + &:has(igx-query-builder-header) { + padding-block-start: 0; + } + + .igx-chip__ghost { + position: relative; + } } - %advanced-filter__header { - @if $variant != 'indigo' { - @include type-style('h6'); - } @else { - @include type-style('h5'); + %query-builder-tree { + background: var-get($theme, 'background'); + + %query-builder-tree { + border-radius: var-get($theme, 'subquery-border-radius'); + } + } + + %query-level-0 { + display: block; + width: 100%; + padding-inline: if($variant != 'bootstrap', rem(24px), rem(16px)); + padding-block: + if($variant != 'bootstrap', 0, rem(16px)) + if($variant != 'bootstrap', rem(24px), rem(16px)); + + > %advanced-filter__main { + gap: rem(16px); + + > %filter-tree__section { + --sb-size: #{rem(10px)}; + + max-height: rem(570px); + overflow-y: auto; + overflow-x: hidden; + padding-inline-end: rem(16px); + } + } + } + + %filter-tree__subquery { + max-width: rem(960px); + + // Add styles to the subquery itself only if there is a direct .igx-filter-tree__inputs inside it + &:has( > %filter-tree__inputs) { + background: var-get($theme, 'subquery-header-background'); + border: rem(1px) solid var-get($theme, 'subquery-border-color'); + border-radius: var-get($theme, 'subquery-border-radius'); + } + + // Hide the subquery itself if there is a tree with display none inside + &:has( > %query-builder-tree[style='display: none;']) { + display: none; + } + + > %filter-tree__inputs { + padding: rem(12px); + border-radius: inherit; + + > igx-input-group, + > igx-date-picker, + > igx-time-picker { + flex-grow: 1; + } + } + + %filter-tree__buttons { + margin-block-start: rem(8px); + } + + %query-builder-tree { + border-block-start: rem(1px) dashed var-get($theme, 'separator-color'); + padding: rem(12px); + } + + &:empty { + display: none; + } + + } + + %filter-tree-details-button { + margin-inline-start: auto; + } + + %query-builder-dialog { + display: flex; + flex-direction: column; + gap: rem(16px); + max-width: rem(310px); - border-top-left-radius: border-radius(rem(10px)); - border-top-right-radius: border-radius(rem(10px)); + > * { + margin: 0 !important; } + } + %advanced-filter__header { display: flex; align-items: center; background-color: var-get($theme, 'header-background'); color: var-get($theme, 'header-foreground'); user-select: none; + border-radius: $border-radius $border-radius 0 0; margin-bottom: 0; border-block-end: rem(1px) solid var-get($theme, 'header-border'); + + padding-inline: if($variant != 'bootstrap', rem(24px), rem(16px)); + padding-block: if($variant != 'bootstrap', rem(24px), rem(16px)) rem(16px); + } + + %advanced-filter__title { + &:empty { + display: none; + } } %advanced-filter__main { - display: block; - overflow: auto; - min-height: pad(rem(138px), rem(164px), rem(214px)); - max-height: pad(rem(305px), rem(394px), rem(468px)); + display: grid; + gap: rem(16px); + } + + %advanced-filter__root { + display: flex; + flex-direction: column; + flex-grow: 1; - [igxButton] + [igxButton] { - margin-inline-start: rem(8px); + > * { + flex-grow: 1; } } - %advanced-filter__header, - %advanced-filter__main { - padding-inline: pad-inline( - map.get($vertical-space, 'compact'), - map.get($vertical-space, 'cosy'), - map.get($vertical-space, 'comfortable') - ); - padding-block: rem(16px); + %advanced-filter__root-actions { + display: flex; + gap: rem(8px); + padding-bottom: rem(16px); } %advanced-filter__outlet { @@ -158,87 +272,202 @@ %filter-tree { display: flex; + width: 100%; - + %filter-tree, - + %filter-tree__expression-item, - + %filter-tree__inputs { - margin-top: pad( - map.get($vertical-space, 'compact'), - map.get($vertical-space, 'cosy'), - map.get($vertical-space, 'comfortable') - ); + %filter-tree { + margin-block: rem(8px); + } + } + + %filter-tree__section { + display: flex; + flex-direction: column; + gap: rem(8px); + + > %filter-tree { + margin-block: 0; + } + } + + %filter-tree__expression-context-menu { + display: flex; + width: 100%; + + [igxbutton='flat'] { + --ig-size: 1; + + @if $variant == 'bootstrap' { + --ig-button-text-transform: capitalize; + } + + border: none; + min-width: auto; } } %filter-tree__line { - width: rem(8px); - min-width: rem(8px); + $size: rem(2px); + width: $size; background-color: white; - margin-inline-end: pad(rem(8px), rem(12px), rem(16px)); + margin-inline-end: calc(rem(8px) - $size); outline-style: none; - border-radius: border-radius(rem(4px)); - cursor: pointer; } %filter-tree__line--and { - background: var-get($theme, 'background-and'); - - &-selected { - background: var-get($theme, 'background-and--focus'); - } - - &:focus { - box-shadow: inset 0 0 0 rem(2px) var-get($theme, 'background-and--focus'); - } + background: var-get($theme, 'color-expression-group-and'); } %filter-tree__line--or { - background: var-get($theme, 'background-or'); + background: var-get($theme, 'color-expression-group-or'); + } - &-selected { - background-color: var-get($theme, 'background-or--focus'); - } + %filter-tree__button--and { + &[igxButton='flat'] { + @if $variant == 'material' or $variant == 'indigo' { + --focus-hover-background: hsl(from #{var-get($theme, 'color-expression-group-and')} h s l / #{$alpha-focus-hover}); + --focus-visible-background: hsl(from #{var-get($theme, 'color-expression-group-and')} h s l / #{$alpha-focus}); + --focus-background: hsl(from #{var-get($theme, 'color-expression-group-and')} h s l / #{$alpha-focus}); + --active-background: hsl(from #{var-get($theme, 'color-expression-group-and')} h s l / #{$alpha-focus}); + --hover-background: hsl(from #{var-get($theme, 'color-expression-group-and')} h s l / #{$alpha-hover}); + --background: transparent; + } + + @if $variant == 'fluent' { + --background: transparent; + --focus-hover-background: #{color($color: 'gray', $variant: if($theme-variant == 'light', 200, 50))}; + --focus-visible-background: transparent; + --focus-background: transparent; + --active-background: #{color($color: 'gray', $variant: if($theme-variant == 'light', 200, 50))}; + --hover-background: #{color($color: 'gray', $variant: if($theme-variant == 'light', 200, 50))}; + } + + --foreground: #{var-get($theme, 'color-expression-group-and')}; + --focus-visible-foreground: #{var-get($theme, 'color-expression-group-and')}; + --icon-color: #{var-get($theme, 'color-expression-group-and')}; + + @if $variant != 'bootstrap' { + --focus-foreground: #{var-get($theme, 'color-expression-group-and')}; + --hover-foreground: #{var-get($theme, 'color-expression-group-and')}; + --icon-color-hover: #{var-get($theme, 'color-expression-group-and')}; + --focus-hover-foreground: #{var-get($theme, 'color-expression-group-and')}; + --active-foreground: #{var-get($theme, 'color-expression-group-and')}; + } @else { + $bootstrap-foreground-lightness: if($theme-variant == 'light', 34%, 78% ); + + --focus-hover-background: transparent; + --focus-visible-background: transparent; + --focus-background: transparent; + --active-background: transparent; + --hover-background: transparent; + --background: transparent; + --shadow-color: hsl(from #{var-get($theme, 'color-expression-group-and')} h s l / .5); + + --icon-color-hover: hsl(from #{var-get($theme, 'color-expression-group-and')} h s #{$bootstrap-foreground-lightness} / 1); + --focus-foreground: hsl(from #{var-get($theme, 'color-expression-group-and')} h s #{$bootstrap-foreground-lightness} / 1); + --hover-foreground: hsl(from #{var-get($theme, 'color-expression-group-and')} h s #{$bootstrap-foreground-lightness} / 1); + --focus-hover-foreground: hsl(from #{var-get($theme, 'color-expression-group-and')} h s #{$bootstrap-foreground-lightness} / 1); + --active-foreground: hsl(from #{var-get($theme, 'color-expression-group-and')} h s #{$bootstrap-foreground-lightness} / 1); + } + } + } - &:focus { - box-shadow: inset 0 0 0 rem(2px) var-get($theme, 'background-or--focus'); - } + %filter-tree__button--or { + &[igxButton='flat'] { + @if $variant == 'material' or $variant == 'indigo' { + --focus-hover-background: hsl(from #{var-get($theme, 'color-expression-group-or')} h s l / #{$alpha-focus-hover}); + --focus-visible-background: hsl(from #{var-get($theme, 'color-expression-group-or')} h s l / #{$alpha-focus}); + --focus-background: hsl(from #{var-get($theme, 'color-expression-group-or')} h s l / #{$alpha-focus}); + --active-background: hsl(from #{var-get($theme, 'color-expression-group-or')} h s l / #{$alpha-focus}); + --hover-background: hsl(from #{var-get($theme, 'color-expression-group-or')} h s l / #{$alpha-hover}); + --background: transparent; + } + + @if $variant == 'fluent' { + --background: transparent; + --focus-hover-background: #{color($color: 'gray', $variant: if($theme-variant == 'light', 200, 50))}; + --focus-visible-background: transparent; + --focus-background: transparent; + --active-background: #{color($color: 'gray', $variant: if($theme-variant == 'light', 200, 50))}; + --hover-background: #{color($color: 'gray', $variant: if($theme-variant == 'light', 200, 50))}; + } + + --foreground: #{var-get($theme, 'color-expression-group-or')}; + --focus-visible-foreground: #{var-get($theme, 'color-expression-group-or')}; + --icon-color: #{var-get($theme, 'color-expression-group-or')}; + + @if $variant != 'bootstrap' { + --focus-foreground: #{var-get($theme, 'color-expression-group-or')}; + --hover-foreground: #{var-get($theme, 'color-expression-group-or')}; + --icon-color-hover: #{var-get($theme, 'color-expression-group-or')}; + --focus-hover-foreground: #{var-get($theme, 'color-expression-group-or')}; + --active-foreground: #{var-get($theme, 'color-expression-group-or')}; + } @else { + $bootstrap-foreground-lightness: if($theme-variant == 'light', 14%, 47%); + + --focus-hover-background: transparent; + --focus-visible-background: transparent; + --focus-background: transparent; + --active-background: transparent; + --hover-background: transparent; + --background: transparent; + --shadow-color: hsl(from #{var-get($theme, 'color-expression-group-or')} h s l / .5); + + --icon-color-hover: hsl(from #{var-get($theme, 'color-expression-group-or')} h s #{$bootstrap-foreground-lightness} / 1); + --focus-foreground: hsl(from #{var-get($theme, 'color-expression-group-or')} h s #{$bootstrap-foreground-lightness} / 1); + --hover-foreground: hsl(from #{var-get($theme, 'color-expression-group-or')} h s #{$bootstrap-foreground-lightness} / 1); + --focus-hover-foreground: hsl(from #{var-get($theme, 'color-expression-group-or')} h s #{$bootstrap-foreground-lightness} / 1); + --active-foreground: hsl(from #{var-get($theme, 'color-expression-group-or')} h s #{$bootstrap-foreground-lightness} / 1); + } + } } - %filter-tree__expression { + %filter-tree__expressions { display: flex; flex-direction: column; align-items: flex-start; + flex-grow: 1; + gap: rem(8px); } - %filter-tree__expression-item { + %filter-tree__expression-section { + $spacing: rem(16px); display: flex; - align-items: center; + flex-direction: column; + width: calc(100% - #{$spacing}); + gap: rem(8px); + margin-inline-start: $spacing; - + %filter-tree, - + %filter-tree__inputs, - + %filter-tree__expression-item { - margin-top: pad( - map.get($vertical-space, 'compact'), - map.get($vertical-space, 'cosy'), - map.get($vertical-space, 'comfortable') - ); + &:empty { + display: none; } + } - > igx-chip { - @container style(--ig-size: 1) { - --ig-size: 2; - } + %filter-tree__expression-item { + display: flex; + align-items: center; + width: 100%; + gap: rem(8px); + position: relative; + + igx-chip { + --ig-size: 3; @if $variant != 'indigo' { - .igx-chip__item { - border-block: none; + igx-icon { + --component-size: 1; } } + } - .igx-filter-tree__expression-column { + > igx-chip { + %filter-tree__expression-column { padding-inline: pad-inline(rem(3px), rem(6px), rem(8px)); } + %filter-tree__expression-condition { + padding-inline-start: pad-inline(rem(3px), rem(6px), rem(8px)); + } + igx-prefix { display: flex; } @@ -249,156 +478,94 @@ } } + + %filter-tree__expression-item-ghost { + &.igx-chip__item { + @include type-style('body-2'); + + --ig-body-2-text-transform: unset; + + padding-inline: rem(32px); + } + + color: color($color: 'gray', $variant: if($theme-variant == 'light', 600, 900)); + border: rem(1px) dashed color($color: 'gray', $variant: if($theme-variant == 'light', 600, 300)); + background: transparent; + } + %filter-tree__expression-column { padding: 0 rem(8px); } %filter-tree__expression-actions { display: inline-flex; - margin: 0 rem(8px); - gap: rem(8px); + gap: if($variant != 'indigo', rem(16px), rem(8px)); - %igx-icon-button-display { - --size: #{sizable(rem(20px), rem(24px), if($variant != 'indigo', rem(32px), rem(28px)))}; + span { + display: inline-flex; } + + %igx-icon-button-display { + --ig-size: #{if($variant != 'bootstrap', 2, 1)}; + }; } %filter-tree__expression-condition { - opacity: .7; + opacity: if($variant != 'indigo', .6, .8); } %filter-tree__buttons { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: pad( - map.get($vertical-space, 'compact'), - map.get($vertical-space, 'cosy'), - map.get($vertical-space, 'comfortable') - ); - - + %filter-tree, - + %filter-tree__expression-item, - + %filter-tree__inputs { - margin-top: pad( - map.get($vertical-space, 'compact'), - map.get($vertical-space, 'cosy'), - map.get($vertical-space, 'comfortable') - ); - } - } + --ig-size: 1; - %filter-tree__inputs { display: flex; - justify-content: space-between; align-items: center; + gap: rem(8px); - igx-input-group { - --ig-size: 1; - } - - igx-select + igx-select, - igx-select + igx-input-group, - igx-select + igx-date-picker, - igx-select + igx-time-picker, - igx-input-group + igx-select { - margin-inline-start: rem(8px); - } - - + %filter-tree, - + %filter-tree__expression-item { - margin-top: pad( - map.get($vertical-space, 'compact'), - map.get($vertical-space, 'cosy'), - map.get($vertical-space, 'comfortable') - ); + [igxbutton='flat'] { + padding-block: 0; + border: none } } - %filter-tree__inputs-actions { - display: flex; - margin: 0 rem(8px); - align-items: center; + %filter-tree__inputs { + --ig-size: #{if($variant == 'indigo' or $variant == 'bootstrap', 2, 1)}; - [igxIconButton] { - transition: none; - } + display: flex; + align-items: flex-end; + gap: rem(16px); + width: 100%; + border-radius: inherit; - [igxIconButton] + [igxIconButton] { - margin-inline-start: rem(8px); + &:empty { + display: none; } } - %filter-legend { + %filter-tree__inputs-field { display: flex; - margin-inline-start: auto; - pointer-events: none; + flex-direction: column; + gap: rem(4px); + max-width: rem(250px); + width: 100%; } - %filter-legend__item { - position: relative; - display: inline-flex; - align-items: center; - font-size: rem(12px); - - @if $variant == 'indigo' { - font-weight: 400; - } + %advanced-filter__label { + @include type-style('body-2'); - &::before { - content: ''; - width: rem(24px); - height: rem(24px); - background: white; - border-radius: border-radius(rem(4px)); - margin-inline-end: rem(8px); - } - - + %filter-legend__item { - margin-inline-start: rem(24px); - } - } - - %filter-legend__item--and::before { - background: var-get($theme, 'background-and'); + color: var-get($theme, 'label-foreground'); } - %filter-legend__item--or::before { - background: var-get($theme, 'background-or'); - } + %filter-tree__inputs-actions { + --ig-size: 2; - %filter-con-menu { - position: relative; display: flex; - flex-flow: column; - width: rem(196px); - background-color: var-get($theme, 'background'); - padding: rem(16px); - margin-inline-start: rem(16px); - border-radius: border-radius(rem(4px)); - border: rem(1px) solid color(null, 'gray', 200); - - > [igxButton] + [igxButton], - igx-buttongroup + [igxButton], - [igxButton] + igx-buttongroup { - margin-top: pad( - map.get($vertical-space, 'compact'), - map.get($vertical-space, 'cosy'), - map.get($vertical-space, 'comfortable') - ); - } - - > [igxButton]%filter-con-menu__close-btn + [igxButton], - [igxButton]%filter-con-menu__close-btn + igx-buttongroup { - margin-top: 0; - } - - [igxButton] > igx-icon + * { - margin-inline-start: rem(8px); - } + gap: rem(8px); + align-items: center; + width: auto; + align-self: center; - igx-buttongroup > * { - box-shadow: none; + [igxIconButton] { + transition: none; } } @@ -422,8 +589,9 @@ %filter-con-menu__close-btn { position: absolute; - top: rem(-18px); - inset-inline-end: rem(-18px); + top: 0; + inset-inline-start: 100%; + transform: translate(-50%, -50%); background-color: var-get($theme, 'background'); border: rem(1px) solid color(null, 'gray', 200); @@ -435,29 +603,6 @@ } } - %filter-empty { - display: flex; - align-items: center; - justify-content: center; - height: pad( - map.get($filter-empty, 'compact'), - map.get($filter-empty, 'cosy'), - map.get($filter-empty, 'comfortable') - ); - } - - %filter-empty__title { - @if $variant == 'indigo' { - @if $theme-variant == 'light' { - color: color(null, 'gray', 600); - } @else { - color: contrast-color(null, 'gray', 50, .6); - } - } @else { - color: color(null, 'gray', 600); - } - } - %advanced-filter--inline { display: flex; flex-direction: column; @@ -475,3 +620,19 @@ } } } + +/// Adds typography styles for the igx-query-builder component. +/// Uses the 'h6' category from the typographic scale. +/// @group typography +/// @param {Map} $categories [(title: 'h6')] - The categories from the typographic scale used for type styles. +@mixin query-builder-typography( + $categories: (title: 'h6') +) { + $title: map.get($categories, 'title'); + + %advanced-filter__title { + @include type-style($title) { + margin: 0; + } + } +} diff --git a/projects/igniteui-angular/src/lib/core/styles/typography/_bootstrap.scss b/projects/igniteui-angular/src/lib/core/styles/typography/_bootstrap.scss index 3358a8d1d64..97c8a89c9a4 100644 --- a/projects/igniteui-angular/src/lib/core/styles/typography/_bootstrap.scss +++ b/projects/igniteui-angular/src/lib/core/styles/typography/_bootstrap.scss @@ -32,6 +32,7 @@ @use '../components/tooltip/tooltip-theme' as *; @use '../components/tree/tree-theme' as *; @use '../components/label/label-theme' as *; +@use '../components/query-builder/query-builder-theme' as *; @mixin typography($type-scale) { @include badge-typography(); @@ -113,4 +114,7 @@ @include label-typography($categories: ( label: 'body-1' )); + @include query-builder-typography($categories: ( + title: 'h5' + )); } diff --git a/projects/igniteui-angular/src/lib/core/styles/typography/_fluent.scss b/projects/igniteui-angular/src/lib/core/styles/typography/_fluent.scss index d203af9fbf1..03987eca9c2 100644 --- a/projects/igniteui-angular/src/lib/core/styles/typography/_fluent.scss +++ b/projects/igniteui-angular/src/lib/core/styles/typography/_fluent.scss @@ -31,6 +31,7 @@ @use '../components/tooltip/tooltip-theme' as *; @use '../components/tree/tree-theme' as *; @use '../components/label/label-theme' as *; +@use '../components/query-builder/query-builder-theme' as *; @mixin typography() { @include badge-typography(); @@ -119,4 +120,5 @@ @include label-typography($categories: ( label: 'subtitle-2' )); + @include query-builder-typography(); } diff --git a/projects/igniteui-angular/src/lib/core/styles/typography/_indigo.scss b/projects/igniteui-angular/src/lib/core/styles/typography/_indigo.scss index d9a0e32013e..ee8596057e2 100644 --- a/projects/igniteui-angular/src/lib/core/styles/typography/_indigo.scss +++ b/projects/igniteui-angular/src/lib/core/styles/typography/_indigo.scss @@ -31,6 +31,7 @@ @use '../components/tooltip/tooltip-theme' as *; @use '../components/tree/tree-theme' as *; @use '../components/label/label-theme' as *; +@use '../components/query-builder/query-builder-theme' as *; @mixin typography($type-scale) { @include badge-typography($categories: ( @@ -125,4 +126,7 @@ @include label-typography($categories: ( label: 'caption' )); + @include query-builder-typography($categories: ( + title: 'h5' + )); } diff --git a/projects/igniteui-angular/src/lib/core/styles/typography/_material.scss b/projects/igniteui-angular/src/lib/core/styles/typography/_material.scss index d48041d30ed..8920a178e02 100644 --- a/projects/igniteui-angular/src/lib/core/styles/typography/_material.scss +++ b/projects/igniteui-angular/src/lib/core/styles/typography/_material.scss @@ -31,6 +31,7 @@ @use '../components/tooltip/tooltip-theme' as *; @use '../components/tree/tree-theme' as *; @use '../components/label/label-theme' as *; +@use '../components/query-builder/query-builder-theme' as *; @mixin typography() { @include badge-typography(); @@ -66,4 +67,5 @@ @include tooltip-typography(); @include tree-typography(); @include label-typography(); + @include query-builder-typography(); } diff --git a/projects/igniteui-angular/src/lib/core/utils.ts b/projects/igniteui-angular/src/lib/core/utils.ts index 487dce78d8d..55404e32fe2 100644 --- a/projects/igniteui-angular/src/lib/core/utils.ts +++ b/projects/igniteui-angular/src/lib/core/utils.ts @@ -656,9 +656,9 @@ export function getComponentCssSizeVar(size: string) { * @param path - The URI path to be normalized. * @returns string encoded using the encodeURI function. */ - export function normalizeURI(path: string) { +export function normalizeURI(path: string) { return path?.split('/').map(encodeURI).join('/'); - } +} export function getComponentTheme(el: Element) { return globalThis.window @@ -666,3 +666,16 @@ export function getComponentTheme(el: Element) { .getPropertyValue('--theme') .trim() as IgxTheme; } + +/** + * Collection re-created w/ the built in track by identity will always log + * warning even for valid cases of recalculating all collection items. + * See https://github.com/angular/angular/blob/55581b4181639568fb496e91055142a1b489e988/packages/core/src/render3/instructions/control_flow.ts#L393-L409 + * Current solution explicit track function doing the same as suggested in: + * https://github.com/angular/angular/issues/56471#issuecomment-2180315803 + * This should be used with moderation and when necessary. + * @internal + */ +export function trackByIdentity(item: T): T { + return item; +} diff --git a/projects/igniteui-angular/src/lib/data-operations/data-util.spec.ts b/projects/igniteui-angular/src/lib/data-operations/data-util.spec.ts index e28623afcc9..f6adde08f78 100644 --- a/projects/igniteui-angular/src/lib/data-operations/data-util.spec.ts +++ b/projects/igniteui-angular/src/lib/data-operations/data-util.spec.ts @@ -352,6 +352,7 @@ const testFilter = () => { { fieldName: 'number', condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), + conditionName: 'greaterThan', searchVal: 3 } ]; @@ -367,6 +368,7 @@ const testFilter = () => { state.expressionsTree.filteringOperands = [ { condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', fieldName: 'string', searchVal: 'row' } @@ -378,6 +380,7 @@ const testFilter = () => { stateIgnoreCase.expressionsTree.filteringOperands = [ { condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', fieldName: 'string', ignoreCase: false, searchVal: 'ROW' @@ -401,6 +404,7 @@ const testFilter = () => { state.expressionsTree.filteringOperands = [ { condition: IgxDateFilteringOperand.instance().condition('after'), + conditionName: 'after', fieldName: 'date', searchVal: new Date() } @@ -416,6 +420,7 @@ const testFilter = () => { state.expressionsTree.filteringOperands = [ { condition: IgxBooleanFilteringOperand.instance().condition('false'), + conditionName: 'false', fieldName: 'boolean' } ]; @@ -431,6 +436,7 @@ const testFilter = () => { state.expressionsTree.filteringOperands = [ { condition: IgxBooleanFilteringOperand.instance().condition('false'), + conditionName: 'false', fieldName: 'boolean' } ]; diff --git a/projects/igniteui-angular/src/lib/data-operations/expressions-tree-util.spec.ts b/projects/igniteui-angular/src/lib/data-operations/expressions-tree-util.spec.ts new file mode 100644 index 00000000000..752915ab9dd --- /dev/null +++ b/projects/igniteui-angular/src/lib/data-operations/expressions-tree-util.spec.ts @@ -0,0 +1,480 @@ +import { FilteringLogic, IFilteringExpression } from './filtering-expression.interface'; +import { FilteringExpressionsTree, IFilteringExpressionsTree } from './filtering-expressions-tree'; +import { recreateTree, recreateTreeFromFields } from './expressions-tree-util'; +import { EntityType, FieldType } from '../grids/common/grid.interface'; +import { IgxBooleanFilteringOperand, IgxDateFilteringOperand, IgxDateTimeFilteringOperand, IgxNumberFilteringOperand, IgxStringFilteringOperand, IgxTimeFilteringOperand } from './filtering-condition'; + +function serialize(value: unknown, pretty = false) { + return pretty ? JSON.stringify(value, undefined, ' ') : JSON.stringify(value) +} + +function checkOp(op: IFilteringExpression, reconstructedOp: IFilteringExpression) { + expect(reconstructedOp.condition.logic).not.toBeNull(); + expect(reconstructedOp.condition.name).toBe(op.conditionName); + expect(reconstructedOp.conditionName).toBe(op.conditionName); + + if (op.searchTree) { + for (let index = 0; index < op.searchTree.filteringOperands.length; index++) { + const innerOp = op.searchTree.filteringOperands[index] as IFilteringExpression; + const reconstructedInnerOp = reconstructedOp.searchTree.filteringOperands[index] as IFilteringExpression; + checkOp(innerOp, reconstructedInnerOp); + } + } +} + +describe('Unit testing FilteringUtil', () => { + it('Expressions should resolve correctly when rehydrating with fields', () => { + const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); + const currDate = new Date(); + + const fields = [ + { field: 'Id', dataType: 'number' }, + { field: 'Name', dataType: 'string' }, + { field: 'Validated', dataType: 'boolean' }, + { field: 'Date created', dataType: 'date' }, + { field: 'Time created', dataType: 'time' }, + { field: 'DateTime created', dataType: 'dateTime' } + ] as FieldType[]; + + // number + tree.filteringOperands.push({ + fieldName: 'Id', + conditionName: 'equals', + searchVal: 100 + }); + + // boolean + tree.filteringOperands.push({ + fieldName: 'Validated', + conditionName: 'false' + }); + + // string + tree.filteringOperands.push({ + fieldName: 'Name', + conditionName: 'equals', + searchVal: 'test' + }); + + // DateTime + tree.filteringOperands.push({ + fieldName: 'DateTime created', + conditionName: 'equals', + searchVal: currDate + }); + + // Date + tree.filteringOperands.push({ + fieldName: 'Date created', + conditionName: 'equals', + searchVal: currDate + }); + + // Time + tree.filteringOperands.push({ + fieldName: 'Time created', + conditionName: 'at', + searchVal: currDate + }); + + // misc + tree.filteringOperands.push({ + fieldName: 'Id', + conditionName: 'inQuery' + }); + + tree.filteringOperands.push({ + fieldName: 'Id', + conditionName: 'notInQuery' + }); + + tree.filteringOperands.push({ + fieldName: 'Id', + conditionName: 'null' + }); + + tree.filteringOperands.push({ + fieldName: 'Id', + conditionName: 'notNull' + }); + + const serializedTree = serialize(tree, true); + const deserializedTree = recreateTreeFromFields(JSON.parse(serializedTree), fields); + + for (let index = 0; index < tree.filteringOperands.length; index++) { + checkOp(tree.filteringOperands[index] as IFilteringExpression, deserializedTree.filteringOperands[index] as IFilteringExpression); + } + }); + + it('Should rehydrate correctly from direct object', () => { + const fields = [ + { field: 'Id', dataType: 'number' }, + { field: 'Name', dataType: 'string' }, + { field: 'Validated', dataType: 'boolean' }, + { field: 'DateTime created', dataType: 'dateTime' }, + { field: 'In', dataType: null } + ] as FieldType[]; + + const innerFields = [ + { field: 'Id', dataType: 'number' } + ] as FieldType[]; + + const entities: EntityType[] = [ + { + name: 'myEntity', + fields: fields + }, + { + name: 'otherEntity', + fields: innerFields + } + ]; + + const tree = { + filteringOperands: [ + { + fieldName: 'Id', + conditionName: 'equals', + searchVal: 100 + }, + { + fieldName: 'Name', + conditionName: 'equals', + searchVal: 'test' + }, + { + fieldName: 'Validated', + conditionName: 'false' + }, + { + fieldName: 'DateTime created', + conditionName: 'equals', + searchVal: new Date().toISOString() + } + ], + operator: FilteringLogic.And, + entity: 'myEntity', + returnFields: ['*'] + }; + + const deserializedTree = recreateTree(tree, entities); + + for (let index = 0; index < tree.filteringOperands.length; index++) { + checkOp(tree.filteringOperands[index], deserializedTree.filteringOperands[index] as IFilteringExpression); + } + }); + + it('Should not modify a fully constructed tree with no entities given', () => { + const tree = { + filteringOperands: [ + { + fieldName: 'Id', + conditionName: 'equals', + condition: IgxNumberFilteringOperand.instance().condition('equals'), + searchVal: 100 + }, + { + fieldName: 'Name', + conditionName: 'equals', + condition: IgxStringFilteringOperand.instance().condition('equals'), + searchVal: 'test' + }, + { + fieldName: 'Validated', + conditionName: 'false', + condition: IgxBooleanFilteringOperand.instance().condition('false') + }, + { + fieldName: 'DateTime created', + conditionName: 'equals', + condition: IgxDateTimeFilteringOperand.instance().condition('equals'), + searchVal: new Date().toISOString() + } + ], + operator: FilteringLogic.And, + entity: 'myEntity', + returnFields: ['*'] + }; + + const deserializedTree = recreateTree(tree, []); + + expect(deserializedTree).toEqual(tree); + + for (let index = 0; index < tree.filteringOperands.length; index++) { + checkOp(tree.filteringOperands[index], deserializedTree.filteringOperands[index] as IFilteringExpression); + const reconstructedOp = deserializedTree.filteringOperands[index] as IFilteringExpression; + // Explicitly check the logic function + expect(tree.filteringOperands[index].condition.logic.toString()).toBe(reconstructedOp.condition.logic.toString()); + } + }); + + it('Should not modify a fully constructed tree with fields given', () => { + + const fields = [ + { field: 'Id', dataType: 'number' }, + { field: 'Name', dataType: 'string' }, + { field: 'Validated', dataType: 'boolean' }, + { field: 'DateTime created', dataType: 'dateTime' }, + ] as FieldType[]; + + const tree = { + filteringOperands: [ + { + fieldName: 'Id', + conditionName: 'equals', + condition: IgxNumberFilteringOperand.instance().condition('equals'), + searchVal: 100 + }, + { + fieldName: 'Name', + conditionName: 'equals', + condition: IgxStringFilteringOperand.instance().condition('equals'), + searchVal: 'test' + }, + { + fieldName: 'Validated', + conditionName: 'false', + condition: IgxBooleanFilteringOperand.instance().condition('false') + }, + { + fieldName: 'DateTime created', + conditionName: 'equals', + condition: IgxDateTimeFilteringOperand.instance().condition('equals'), + searchVal: new Date().toISOString() + } + ], + operator: FilteringLogic.And, + entity: 'myEntity', + returnFields: ['*'] + }; + + const deserializedTree = recreateTreeFromFields(tree, fields); + + expect(deserializedTree).toEqual(tree); + + for (let index = 0; index < tree.filteringOperands.length; index++) { + checkOp(tree.filteringOperands[index], deserializedTree.filteringOperands[index] as IFilteringExpression); + const reconstructedOp = deserializedTree.filteringOperands[index] as IFilteringExpression; + // Explicitly check the logic function + expect(tree.filteringOperands[index].condition.logic.toString()).toBe(reconstructedOp.condition.logic.toString()); + } + }); + + it('Sub-queries should deserialize correctly', () => { + const tree = new FilteringExpressionsTree(FilteringLogic.Or, undefined, 'myEntity', ['*']); + const innerTree = new FilteringExpressionsTree(FilteringLogic.And, undefined, 'otherEntity', ['*']); + const entities: EntityType[] = [ + { + name: 'myEntity', + fields: [ + { field: 'Id', dataType: null } + ] as any[], + }, + { + name: 'otherEntity', + fields: [ + { field: 'Bool', dataType: 'boolean' } + ] as any[], + } + ]; + + innerTree.filteringOperands.push({ + fieldName: 'Bool', + conditionName: 'true', + searchVal: true + }); + + tree.filteringOperands.push({ + fieldName: 'Id', + conditionName: 'inQuery', + searchTree: innerTree + }); + + const serializedTree = serialize(tree, true); + const deserializedTree = recreateTree(JSON.parse(serializedTree), entities); + const firstOperand = deserializedTree.filteringOperands[0] as IFilteringExpression; + const nestedOperand = firstOperand.searchTree.filteringOperands[0] as IFilteringExpression; + + expect(firstOperand.conditionName).toBe('inQuery'); + expect(firstOperand.condition.name).toBe('inQuery'); + expect(nestedOperand.condition.logic(true, nestedOperand.searchVal)).toBe(true); + expect(nestedOperand.conditionName).toBe('true'); + expect(nestedOperand.condition.name).toBe('true'); + }); + + it('Number search values should deserialize correctly', () => { + const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); + const entities: EntityType[] = [{ + name: 'myEntity', + fields: [ + { field: 'Id', dataType: 'number' } + ] as any, + }]; + + tree.filteringOperands.push({ + fieldName: 'Id', + conditionName: 'equals', + searchVal: 100 + }); + + const serializedTree = serialize(tree, true); + const deserializedTree = recreateTree(JSON.parse(serializedTree), entities); + const firstOperand = deserializedTree.filteringOperands[0] as IFilteringExpression; + + expect(firstOperand.condition.logic(100, firstOperand.searchVal)).toBe(true); + expect(firstOperand.condition).toBe(IgxNumberFilteringOperand.instance().condition('equals')); + }); + + it('Boolean search values should deserialize correctly', () => { + const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); + const entities: EntityType[] = [{ + name: 'myEntity', + fields: [ + { field: 'Id', dataType: 'boolean' } + ] as any, + }]; + tree.filteringOperands.push({ + fieldName: 'Id', + conditionName: 'false' + }); + + const serializedTree = serialize(tree, true); + const deserializedTree = recreateTree(JSON.parse(serializedTree), entities); + const firstOperand = deserializedTree.filteringOperands[0] as IFilteringExpression; + + expect(firstOperand.condition.logic(false)).toBe(true); + expect(firstOperand.condition).toBe(IgxBooleanFilteringOperand.instance().condition('false')); + }); + + it('String search values should deserialize correctly', () => { + const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); + const entities: EntityType[] = [{ + name: 'myEntity', + fields: [ + { field: 'Id', dataType: 'string' } + ] as any, + }]; + tree.filteringOperands.push({ + fieldName: 'Id', + conditionName: 'equals', + searchVal: 'potato' + }); + + const serializedTree = serialize(tree, true); + const deserializedTree = recreateTree(JSON.parse(serializedTree), entities); + const firstOperand = deserializedTree.filteringOperands[0] as IFilteringExpression; + + expect(firstOperand.condition.logic('potato', firstOperand.searchVal)).toBe(true); + expect(firstOperand.condition).toBe(IgxStringFilteringOperand.instance().condition('equals')); + }); + + it('Date search values should deserialize correctly', () => { + const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); + const entities: EntityType[] = [{ + name: 'myEntity', + fields: [ + { field: 'Id', dataType: 'date' } + ] as any, + }]; + tree.filteringOperands.push({ + fieldName: 'Id', + conditionName: 'equals', + searchVal: new Date(2022, 2, 3).toISOString() + }); + + const serializedTree = serialize(tree, true); + const deserializedTree = recreateTree(JSON.parse(serializedTree), entities); + const firstOperand = deserializedTree.filteringOperands[0] as IFilteringExpression; + + expect(firstOperand.condition.logic(new Date(2022, 2, 3), firstOperand.searchVal)).toBe(true); + expect(firstOperand.condition).toBe(IgxDateFilteringOperand.instance().condition('equals')); + }); + + it('DateTime search values should deserialize correctly', () => { + const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); + const entities: EntityType[] = [{ + name: 'myEntity', + fields: [ + { field: 'Id', dataType: 'dateTime' } + ] as any, + }]; + const currDate = new Date(); + tree.filteringOperands.push({ + fieldName: 'Id', + conditionName: 'equals', + searchVal: currDate.toISOString() + }); + + const serializedTree = serialize(tree, true); + const deserializedTree = recreateTree(JSON.parse(serializedTree), entities); + const firstOperand = deserializedTree.filteringOperands[0] as IFilteringExpression; + + expect(firstOperand.condition.logic(currDate, firstOperand.searchVal)).toBe(true); + expect(firstOperand.condition).toBe(IgxDateTimeFilteringOperand.instance().condition('equals')); + }); + + it('Time search values should deserialize correctly', () => { + const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); + const entities: EntityType[] = [{ + name: 'myEntity', + fields: [ + { field: 'Id', dataType: 'time' } + ] as any, + }]; + tree.filteringOperands.push({ + fieldName: 'Id', + conditionName: 'at', + searchVal: '18:30:00' + }); + + const serializedTree = serialize(tree, true); + const deserializedTree = recreateTree(JSON.parse(serializedTree), entities); + const firstOperand = deserializedTree.filteringOperands[0] as IFilteringExpression; + + expect(firstOperand.condition.logic(new Date(2020, 9, 2, 18, 30, 0, 0), firstOperand.searchVal)).toBe(true); + expect(firstOperand.condition).toBe(IgxTimeFilteringOperand.instance().condition('at')); + }); + + it('Nested tree should deserialize correctly', () => { + const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); + const subTree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField2', 'myEntity2', ['*']); + const currDate = new Date(); + const entities: EntityType[] = [ + { + name: 'myEntity', + fields: [ + { field: 'date', dataType: 'date' } + ] as any[], + }, + { + name: 'myEntity2', + fields: [ + { field: 'id', dataType: 'number' } + ] as any[], + } + ]; + + tree.filteringOperands.push({ + fieldName: 'date', + conditionName: 'equals', + searchVal: currDate.toISOString() + }); + subTree.filteringOperands.push({ + fieldName: 'id', + conditionName: 'greaterThan', + searchVal: 123 + }); + tree.filteringOperands.push(subTree); + + const serializedTree = serialize(tree, true); + const deserializedTree = recreateTree(JSON.parse(serializedTree), entities); + const firstOperand = deserializedTree.filteringOperands[0] as IFilteringExpression; + const nestedCondition = (deserializedTree.filteringOperands[1] as IFilteringExpressionsTree).filteringOperands[0] as IFilteringExpression; + + expect(firstOperand.condition.name).toBe('equals'); + expect(firstOperand.condition.logic(currDate, firstOperand.searchVal)).toBe(true); + + expect(nestedCondition.condition.name).toBe('greaterThan'); + expect(nestedCondition.condition.logic(200, nestedCondition.searchVal)).toBe(true); + }); +}); diff --git a/projects/igniteui-angular/src/lib/data-operations/expressions-tree-util.ts b/projects/igniteui-angular/src/lib/data-operations/expressions-tree-util.ts index 47ef83d3470..02a8c260a46 100644 --- a/projects/igniteui-angular/src/lib/data-operations/expressions-tree-util.ts +++ b/projects/igniteui-angular/src/lib/data-operations/expressions-tree-util.ts @@ -1,5 +1,9 @@ +import { DateTimeUtil } from '../date-common/util/date-time.util'; +import { EntityType, FieldType } from '../grids/common/grid.interface'; +import { GridColumnDataType } from './data-util'; +import { IFilteringOperation, IgxBooleanFilteringOperand, IgxDateFilteringOperand, IgxDateTimeFilteringOperand, IgxFilteringOperand, IgxNumberFilteringOperand, IgxStringFilteringOperand, IgxTimeFilteringOperand } from './filtering-condition'; import { IFilteringExpression } from './filtering-expression.interface'; -import { IFilteringExpressionsTree } from './filtering-expressions-tree'; +import { IExpressionTree, IFilteringExpressionsTree } from './filtering-expressions-tree'; export class ExpressionsTreeUtil { /** @@ -54,3 +58,163 @@ export class ExpressionsTreeUtil { return false; } } + +/** + * Recreates the search value for a given expression. + * @param searchValue The search value to recreate. + * @param dataType The data type of the field. + * @returns The recreated search value. + */ +function recreateSearchValue(searchValue: any, dataType: string): any { + if (!dataType && !Array.isArray(searchValue)) { + return searchValue; + } + // In ESF, values are stored as a Set. + // Those values are converted to an array before returning string in the stringifyCallback + // now we need to convert those back to Set + if (Array.isArray(searchValue)) { + return new Set(searchValue); + } else if ((dataType.toLowerCase().includes('date') || dataType.toLowerCase().includes('time')) && !(searchValue instanceof Date)) { + return DateTimeUtil.parseIsoDate(searchValue) ?? searchValue; + } + + return searchValue; +} + +/** + * Returns the filtering logic function for a given dataType and condition (contains, greaterThan, etc.) + * @param dataType The data type of the field. + * @param name The name of the filtering condition. + * @returns The filtering logic function. + */ +function getFilteringCondition(dataType: string, name: string): IFilteringOperation { + let filters: IgxFilteringOperand; + switch (dataType) { + case GridColumnDataType.Boolean: + filters = IgxBooleanFilteringOperand.instance(); + break; + case GridColumnDataType.Number: + case GridColumnDataType.Currency: + case GridColumnDataType.Percent: + filters = IgxNumberFilteringOperand.instance(); + break; + case GridColumnDataType.Date: + filters = IgxDateFilteringOperand.instance(); + break; + case GridColumnDataType.Time: + filters = IgxTimeFilteringOperand.instance(); + break; + case GridColumnDataType.DateTime: + filters = IgxDateTimeFilteringOperand.instance(); + break; + case GridColumnDataType.String: + default: + filters = IgxStringFilteringOperand.instance(); + break; + } + return filters.condition(name); +} + +/** + * Recreates the IFilteringOperation for a given expression. + * If the `logic` is already populated - it will return the original IFilteringOperation + * of the expression. + * @param expression The expression for which to resolve the IFilteringOperation. + * @param dataType The data type of the field. + * @returns The IFilteringOperation for the given expression. + */ +function recreateOperatorFromDataType(expression: IFilteringExpression, dataType: string): IFilteringOperation { + if (!expression.condition?.logic) { + return getFilteringCondition(dataType, expression.conditionName || expression.condition?.name); + } + + return expression.condition; +} + +/** + * Recreates an expression from the given fields by applying the correct operands + * and adjusting the search value to be the correct type. + * @param expression The expression to recreate. + * @param fields An array of fields to use for recreating the expression. + * @returns The recreated expression. + */ +function recreateExpression(expression: IFilteringExpression, fields: FieldType[]): IFilteringExpression { + const field = fields?.find(f => f.field === expression.fieldName); + + if (field && !expression.condition?.logic) { + if (!field.filters) { + expression.condition = recreateOperatorFromDataType(expression, field.dataType); + } else { + expression.condition = field.filters.condition(expression.conditionName || expression.condition?.name); + } + } + + if (!expression.condition && expression.conditionName) { + throw Error('Wrong `conditionName`, `condition` or `field` provided!'); + } + + if (!expression.conditionName) { + expression.conditionName = expression.condition?.name; + } + + expression.searchVal = recreateSearchValue(expression.searchVal, field?.dataType); + + return expression; +} + +/** + * Checks if the given entry is an IExpressionTree. + * @param entry The entry to check. + * @returns True if the entry is an IExpressionTree, false otherwise. + */ +export function isTree(entry: IExpressionTree | IFilteringExpression): entry is IExpressionTree { + return 'operator' in entry; +} + +/** + * Recreates the tree from a given array of entities by applying the correct operands + * for each expression and adjusting the search values to be the correct type. + * @param tree The expression tree to recreate. + * @param entities An array of entities to use for recreating the tree. + * @returns The recreated expression tree. + */ +export function recreateTree(tree: IExpressionTree, entities: EntityType[]): IExpressionTree { + const entity = entities.find(e => e.name === tree.entity); + + for (let i = 0; i < tree.filteringOperands.length; i++) { + const operand = tree.filteringOperands[i]; + if (isTree(operand)) { + tree.filteringOperands[i] = recreateTree(operand, entities); + } else { + if (operand.searchTree) { + operand.searchTree = recreateTree(operand.searchTree, entities); + } + tree.filteringOperands[i] = recreateExpression(operand, entity?.fields); + } + } + + return tree; +} + +/** + * Recreates the tree from a given array of fields by applying the correct operands. + * It is recommended to use `recreateTree` if there will be multiple entities in the tree + * with potentially colliding field names. + * @param tree The expression tree to recreate. + * @param fields An array of fields to use for recreating the tree. + */ +export function recreateTreeFromFields(tree: IExpressionTree, fields: FieldType[]): IExpressionTree { + for (let i = 0; i < tree.filteringOperands.length; i++) { + const operand = tree.filteringOperands[i]; + if (isTree(operand)) { + tree.filteringOperands[i] = recreateTreeFromFields(operand, fields); + } else { + if (operand.searchTree) { + operand.searchTree = recreateTreeFromFields(operand.searchTree, fields); + } + tree.filteringOperands[i] = recreateExpression(operand, fields); + } + } + + return tree; +} diff --git a/projects/igniteui-angular/src/lib/data-operations/filtering-condition.ts b/projects/igniteui-angular/src/lib/data-operations/filtering-condition.ts index 0ed4e613279..9cb01167241 100644 --- a/projects/igniteui-angular/src/lib/data-operations/filtering-condition.ts +++ b/projects/igniteui-angular/src/lib/data-operations/filtering-condition.ts @@ -25,6 +25,18 @@ export class IgxFilteringOperand { iconName: 'filter_in', hidden: true, logic: (target: any, searchVal: Set) => this.findValueInSet(target, searchVal) + }, { + name: 'inQuery', + isUnary: false, + isNestedQuery: true, + iconName: 'in', + logic: (target: any, searchVal: Set) => this.findValueInSet(target, searchVal) + }, { + name: 'notInQuery', + isUnary: false, + isNestedQuery: true, + iconName: 'not-in', + logic: (target: any, searchVal: Set) => !this.findValueInSet(target, searchVal) }]; } @@ -33,9 +45,16 @@ export class IgxFilteringOperand { } /** - * Returns an array of names of the conditions which are visible in the UI + * Returns an array of names of the conditions which are visible in the filtering UI */ public conditionList(): string[] { + return this.operations.filter(f => !f.hidden && !f.isNestedQuery).map((element) => element.name); + } + + /** + * Returns an array of names of the conditions which are visible in the UI, including "In" and "Not In", allowing the creation of sub-queries. + */ + public extendedConditionList(): string[] { return this.operations.filter(f => !f.hidden).map((element) => element.name); } @@ -60,7 +79,7 @@ export class IgxFilteringOperand { /** * @hidden */ - protected findValueInSet(target: any, searchVal: Set) { + public findValueInSet(target: any, searchVal: Set) { return searchVal.has(target); } } @@ -74,7 +93,7 @@ export class IgxFilteringOperand { export class IgxBooleanFilteringOperand extends IgxFilteringOperand { protected constructor() { super(); - this.operations = [{ + const newOperations: IFilteringOperation[] = [{ name: 'all', isUnary: true, iconName: 'filter_all', @@ -99,7 +118,9 @@ export class IgxBooleanFilteringOperand extends IgxFilteringOperand { isUnary: true, iconName: 'filter_not_empty', logic: (target: boolean) => target !== null && target !== undefined - }].concat(this.operations); + }]; + + this.operations = newOperations.concat(this.operations); } } @@ -111,7 +132,7 @@ export class IgxBooleanFilteringOperand extends IgxFilteringOperand { class IgxBaseDateTimeFilteringOperand extends IgxFilteringOperand { protected constructor() { super(); - this.operations = [{ + const newOperations: IFilteringOperation[] = [{ name: 'empty', isUnary: true, iconName: 'filter_empty', @@ -121,7 +142,9 @@ class IgxBaseDateTimeFilteringOperand extends IgxFilteringOperand { isUnary: true, iconName: 'filter_not_empty', logic: (target: Date) => target !== null && target !== undefined - }].concat(this.operations); + }]; + + this.operations = newOperations.concat(this.operations); } /** @@ -166,7 +189,10 @@ class IgxBaseDateTimeFilteringOperand extends IgxFilteringOperand { return res; } - protected override findValueInSet(target: any, searchVal: Set) { + /** + * @hidden + */ + public override findValueInSet(target: any, searchVal: Set) { if (!target) { return false; } @@ -189,7 +215,7 @@ class IgxBaseDateTimeFilteringOperand extends IgxFilteringOperand { export class IgxDateFilteringOperand extends IgxBaseDateTimeFilteringOperand { protected constructor() { super(); - this.operations = [{ + const newOperations: IFilteringOperation[] = [{ name: 'equals', isUnary: false, iconName: 'filter_equal', @@ -389,10 +415,12 @@ export class IgxDateFilteringOperand extends IgxBaseDateTimeFilteringOperand { const now = IgxDateFilteringOperand.getDateParts(new Date(), 'y'); return d.year === now.year + 1; } - }].concat(this.operations); + }]; + + this.operations = newOperations.concat(this.operations); } - protected override findValueInSet(target: any, searchVal: Set) { + public override findValueInSet(target: any, searchVal: Set) { if (!target) { return false; } @@ -406,7 +434,7 @@ export class IgxDateFilteringOperand extends IgxBaseDateTimeFilteringOperand { export class IgxDateTimeFilteringOperand extends IgxBaseDateTimeFilteringOperand { protected constructor() { super(); - this.operations = [{ + const newOperations: IFilteringOperation[] = [{ name: 'equals', isUnary: false, iconName: 'filter_equal', @@ -608,7 +636,9 @@ export class IgxDateTimeFilteringOperand extends IgxBaseDateTimeFilteringOperand const now = IgxDateTimeFilteringOperand.getDateParts(new Date(), 'y'); return d.year === now.year + 1; } - }].concat(this.operations); + }]; + + this.operations = newOperations.concat(this.operations); } } @@ -616,7 +646,7 @@ export class IgxDateTimeFilteringOperand extends IgxBaseDateTimeFilteringOperand export class IgxTimeFilteringOperand extends IgxBaseDateTimeFilteringOperand { protected constructor() { super(); - this.operations = [{ + const newOperations: IFilteringOperation[] = [{ name: 'at', isUnary: false, iconName: 'filter_equal', @@ -710,10 +740,15 @@ export class IgxTimeFilteringOperand extends IgxBaseDateTimeFilteringOperand { targetn.hours > search.hours ? true : targetn.hours === search.hours && targetn.minutes > search.minutes ? true : targetn.hours === search.hours && targetn.minutes === search.minutes && targetn.seconds > search.seconds; } - }].concat(this.operations); + }]; + + this.operations = newOperations.concat(this.operations); } - protected override findValueInSet(target: any, searchVal: Set) { + /** + * @hidden + */ + public override findValueInSet(target: any, searchVal: Set) { if (!target) { return false; } @@ -730,7 +765,7 @@ export class IgxTimeFilteringOperand extends IgxBaseDateTimeFilteringOperand { export class IgxNumberFilteringOperand extends IgxFilteringOperand { protected constructor() { super(); - this.operations = [{ + const newOperations: IFilteringOperation[] = [{ name: 'equals', isUnary: false, iconName: 'filter_equal', @@ -770,7 +805,9 @@ export class IgxNumberFilteringOperand extends IgxFilteringOperand { isUnary: true, iconName: 'filter_not_empty', logic: (target: number) => target !== null && target !== undefined && !isNaN(target) - }].concat(this.operations); + }]; + + this.operations = newOperations.concat(this.operations); } } @@ -783,7 +820,7 @@ export class IgxNumberFilteringOperand extends IgxFilteringOperand { export class IgxStringFilteringOperand extends IgxFilteringOperand { protected constructor() { super(); - this.operations = [{ + const newOperations: IFilteringOperation[] = [{ name: 'contains', isUnary: false, iconName: 'filter_contains', @@ -847,7 +884,9 @@ export class IgxStringFilteringOperand extends IgxFilteringOperand { isUnary: true, iconName: 'filter_not_empty', logic: (target: string) => target !== null && target !== undefined && target.length > 0 - }].concat(this.operations); + }]; + + this.operations = newOperations.concat(this.operations); } /** @@ -872,6 +911,7 @@ export class IgxStringFilteringOperand extends IgxFilteringOperand { export interface IFilteringOperation { name: string; isUnary: boolean; + isNestedQuery?: boolean; iconName: string; hidden?: boolean; /* blazorCSSuppress */ diff --git a/projects/igniteui-angular/src/lib/data-operations/filtering-expression.interface.ts b/projects/igniteui-angular/src/lib/data-operations/filtering-expression.interface.ts index 482ee7ea77e..3e308e0fe1c 100644 --- a/projects/igniteui-angular/src/lib/data-operations/filtering-expression.interface.ts +++ b/projects/igniteui-angular/src/lib/data-operations/filtering-expression.interface.ts @@ -1,4 +1,5 @@ import { IFilteringOperation } from './filtering-condition'; +import { IExpressionTree } from './filtering-expressions-tree'; /* mustCoerceToInt */ export enum FilteringLogic { @@ -13,7 +14,9 @@ export enum FilteringLogic { */ export declare interface IFilteringExpression { fieldName: string; - condition: IFilteringOperation; - searchVal?: any; + condition?: IFilteringOperation; + conditionName?: string; + searchVal?: any; + searchTree?: IExpressionTree; ignoreCase?: boolean; } diff --git a/projects/igniteui-angular/src/lib/data-operations/filtering-expressions-tree.ts b/projects/igniteui-angular/src/lib/data-operations/filtering-expressions-tree.ts index 438f2b7be7f..1381263f5bf 100644 --- a/projects/igniteui-angular/src/lib/data-operations/filtering-expressions-tree.ts +++ b/projects/igniteui-angular/src/lib/data-operations/filtering-expressions-tree.ts @@ -12,6 +12,8 @@ export declare interface IExpressionTree { filteringOperands: (IExpressionTree | IFilteringExpression)[]; operator: FilteringLogic; fieldName?: string; + entity?: string; + returnFields?: string[]; } /* marshalByValue */ @@ -75,7 +77,7 @@ export class FilteringExpressionsTree implements IFilteringExpressionsTree { /** * Sets/gets the field name of the column where the filtering expression is placed. * ```typescript - * gridExpressionTree.fieldName = 'Column Field'; + * gridExpressionTree.fieldName = 'Column Field'; * ``` * ```typescript * let columnField = expressionTree.fieldName; @@ -89,7 +91,7 @@ export class FilteringExpressionsTree implements IFilteringExpressionsTree { /** * Sets/gets the type of the filtering expressions tree. * ```typescript - * gridExpressionTree.type = FilteringExpressionsTree.Advanced; + * gridExpressionTree.type = FilteringExpressionsTree.Advanced; * ``` * ```typescript * let type = expressionTree.type; @@ -99,12 +101,39 @@ export class FilteringExpressionsTree implements IFilteringExpressionsTree { */ public type?: FilteringExpressionsTreeType; - constructor(operator: FilteringLogic, fieldName?: string) { + /** + * Sets/gets the entity. + * ```typescript + * gridExpressionsTree.entity = 'Entity A'; + * ``` + * ```typescript + * let entity = gridExpressionsTree.entity; + * ``` + * + * @memberof FilteringExpressionsTree + */ + public entity?: string; + + /** + * Sets/gets the return fields. + * ```typescript + * gridExpressionsTree.returnFields = ['Column Field 1', 'Column Field 2']; + * ``` + * ```typescript + * let returnFields = gridExpressionsTree.returnFields; + * ``` + * + * @memberof FilteringExpressionsTree + */ + public returnFields?: string[]; + + constructor(operator: FilteringLogic, fieldName?: string, entity?: string, returnFields?: string[]) { this.operator = operator; + this.entity = entity; + this.returnFields = returnFields; this.fieldName = fieldName; } - /** * Checks if filtering expressions tree is empty. * diff --git a/projects/igniteui-angular/src/lib/data-operations/filtering-strategy.spec.ts b/projects/igniteui-angular/src/lib/data-operations/filtering-strategy.spec.ts index 22cf2f0b03e..2ad1908e022 100644 --- a/projects/igniteui-angular/src/lib/data-operations/filtering-strategy.spec.ts +++ b/projects/igniteui-angular/src/lib/data-operations/filtering-strategy.spec.ts @@ -19,6 +19,7 @@ describe('Unit testing FilteringStrategy', () => { expressionTree.filteringOperands = [ { condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), + conditionName: 'greaterThan', fieldName: 'number', searchVal: 1 } @@ -33,12 +34,14 @@ describe('Unit testing FilteringStrategy', () => { expressionTree.filteringOperands = [ { condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', fieldName: 'string', ignoreCase: false, searchVal: 'ROW' }, { condition: IgxNumberFilteringOperand.instance().condition('lessThan'), + conditionName: 'lessThan', fieldName: 'number', searchVal: 1 } @@ -50,6 +53,7 @@ describe('Unit testing FilteringStrategy', () => { const rec = data[0]; const res = fs.findMatchByExpression(rec, { condition: IgxBooleanFilteringOperand.instance().condition('false'), + conditionName: 'false', fieldName: 'boolean' }); expect(res).toBeTruthy(); @@ -61,6 +65,7 @@ describe('Unit testing FilteringStrategy', () => { expressionTree.filteringOperands = [ { condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', fieldName: 'string', searchVal: 'ROW' } diff --git a/projects/igniteui-angular/src/lib/data-operations/filtering-strategy.ts b/projects/igniteui-angular/src/lib/data-operations/filtering-strategy.ts index 9674032ee56..ffecead98e2 100644 --- a/projects/igniteui-angular/src/lib/data-operations/filtering-strategy.ts +++ b/projects/igniteui-angular/src/lib/data-operations/filtering-strategy.ts @@ -6,6 +6,7 @@ import { GridColumnDataType } from './data-util'; import { SortingDirection } from './sorting-strategy'; import { formatNumber, formatPercent, getLocaleCurrencyCode } from '@angular/common'; import { IFilteringState } from './filtering-state.interface'; +import { isTree } from './expressions-tree-util'; const DateType = 'date'; const DateTimeType = 'dateTime'; @@ -46,8 +47,8 @@ export abstract class BaseFilteringStrategy implements IFilteringStrategy { // protected public matchRecord(rec: any, expressions: IFilteringExpressionsTree | IFilteringExpression, grid?: GridType): boolean { if (expressions) { - if (expressions instanceof FilteringExpressionsTree) { - const expressionsTree = expressions as IFilteringExpressionsTree; + if (isTree(expressions)) { + const expressionsTree = expressions; const operator = expressionsTree.operator as FilteringLogic; let matchOperand; @@ -71,7 +72,7 @@ export abstract class BaseFilteringStrategy implements IFilteringStrategy { return true; } else { - const expression = expressions as IFilteringExpression; + const expression = expressions; const column = grid && grid.getColumnByName(expression.fieldName); const isDate = column ? column.dataType === DateType || column.dataType === DateTimeType : false; const isTime = column ? column.dataType === TimeType : false; diff --git a/projects/igniteui-angular/src/lib/date-common/calendar-container/calendar-container.component.html b/projects/igniteui-angular/src/lib/date-common/calendar-container/calendar-container.component.html index f9929eab2da..0d54b8105b3 100644 --- a/projects/igniteui-angular/src/lib/date-common/calendar-container/calendar-container.component.html +++ b/projects/igniteui-angular/src/lib/date-common/calendar-container/calendar-container.component.html @@ -1,39 +1,44 @@ -
- - -
+ @if (closeButtonLabel || todayButtonLabel) { +
+ @if (closeButtonLabel) { + + } + @if (todayButtonLabel) { + + } +
+ }
- -
- - -
+@if (pickerActions?.template || (closeButtonLabel || todayButtonLabel)) { + +} +@if (pickerActions?.template || (closeButtonLabel || todayButtonLabel)) { +
+ + +
+} diff --git a/projects/igniteui-angular/src/lib/date-common/calendar-container/calendar-container.component.ts b/projects/igniteui-angular/src/lib/date-common/calendar-container/calendar-container.component.ts index 3f8cd15202a..510be7214f1 100644 --- a/projects/igniteui-angular/src/lib/date-common/calendar-container/calendar-container.component.ts +++ b/projects/igniteui-angular/src/lib/date-common/calendar-container/calendar-container.component.ts @@ -1,4 +1,4 @@ -import { NgIf, NgTemplateOutlet } from '@angular/common'; +import { NgTemplateOutlet } from '@angular/common'; import { Component, ViewChild, @@ -20,7 +20,6 @@ import { IgxDividerDirective } from "../../directives/divider/divider.directive" styles: [':host {display: block;}'], templateUrl: 'calendar-container.component.html', imports: [ - NgIf, IgxButtonDirective, IgxRippleDirective, IgxCalendarComponent, diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.html b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.html index ebcfec861f4..81159a032bd 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.html +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.html @@ -1,16 +1,18 @@ - - + - - + + + } - - - + @if (!clearComponents.length && value) { + + + + } diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts index 6638292d7cc..a85061000d8 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts @@ -21,7 +21,7 @@ import { DateRangeDescriptor, DateRangeType } from '../core/dates'; import { IgxOverlayOutletDirective } from '../directives/toggle/toggle.directive'; import { IgxPickerClearComponent, IgxPickerToggleComponent } from '../date-common/public_api'; import { DateTimeUtil } from '../date-common/util/date-time.util'; -import { NgIf, registerLocaleData } from "@angular/common"; +import { registerLocaleData } from "@angular/common"; import localeES from "@angular/common/locales/es"; import localeBg from "@angular/common/locales/bg"; import { IgxDateTimeEditorDirective } from '../directives/date-time-editor/public_api'; @@ -1552,13 +1552,17 @@ export class IgxDatePickerTestKbrdComponent { template: ` - CustomToggle + @if (showCustomToggle) { + CustomToggle + } Prefix - CustomClear + @if (showCustomClear) { + CustomClear + } Suffix Hint `, - imports: [IgxDatePickerComponent, IgxPickerToggleComponent, IgxPrefixDirective, IgxPickerClearComponent, IgxLabelDirective, IgxSuffixDirective, IgxHintDirective, NgIf] + imports: [IgxDatePickerComponent, IgxPickerToggleComponent, IgxPrefixDirective, IgxPickerClearComponent, IgxLabelDirective, IgxSuffixDirective, IgxHintDirective] }) export class IgxDatePickerWithProjectionsComponent { @ViewChild(IgxDatePickerComponent) public datePicker: IgxDatePickerComponent; diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts index d1348e1afbd..a3a6935af7d 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts @@ -25,7 +25,6 @@ import { ViewContainerRef, booleanAttribute } from '@angular/core'; -import { NgIf } from '@angular/common'; import { AbstractControl, ControlValueAccessor, @@ -93,7 +92,6 @@ let NEXT_ID = 0; templateUrl: 'date-picker.component.html', styles: [':host { display: block; }'], imports: [ - NgIf, IgxInputGroupComponent, IgxPrefixDirective, IgxIconComponent, diff --git a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts index e08cf779ed5..8cccd6a2275 100644 --- a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts +++ b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts @@ -10,7 +10,7 @@ import { IgxIconComponent } from '../icon/icon.component'; import { IgxSuffixDirective } from '../directives/suffix/suffix.directive'; import { IgxButtonDirective } from '../directives/button/button.directive'; import { IgxPrefixDirective } from '../directives/prefix/prefix.directive'; -import { NgIf, NgTemplateOutlet, NgClass, NgSwitch, NgSwitchCase, NgSwitchDefault } from '@angular/common'; +import { NgTemplateOutlet, NgClass } from '@angular/common'; /** Represents a range between two dates. */ export interface DateRange { @@ -126,7 +126,7 @@ export class IgxDateRangeInputsBaseComponent extends IgxInputGroupComponent { { provide: IgxInputGroupBase, useExisting: IgxDateRangeStartComponent }, { provide: IgxDateRangeInputsBaseComponent, useExisting: IgxDateRangeStartComponent } ], - imports: [NgIf, NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, NgClass, IgxSuffixDirective, IgxIconComponent, NgSwitch, NgSwitchCase, NgSwitchDefault] + imports: [NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, NgClass, IgxSuffixDirective, IgxIconComponent] }) export class IgxDateRangeStartComponent extends IgxDateRangeInputsBaseComponent { } @@ -161,7 +161,7 @@ export class IgxDateRangeStartComponent extends IgxDateRangeInputsBaseComponent { provide: IgxInputGroupBase, useExisting: IgxDateRangeEndComponent }, { provide: IgxDateRangeInputsBaseComponent, useExisting: IgxDateRangeEndComponent } ], - imports: [NgIf, NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, NgClass, IgxSuffixDirective, IgxIconComponent, NgSwitch, NgSwitchCase, NgSwitchDefault] + imports: [NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, NgClass, IgxSuffixDirective, IgxIconComponent] }) export class IgxDateRangeEndComponent extends IgxDateRangeInputsBaseComponent { } diff --git a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.html b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.html index 79359e0cd14..6ea322900a2 100644 --- a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.html +++ b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.html @@ -28,9 +28,11 @@ role="combobox" aria-haspopup="grid" [attr.aria-expanded]="!collapsed" [attr.aria-labelledby]="label?.id" [value]="value | dateRange: appliedFormat : locale : formatter" /> - - - + @if (!toggleComponents.length) { + + + + } diff --git a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts index 4a5ec190653..e6b5edca0ba 100644 --- a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts +++ b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts @@ -4,7 +4,7 @@ import { OnChanges, OnDestroy, OnInit, Optional, Output, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core'; -import { NgTemplateOutlet, NgIf, getLocaleFirstDayOfWeek } from '@angular/common'; +import { NgTemplateOutlet, getLocaleFirstDayOfWeek } from '@angular/common'; import { AbstractControl, ControlValueAccessor, NgControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, ValidationErrors, Validator @@ -68,7 +68,6 @@ const SingleInputDatesConcatenationString = ' - '; { provide: NG_VALIDATORS, useExisting: IgxDateRangePickerComponent, multi: true } ], imports: [ - NgIf, NgTemplateOutlet, IgxIconComponent, IgxInputGroupComponent, diff --git a/projects/igniteui-angular/src/lib/dialog/dialog-content.component.html b/projects/igniteui-angular/src/lib/dialog/dialog-content.component.html index f92bfab185e..efe481f28d9 100644 --- a/projects/igniteui-angular/src/lib/dialog/dialog-content.component.html +++ b/projects/igniteui-angular/src/lib/dialog/dialog-content.component.html @@ -12,49 +12,54 @@ [attr.role]="role" [attr.aria-labelledby]="titleId" > -
- {{ title }} -
- + @if (title) { +
+ {{ title }} +
+ } + @if (!title) { + + }
- {{ - message - }} - + @if (message) { + + {{ message }} + + } + @if (!message) { + + }
-
- - -
- + @if (leftButtonLabel || rightButtonLabel) { +
+ @if (leftButtonLabel) { + + } + @if (rightButtonLabel) { + + } +
+ } + @if (!leftButtonLabel && !rightButtonLabel) { + + }
diff --git a/projects/igniteui-angular/src/lib/dialog/dialog.component.ts b/projects/igniteui-angular/src/lib/dialog/dialog.component.ts index cb6fc430cc9..09c76ecfdd5 100644 --- a/projects/igniteui-angular/src/lib/dialog/dialog.component.ts +++ b/projects/igniteui-angular/src/lib/dialog/dialog.component.ts @@ -1,4 +1,3 @@ -import { NgIf } from '@angular/common'; import { Component, ElementRef, @@ -56,7 +55,7 @@ let DIALOG_ID = 0; @Component({ selector: 'igx-dialog', templateUrl: 'dialog-content.component.html', - imports: [IgxToggleDirective, IgxFocusTrapDirective, NgIf, IgxFocusDirective, IgxButtonDirective, IgxRippleDirective] + imports: [IgxToggleDirective, IgxFocusTrapDirective, IgxFocusDirective, IgxButtonDirective, IgxRippleDirective] }) export class IgxDialogComponent implements IToggleView, OnInit, OnDestroy, AfterContentInit { private static NEXT_ID = 1; diff --git a/projects/igniteui-angular/src/lib/directives/autocomplete/autocomplete.directive.spec.ts b/projects/igniteui-angular/src/lib/directives/autocomplete/autocomplete.directive.spec.ts index 2d71a3871aa..5d4fac049d4 100644 --- a/projects/igniteui-angular/src/lib/directives/autocomplete/autocomplete.directive.spec.ts +++ b/projects/igniteui-angular/src/lib/directives/autocomplete/autocomplete.directive.spec.ts @@ -10,7 +10,6 @@ import { IgxInputGroupComponent, IgxLabelDirective, IgxPrefixDirective, IgxSuffi import { IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective } from '../../drop-down/public_api'; import { FormsModule, ReactiveFormsModule, UntypedFormGroup, UntypedFormBuilder, Validators } from '@angular/forms'; import { ConnectedPositioningStrategy, VerticalAlignment, HorizontalAlignment } from '../../services/public_api'; -import { NgFor } from '@angular/common'; import { IgxRippleDirective } from '../ripple/ripple.directive'; import { IgxIconComponent } from '../../icon/icon.component'; @@ -949,9 +948,11 @@ export class IgxAutocompletePipeStartsWith implements PipeTransform { clear - - {{town}} - + @for (town of towns | startsWith:townSelected; track town+$index) { + + {{town}} + + } `, imports: [ FormsModule, @@ -964,7 +965,6 @@ export class IgxAutocompletePipeStartsWith implements PipeTransform { IgxIconComponent, IgxAutocompleteDirective, IgxAutocompletePipeStartsWith, - NgFor ] }) class AutocompleteComponent { @@ -979,7 +979,7 @@ class AutocompleteComponent { constructor() { this.towns = [ - 'Sofia', 'Plovdiv', 'Varna', 'Burgas', 'Ruse', 'Stara Zagora', 'Pleven', 'Dobrich', 'Sliven', 'Shumen', 'Pernik', 'Haskovo', 'Yambol', 'Pazardzhik', 'Blagoevgrad', 'Veliko Tarnovo', 'Vratsa', 'Gabrovo', 'Asenovgrad', 'Vidin', 'Kazanlak', 'Kyustendil', 'Kardzhali', 'Montana', 'Dimitrovgrad', 'Targovishte', 'Lovech', 'Silistra', 'Dupnitsa', 'Svishtov', 'Razgrad', 'Gorna Oryahovitsa', 'Smolyan', 'Petrich', 'Sandanski', 'Samokov', 'Sevlievo', 'Lom', 'Karlovo', 'Velingrad', 'Nova Zagora', 'Troyan', 'Aytos', 'Botevgrad', 'Gotse Delchev', 'Peshtera', 'Harmanli', 'Karnobat', 'Svilengrad', 'Panagyurishte', 'Chirpan', 'Popovo', 'Rakovski', 'Radomir', 'Novi Iskar', 'Kozloduy', 'Parvomay', 'Berkovitsa', 'Cherven Bryag', 'Pomorie', 'Ihtiman', 'Radnevo', 'Provadiya', 'Novi Pazar', 'Razlog', 'Byala Slatina', 'Nesebar', 'Balchik', 'Kostinbrod', 'Stamboliyski', 'Kavarna', 'Knezha', 'Pavlikeni', 'Mezdra', 'Etropole', 'Levski', 'Teteven', 'Elhovo', 'Bankya', 'Tryavna', 'Lukovit', 'Tutrakan', 'Sredets', 'Sopot', 'Byala', 'Veliki Preslav', 'Isperih', 'Belene', 'Omurtag', 'Bansko', 'Krichim', 'Galabovo', 'Devnya', 'Septemvri', 'Rakitovo', 'Lyaskovets', 'Svoge', 'Aksakovo', 'Kubrat', 'Dryanovo', 'Beloslav', 'Pirdop', 'Lyubimets', 'Momchilgrad', 'Slivnitsa', 'Hisarya', 'Zlatograd', 'Kostenets', 'Devin', 'General Toshevo', 'Simeonovgrad', 'Simitli', 'Elin Pelin', 'Dolni Chiflik', 'Tervel', 'Dulovo', 'Varshets', 'Kotel', 'Madan', 'Straldzha', 'Saedinenie', 'Bobov Dol', 'Tsarevo', 'Kuklen', 'Tvarditsa', 'Yakoruda', 'Elena', 'Topolovgrad', 'Bozhurishte', 'Chepelare', 'Oryahovo', 'Sozopol', 'Belogradchik', 'Perushtitsa', 'Zlatitsa', 'Strazhitsa', 'Krumovgrad', 'Kameno', 'Dalgopol', 'Vetovo', 'Suvorovo', 'Dolni Dabnik', 'Dolna Banya', 'Pravets', 'Nedelino', 'Polski Trambesh', 'Trastenik', 'Bratsigovo', 'Koynare', 'Godech', 'Slavyanovo', 'Dve Mogili', 'Kostandovo', 'Debelets', 'Strelcha', 'Sapareva Banya', 'Ignatievo', 'Smyadovo', 'Breznik', 'Sveti Vlas', 'Nikopol', 'Shivachevo', 'Belovo', 'Tsar Kaloyan', 'Ivaylovgrad', 'Valchedram', 'Marten', 'Glodzhevo', 'Sarnitsa', 'Letnitsa', 'Varbitsa', 'Iskar', 'Ardino', 'Shabla', 'Rudozem', 'Vetren', 'Kresna', 'Banya', 'Batak', 'Maglizh', 'Valchi Dol', 'Gulyantsi', 'Dragoman', 'Zavet', 'Kran', 'Miziya', 'Primorsko', 'Sungurlare', 'Dolna Mitropoliya', 'Krivodol', 'Kula', 'Kalofer', 'Slivo Pole', 'Kaspichan', 'Apriltsi', 'Belitsa', 'Roman', 'Dzhebel', 'Dolna Oryahovitsa', 'Buhovo', 'Gurkovo', 'Pavel Banya', 'Nikolaevo', 'Yablanitsa', 'Kableshkovo', 'Opaka', 'Rila', 'Ugarchin', 'Dunavtsi', 'Dobrinishte', 'Hadzhidimovo', 'Bregovo', 'Byala Cherkva', 'Zlataritsa', 'Kocherinovo', 'Dospat', 'Tran', 'Sadovo', 'Laki', 'Koprivshtitsa', 'Malko Tarnovo', 'Loznitsa', 'Obzor', 'Kilifarevo', 'Borovo', 'Batanovtsi', 'Chernomorets', 'Aheloy', 'Byala', 'Pordim', 'Suhindol', 'Merichleri', 'Glavinitsa', 'Chiprovtsi', 'Kermen', 'Brezovo', 'Plachkovtsi', 'Zemen', 'Balgarovo', 'Alfatar', 'Boychinovtsi', 'Gramada', 'Senovo', 'Momin Prohod', 'Kaolinovo', 'Shipka', 'Antonovo', 'Ahtopol', 'Boboshevo', 'Bolyarovo', 'Brusartsi', 'Klisura', 'Dimovo', 'Kiten', 'Pliska', 'Madzharovo', 'Melnik' + 'Sofia', 'Plovdiv', 'Varna', 'Burgas', 'Ruse', 'Stara Zagora', 'Pleven', 'Dobrich', 'Sliven', 'Shumen', 'Pernik', 'Haskovo', 'Yambol', 'Pazardzhik', 'Blagoevgrad', 'Veliko Tarnovo', 'Vratsa', 'Gabrovo', 'Asenovgrad', 'Vidin', 'Kazanlak', 'Kyustendil', 'Kardzhali', 'Montana', 'Dimitrovgrad', 'Targovishte', 'Lovech', 'Silistra', 'Dupnitsa', 'Svishtov', 'Razgrad', 'Gorna Oryahovitsa', 'Smolyan', 'Petrich', 'Sandanski', 'Samokov', 'Sevlievo', 'Lom', 'Karlovo', 'Velingrad', 'Nova Zagora', 'Troyan', 'Aytos', 'Botevgrad', 'Gotse Delchev', 'Peshtera', 'Harmanli', 'Karnobat', 'Svilengrad', 'Panagyurishte', 'Chirpan', 'Popovo', 'Rakovski', 'Radomir', 'Novi Iskar', 'Kozloduy', 'Parvomay', 'Berkovitsa', 'Cherven Bryag', 'Pomorie', 'Ihtiman', 'Radnevo', 'Provadiya', 'Novi Pazar', 'Razlog', 'Byala Slatina', 'Nesebar', 'Balchik', 'Kostinbrod', 'Stamboliyski', 'Kavarna', 'Knezha', 'Pavlikeni', 'Mezdra', 'Etropole', 'Levski', 'Teteven', 'Elhovo', 'Bankya', 'Tryavna', 'Lukovit', 'Tutrakan', 'Sredets', 'Sopot', 'Byala', 'Veliki Preslav', 'Isperih', 'Belene', 'Omurtag', 'Bansko', 'Krichim', 'Galabovo', 'Devnya', 'Septemvri', 'Rakitovo', 'Lyaskovets', 'Svoge', 'Aksakovo', 'Kubrat', 'Dryanovo', 'Beloslav', 'Pirdop', 'Lyubimets', 'Momchilgrad', 'Slivnitsa', 'Hisarya', 'Zlatograd', 'Kostenets', 'Devin', 'General Toshevo', 'Simeonovgrad', 'Simitli', 'Elin Pelin', 'Dolni Chiflik', 'Tervel', 'Dulovo', 'Varshets', 'Kotel', 'Madan', 'Straldzha', 'Saedinenie', 'Bobov Dol', 'Tsarevo', 'Kuklen', 'Tvarditsa', 'Yakoruda', 'Elena', 'Topolovgrad', 'Bozhurishte', 'Chepelare', 'Oryahovo', 'Sozopol', 'Belogradchik', 'Perushtitsa', 'Zlatitsa', 'Strazhitsa', 'Krumovgrad', 'Kameno', 'Dalgopol', 'Vetovo', 'Suvorovo', 'Dolni Dabnik', 'Dolna Banya', 'Pravets', 'Nedelino', 'Polski Trambesh', 'Trastenik', 'Bratsigovo', 'Koynare', 'Godech', 'Slavyanovo', 'Dve Mogili', 'Kostandovo', 'Debelets', 'Strelcha', 'Sapareva Banya', 'Ignatievo', 'Smyadovo', 'Breznik', 'Sveti Vlas', 'Nikopol', 'Shivachevo', 'Belovo', 'Tsar Kaloyan', 'Ivaylovgrad', 'Valchedram', 'Marten', 'Glodzhevo', 'Sarnitsa', 'Letnitsa', 'Varbitsa', 'Iskar', 'Ardino', 'Shabla', 'Rudozem', 'Vetren', 'Kresna', 'Banya', 'Batak', 'Maglizh', 'Valchi Dol', 'Gulyantsi', 'Dragoman', 'Zavet', 'Kran', 'Miziya', 'Primorsko', 'Sungurlare', 'Dolna Mitropoliya', 'Krivodol', 'Kula', 'Kalofer', 'Slivo Pole', 'Kaspichan', 'Apriltsi', 'Belitsa', 'Roman', 'Dzhebel', 'Dolna Oryahovitsa', 'Buhovo', 'Gurkovo', 'Pavel Banya', 'Nikolaevo', 'Yablanitsa', 'Kableshkovo', 'Opaka', 'Rila', 'Ugarchin', 'Dunavtsi', 'Dobrinishte', 'Hadzhidimovo', 'Bregovo', 'Byala Cherkva', 'Zlataritsa', 'Kocherinovo', 'Dospat', 'Tran', 'Sadovo', 'Laki', 'Koprivshtitsa', 'Malko Tarnovo', 'Loznitsa', 'Obzor', 'Kilifarevo', 'Borovo', 'Batanovtsi', 'Chernomorets', 'Aheloy', 'Pordim', 'Suhindol', 'Merichleri', 'Glavinitsa', 'Chiprovtsi', 'Kermen', 'Brezovo', 'Plachkovtsi', 'Zemen', 'Balgarovo', 'Alfatar', 'Boychinovtsi', 'Gramada', 'Senovo', 'Momin Prohod', 'Kaolinovo', 'Shipka', 'Antonovo', 'Ahtopol', 'Boboshevo', 'Bolyarovo', 'Brusartsi', 'Klisura', 'Dimovo', 'Kiten', 'Pliska', 'Madzharovo', 'Melnik' ]; } public selectionChanging() { } @@ -997,9 +997,11 @@ class AutocompleteComponent { [igxAutocomplete]='townsPanel' #textarea> - - {{town}} - + @for (town of towns | startsWith:townSelected; track town+$index) { + + {{town}} + + } `, imports: [ FormsModule, @@ -1008,7 +1010,6 @@ class AutocompleteComponent { IgxDropDownComponent, IgxDropDownItemComponent, IgxAutocompletePipeStartsWith, - NgFor ] }) class AutocompleteInputComponent extends AutocompleteComponent { @@ -1028,9 +1029,11 @@ class AutocompleteInputComponent extends AutocompleteComponent { clear - - {{town}} - + @for (town of towns | startsWith:townSelected; track town+$index) { + + {{town}} + + } @@ -1048,7 +1051,6 @@ class AutocompleteInputComponent extends AutocompleteComponent { IgxIconComponent, IgxAutocompleteDirective, IgxAutocompletePipeStartsWith, - NgFor ] }) @@ -1065,7 +1067,7 @@ class AutocompleteFormComponent { constructor(fb: UntypedFormBuilder) { this.towns = [ - 'Sofia', 'Plovdiv', 'Varna', 'Burgas', 'Ruse', 'Stara Zagora', 'Pleven', 'Dobrich', 'Sliven', 'Shumen', 'Pernik', 'Haskovo', 'Yambol', 'Pazardzhik', 'Blagoevgrad', 'Veliko Tarnovo', 'Vratsa', 'Gabrovo', 'Asenovgrad', 'Vidin', 'Kazanlak', 'Kyustendil', 'Kardzhali', 'Montana', 'Dimitrovgrad', 'Targovishte', 'Lovech', 'Silistra', 'Dupnitsa', 'Svishtov', 'Razgrad', 'Gorna Oryahovitsa', 'Smolyan', 'Petrich', 'Sandanski', 'Samokov', 'Sevlievo', 'Lom', 'Karlovo', 'Velingrad', 'Nova Zagora', 'Troyan', 'Aytos', 'Botevgrad', 'Gotse Delchev', 'Peshtera', 'Harmanli', 'Karnobat', 'Svilengrad', 'Panagyurishte', 'Chirpan', 'Popovo', 'Rakovski', 'Radomir', 'Novi Iskar', 'Kozloduy', 'Parvomay', 'Berkovitsa', 'Cherven Bryag', 'Pomorie', 'Ihtiman', 'Radnevo', 'Provadiya', 'Novi Pazar', 'Razlog', 'Byala Slatina', 'Nesebar', 'Balchik', 'Kostinbrod', 'Stamboliyski', 'Kavarna', 'Knezha', 'Pavlikeni', 'Mezdra', 'Etropole', 'Levski', 'Teteven', 'Elhovo', 'Bankya', 'Tryavna', 'Lukovit', 'Tutrakan', 'Sredets', 'Sopot', 'Byala', 'Veliki Preslav', 'Isperih', 'Belene', 'Omurtag', 'Bansko', 'Krichim', 'Galabovo', 'Devnya', 'Septemvri', 'Rakitovo', 'Lyaskovets', 'Svoge', 'Aksakovo', 'Kubrat', 'Dryanovo', 'Beloslav', 'Pirdop', 'Lyubimets', 'Momchilgrad', 'Slivnitsa', 'Hisarya', 'Zlatograd', 'Kostenets', 'Devin', 'General Toshevo', 'Simeonovgrad', 'Simitli', 'Elin Pelin', 'Dolni Chiflik', 'Tervel', 'Dulovo', 'Varshets', 'Kotel', 'Madan', 'Straldzha', 'Saedinenie', 'Bobov Dol', 'Tsarevo', 'Kuklen', 'Tvarditsa', 'Yakoruda', 'Elena', 'Topolovgrad', 'Bozhurishte', 'Chepelare', 'Oryahovo', 'Sozopol', 'Belogradchik', 'Perushtitsa', 'Zlatitsa', 'Strazhitsa', 'Krumovgrad', 'Kameno', 'Dalgopol', 'Vetovo', 'Suvorovo', 'Dolni Dabnik', 'Dolna Banya', 'Pravets', 'Nedelino', 'Polski Trambesh', 'Trastenik', 'Bratsigovo', 'Koynare', 'Godech', 'Slavyanovo', 'Dve Mogili', 'Kostandovo', 'Debelets', 'Strelcha', 'Sapareva Banya', 'Ignatievo', 'Smyadovo', 'Breznik', 'Sveti Vlas', 'Nikopol', 'Shivachevo', 'Belovo', 'Tsar Kaloyan', 'Ivaylovgrad', 'Valchedram', 'Marten', 'Glodzhevo', 'Sarnitsa', 'Letnitsa', 'Varbitsa', 'Iskar', 'Ardino', 'Shabla', 'Rudozem', 'Vetren', 'Kresna', 'Banya', 'Batak', 'Maglizh', 'Valchi Dol', 'Gulyantsi', 'Dragoman', 'Zavet', 'Kran', 'Miziya', 'Primorsko', 'Sungurlare', 'Dolna Mitropoliya', 'Krivodol', 'Kula', 'Kalofer', 'Slivo Pole', 'Kaspichan', 'Apriltsi', 'Belitsa', 'Roman', 'Dzhebel', 'Dolna Oryahovitsa', 'Buhovo', 'Gurkovo', 'Pavel Banya', 'Nikolaevo', 'Yablanitsa', 'Kableshkovo', 'Opaka', 'Rila', 'Ugarchin', 'Dunavtsi', 'Dobrinishte', 'Hadzhidimovo', 'Bregovo', 'Byala Cherkva', 'Zlataritsa', 'Kocherinovo', 'Dospat', 'Tran', 'Sadovo', 'Laki', 'Koprivshtitsa', 'Malko Tarnovo', 'Loznitsa', 'Obzor', 'Kilifarevo', 'Borovo', 'Batanovtsi', 'Chernomorets', 'Aheloy', 'Byala', 'Pordim', 'Suhindol', 'Merichleri', 'Glavinitsa', 'Chiprovtsi', 'Kermen', 'Brezovo', 'Plachkovtsi', 'Zemen', 'Balgarovo', 'Alfatar', 'Boychinovtsi', 'Gramada', 'Senovo', 'Momin Prohod', 'Kaolinovo', 'Shipka', 'Antonovo', 'Ahtopol', 'Boboshevo', 'Bolyarovo', 'Brusartsi', 'Klisura', 'Dimovo', 'Kiten', 'Pliska', 'Madzharovo', 'Melnik' + 'Sofia', 'Plovdiv', 'Varna', 'Burgas', 'Ruse', 'Stara Zagora', 'Pleven', 'Dobrich', 'Sliven', 'Shumen', 'Pernik', 'Haskovo', 'Yambol', 'Pazardzhik', 'Blagoevgrad', 'Veliko Tarnovo', 'Vratsa', 'Gabrovo', 'Asenovgrad', 'Vidin', 'Kazanlak', 'Kyustendil', 'Kardzhali', 'Montana', 'Dimitrovgrad', 'Targovishte', 'Lovech', 'Silistra', 'Dupnitsa', 'Svishtov', 'Razgrad', 'Gorna Oryahovitsa', 'Smolyan', 'Petrich', 'Sandanski', 'Samokov', 'Sevlievo', 'Lom', 'Karlovo', 'Velingrad', 'Nova Zagora', 'Troyan', 'Aytos', 'Botevgrad', 'Gotse Delchev', 'Peshtera', 'Harmanli', 'Karnobat', 'Svilengrad', 'Panagyurishte', 'Chirpan', 'Popovo', 'Rakovski', 'Radomir', 'Novi Iskar', 'Kozloduy', 'Parvomay', 'Berkovitsa', 'Cherven Bryag', 'Pomorie', 'Ihtiman', 'Radnevo', 'Provadiya', 'Novi Pazar', 'Razlog', 'Byala Slatina', 'Nesebar', 'Balchik', 'Kostinbrod', 'Stamboliyski', 'Kavarna', 'Knezha', 'Pavlikeni', 'Mezdra', 'Etropole', 'Levski', 'Teteven', 'Elhovo', 'Bankya', 'Tryavna', 'Lukovit', 'Tutrakan', 'Sredets', 'Sopot', 'Byala', 'Veliki Preslav', 'Isperih', 'Belene', 'Omurtag', 'Bansko', 'Krichim', 'Galabovo', 'Devnya', 'Septemvri', 'Rakitovo', 'Lyaskovets', 'Svoge', 'Aksakovo', 'Kubrat', 'Dryanovo', 'Beloslav', 'Pirdop', 'Lyubimets', 'Momchilgrad', 'Slivnitsa', 'Hisarya', 'Zlatograd', 'Kostenets', 'Devin', 'General Toshevo', 'Simeonovgrad', 'Simitli', 'Elin Pelin', 'Dolni Chiflik', 'Tervel', 'Dulovo', 'Varshets', 'Kotel', 'Madan', 'Straldzha', 'Saedinenie', 'Bobov Dol', 'Tsarevo', 'Kuklen', 'Tvarditsa', 'Yakoruda', 'Elena', 'Topolovgrad', 'Bozhurishte', 'Chepelare', 'Oryahovo', 'Sozopol', 'Belogradchik', 'Perushtitsa', 'Zlatitsa', 'Strazhitsa', 'Krumovgrad', 'Kameno', 'Dalgopol', 'Vetovo', 'Suvorovo', 'Dolni Dabnik', 'Dolna Banya', 'Pravets', 'Nedelino', 'Polski Trambesh', 'Trastenik', 'Bratsigovo', 'Koynare', 'Godech', 'Slavyanovo', 'Dve Mogili', 'Kostandovo', 'Debelets', 'Strelcha', 'Sapareva Banya', 'Ignatievo', 'Smyadovo', 'Breznik', 'Sveti Vlas', 'Nikopol', 'Shivachevo', 'Belovo', 'Tsar Kaloyan', 'Ivaylovgrad', 'Valchedram', 'Marten', 'Glodzhevo', 'Sarnitsa', 'Letnitsa', 'Varbitsa', 'Iskar', 'Ardino', 'Shabla', 'Rudozem', 'Vetren', 'Kresna', 'Banya', 'Batak', 'Maglizh', 'Valchi Dol', 'Gulyantsi', 'Dragoman', 'Zavet', 'Kran', 'Miziya', 'Primorsko', 'Sungurlare', 'Dolna Mitropoliya', 'Krivodol', 'Kula', 'Kalofer', 'Slivo Pole', 'Kaspichan', 'Apriltsi', 'Belitsa', 'Roman', 'Dzhebel', 'Dolna Oryahovitsa', 'Buhovo', 'Gurkovo', 'Pavel Banya', 'Nikolaevo', 'Yablanitsa', 'Kableshkovo', 'Opaka', 'Rila', 'Ugarchin', 'Dunavtsi', 'Dobrinishte', 'Hadzhidimovo', 'Bregovo', 'Byala Cherkva', 'Zlataritsa', 'Kocherinovo', 'Dospat', 'Tran', 'Sadovo', 'Laki', 'Koprivshtitsa', 'Malko Tarnovo', 'Loznitsa', 'Obzor', 'Kilifarevo', 'Borovo', 'Batanovtsi', 'Chernomorets', 'Aheloy', 'Pordim', 'Suhindol', 'Merichleri', 'Glavinitsa', 'Chiprovtsi', 'Kermen', 'Brezovo', 'Plachkovtsi', 'Zemen', 'Balgarovo', 'Alfatar', 'Boychinovtsi', 'Gramada', 'Senovo', 'Momin Prohod', 'Kaolinovo', 'Shipka', 'Antonovo', 'Ahtopol', 'Boboshevo', 'Bolyarovo', 'Brusartsi', 'Klisura', 'Dimovo', 'Kiten', 'Pliska', 'Madzharovo', 'Melnik' ]; this.reactiveForm = fb.group({ towns: ['', Validators.required] diff --git a/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.spec.ts b/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.spec.ts index cb0001c7d44..de893b9bd94 100644 --- a/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.spec.ts +++ b/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.spec.ts @@ -15,7 +15,6 @@ import { IgxDragIgnoreDirective } from './drag-drop.directive'; import { IgxIconComponent } from '../../icon/icon.component'; -import { NgFor } from '@angular/common'; describe('General igxDrag/igxDrop', () => { let fix: ComponentFixture; @@ -2108,21 +2107,25 @@ class TestDragDropStrategiesComponent extends TestDragDropLinkedSingleComponent drag_indicator Movies list -
-
- drag_indicator - {{category.text}} -
-
+ @for (category of categoriesNotes; track category) { +
drag_indicator - {{note.text}} + {{category.text}}
+ @for (note of getCategoryMovies(category.text); track note) { +
+
+ drag_indicator + {{note.text}} +
+
+ }
-
+ }
`, - imports: [NgFor, IgxIconComponent, IgxDragDirective, IgxDragHandleDirective] + imports: [IgxIconComponent, IgxDragDirective, IgxDragHandleDirective] }) class TestDragDropNestedComponent extends TestDragDropComponent { public categoriesNotes = [ diff --git a/projects/igniteui-angular/src/lib/directives/filter/filter.directive.spec.ts b/projects/igniteui-angular/src/lib/directives/filter/filter.directive.spec.ts index d8ea891bfa5..49ddf007b6f 100644 --- a/projects/igniteui-angular/src/lib/directives/filter/filter.directive.spec.ts +++ b/projects/igniteui-angular/src/lib/directives/filter/filter.directive.spec.ts @@ -5,7 +5,6 @@ import { IgxListComponent } from '../../list/list.component'; import { IgxFilterDirective, IgxFilterOptions, IgxFilterPipe } from './filter.directive'; import { configureTestSuite } from '../../test-utils/configure-suite'; -import { NgFor } from '@angular/common'; describe('Filter', () => { configureTestSuite(); @@ -214,11 +213,11 @@ class DeclarativeListTestComponent { @Component({ template: ` - - {{item.text}} - + @for (item of dataSourceItems | igxFilter: fo; track item) { + {{item.text}} + } `, - imports: [IgxListComponent, IgxListItemComponent, IgxFilterPipe, NgFor] + imports: [IgxListComponent, IgxListItemComponent, IgxFilterPipe] }) class DynamicListTestComponent { @ViewChild(IgxListComponent, { static: true }) public list: IgxListComponent; diff --git a/projects/igniteui-angular/src/lib/directives/focus-trap/focus-trap.directive.spec.ts b/projects/igniteui-angular/src/lib/directives/focus-trap/focus-trap.directive.spec.ts index bfd3f55b919..e960b7b34e6 100644 --- a/projects/igniteui-angular/src/lib/directives/focus-trap/focus-trap.directive.spec.ts +++ b/projects/igniteui-angular/src/lib/directives/focus-trap/focus-trap.directive.spec.ts @@ -6,7 +6,6 @@ import { IgxFocusTrapDirective } from './focus-trap.directive'; import { configureTestSuite } from '../../test-utils/configure-suite'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { UIInteractions } from '../../test-utils/ui-interactions.spec'; -import { NgIf } from '@angular/common'; describe('igxFocusTrap', () => { configureTestSuite(); @@ -171,12 +170,20 @@ describe('igxFocusTrap', () => { template: `

-
+ @if (showInput) { + + } +

-
- + @if (showInput) { + + } +
+ @if (showButton) { + + }
`, - imports: [IgxFocusTrapDirective, NgIf] + imports: [IgxFocusTrapDirective] }) class TrapFocusTestComponent { public showInput = true; diff --git a/projects/igniteui-angular/src/lib/directives/for-of/for_of.directive.spec.ts b/projects/igniteui-angular/src/lib/directives/for-of/for_of.directive.spec.ts index abc46f747e0..cea8758dec5 100644 --- a/projects/igniteui-angular/src/lib/directives/for-of/for_of.directive.spec.ts +++ b/projects/igniteui-angular/src/lib/directives/for-of/for_of.directive.spec.ts @@ -1,4 +1,4 @@ -import { AsyncPipe, NgClass, NgFor, NgForOfContext, NgIf } from '@angular/common'; +import { AsyncPipe, NgClass, NgForOfContext } from '@angular/common'; import { AfterViewInit, ChangeDetectorRef, @@ -1514,22 +1514,24 @@ export class VerticalVirtualComponent extends VirtualComponent { @Component({ template: ` -
- -
-
{{rowData['1']}}
-
{{rowData['2']}}
-
{{rowData['3']}}
-
{{rowData['4']}}
-
{{rowData['5']}}
-
-
-
+ @if (exists) { +
+ +
+
{{rowData['1']}}
+
{{rowData['2']}}
+
{{rowData['3']}}
+
{{rowData['4']}}
+
{{rowData['5']}}
+
+
+
+ } `, - imports: [TestIgxForOfDirective, IgxForOfDirective, NgIf] + imports: [TestIgxForOfDirective, IgxForOfDirective] }) export class VerticalVirtualDestroyComponent extends VerticalVirtualComponent { public exists = true; @@ -1551,7 +1553,8 @@ export class VerticalVirtualDestroyComponent extends VerticalVirtualComponent { -
+ @if (exists) { +
+ } `, - imports: [IgxForOfDirective, NgIf] + imports: [IgxForOfDirective] }) export class VerticalVirtualCreateComponent extends VerticalVirtualComponent { @ViewChild('scrollContainer2', { read: IgxForOfDirective, static: false }) @@ -1585,18 +1589,20 @@ export class VerticalVirtualCreateComponent extends VerticalVirtualComponent { [style.overflow]='"hidden"' [style.float]='"left"' [style.position]='"relative"'> -
- + @for (rowData of data; track rowData) { +
+
{{rowData[col.field]}}
-
-
+
+
+ }
`, - imports: [TestIgxForOfDirective, IgxForOfDirective, NgFor] + imports: [TestIgxForOfDirective, IgxForOfDirective] }) export class HorizontalVirtualComponent extends VirtualComponent { public override width = '800px'; diff --git a/projects/igniteui-angular/src/lib/directives/radio/radio-group.directive.spec.ts b/projects/igniteui-angular/src/lib/directives/radio/radio-group.directive.spec.ts index 468cb51d5c9..b8c3c2391f6 100644 --- a/projects/igniteui-angular/src/lib/directives/radio/radio-group.directive.spec.ts +++ b/projects/igniteui-angular/src/lib/directives/radio/radio-group.directive.spec.ts @@ -7,7 +7,6 @@ import { configureTestSuite } from '../../test-utils/configure-suite'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { By } from '@angular/platform-browser'; import { IgxRadioComponent } from '../../radio/radio.component'; -import { NgFor } from '@angular/common'; describe('IgxRadioGroupDirective', () => { configureTestSuite(); @@ -281,12 +280,14 @@ class RadioGroupSimpleComponent { @Component({ template: ` - - {{item}} - - -`, - imports: [IgxRadioComponent, IgxRadioGroupDirective, NgFor] + @for (item of ['Foo', 'Bar', 'Baz']; track item) { + + {{item}} + + } + + `, + imports: [IgxRadioComponent, IgxRadioGroupDirective] }) class RadioGroupComponent { @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) public radioGroup: IgxRadioGroupDirective; @@ -294,12 +295,14 @@ class RadioGroupComponent { @Component({ template: ` - - {{item}} - - -`, - imports: [IgxRadioComponent, IgxRadioGroupDirective, NgFor] + @for (item of ['Foo', 'Bar', 'Baz']; track item) { + + {{item}} + + } + + `, + imports: [IgxRadioComponent, IgxRadioGroupDirective] }) class RadioGroupRequiredComponent { @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) public radioGroup: IgxRadioGroupDirective; @@ -334,12 +337,14 @@ class RadioGroupOnPushComponent { @Component({ template: ` - - {{item}} - - -`, - imports: [IgxRadioComponent, IgxRadioGroupDirective, NgFor, FormsModule] + @for (item of seasons; track item) { + + {{item}} + + } + + `, + imports: [IgxRadioComponent, IgxRadioGroupDirective, FormsModule] }) class RadioGroupWithModelComponent { @ViewChild('radioGroupSeasons', { read: IgxRadioGroupDirective, static: true }) public radioGroup: IgxRadioGroupDirective; @@ -358,13 +363,15 @@ class RadioGroupWithModelComponent { template: `
- - {{item}} - + @for (item of seasons; track item) { + + {{item}} + + }
`, - imports: [IgxRadioComponent, IgxRadioGroupDirective, NgFor, ReactiveFormsModule] + imports: [IgxRadioComponent, IgxRadioGroupDirective, ReactiveFormsModule] }) class RadioGroupReactiveFormsComponent { public seasons = [ @@ -410,13 +417,15 @@ class RadioGroupReactiveFormsComponent { template: `
-
-

{{ choice }}

-
+ @for (choice of choices; track choice) { +
+

{{ choice }}

+
+ }
`, - imports: [IgxRadioComponent, IgxRadioGroupDirective, NgFor, ReactiveFormsModule] + imports: [IgxRadioComponent, IgxRadioGroupDirective, ReactiveFormsModule] }) class RadioGroupDeepProjectionComponent { diff --git a/projects/igniteui-angular/src/lib/drop-down/drop-down.component.html b/projects/igniteui-angular/src/lib/drop-down/drop-down.component.html index 5d582b8c918..ea1e07c9c46 100644 --- a/projects/igniteui-angular/src/lib/drop-down/drop-down.component.html +++ b/projects/igniteui-angular/src/lib/drop-down/drop-down.component.html @@ -4,10 +4,10 @@ (opening)="onToggleOpening($event)" (opened)="onToggleOpened()" (closing)="onToggleClosing($event)" (closed)="onToggleClosed()">
- + [style.height]="height" + [style.maxHeight]="maxHeight"> + @if (!collapsed) { - + }
diff --git a/projects/igniteui-angular/src/lib/drop-down/drop-down.component.spec.ts b/projects/igniteui-angular/src/lib/drop-down/drop-down.component.spec.ts index 62440af898b..6ce79bc3fc3 100644 --- a/projects/igniteui-angular/src/lib/drop-down/drop-down.component.spec.ts +++ b/projects/igniteui-angular/src/lib/drop-down/drop-down.component.spec.ts @@ -16,7 +16,6 @@ import { IgxForOfDirective } from '../directives/for-of/for_of.directive'; import { IgxDropDownItemBaseDirective } from './drop-down-item.base'; import { IgxSelectionAPIService } from '../core/selection'; import { IgxButtonDirective } from '../directives/button/button.directive'; -import { NgFor } from '@angular/common'; import { ConnectedPositioningStrategy, HorizontalAlignment, OverlaySettings, VerticalAlignment } from '../services/public_api'; const CSS_CLASS_DROP_DOWN_BASE = 'igx-drop-down'; @@ -1298,12 +1297,14 @@ describe('IgxDropDown ', () => { template: ` - - {{item.field}} - + [allowItemsFocus]="true" style="--ig-size: var(--ig-size-medium);"> + @for (item of items; track item) { + + {{item.field}} + + } `, - imports: [IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective, NgFor] + imports: [IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective] }) class IgxDropDownTestComponent { @@ -1337,17 +1338,21 @@ class IgxDropDownTestComponent { template: ` - - {{ item.field }} - + @for (item of items; track item) { + + {{ item.field }} + + } - - {{ item.field }} - + @for (item of items; track item) { + + {{ item.field }} + + } `, - imports: [IgxDropDownComponent, IgxDropDownItemComponent, NgFor] + imports: [IgxDropDownComponent, IgxDropDownItemComponent] }) class DoubleIgxDropDownComponent implements OnInit { @@ -1396,13 +1401,15 @@ class DoubleIgxDropDownComponent implements OnInit { - - {{ item.field }} - + (opening)="onToggleOpening()" (opened)="onToggleOpened()" + (closing)="onToggleClosing()" (closed)="onToggleClosed()" [width]="'400px'" [height]="'400px'"> + @for (item of items; track item) { + + {{ item.field }} + + } `, - imports: [IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective, IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent, NgFor] + imports: [IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective, IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent] }) class IgxDropDownAnchorTestComponent { @ViewChild(IgxTabsComponent, { static: true }) @@ -1434,11 +1441,13 @@ class IgxDropDownAnchorTestComponent { @Component({ template: ` - - {{ item.field }} - + @for (item of items; track item) { + + {{ item.field }} + + } `, - imports: [IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective, NgFor] + imports: [IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective] }) class InputWithDropDownDirectiveComponent { @ViewChild(IgxDropDownComponent, { read: IgxDropDownComponent, static: true }) @@ -1457,13 +1466,17 @@ class InputWithDropDownDirectiveComponent { @Component({ template: ` - - - {{ child.name }} - - + @for (parent of data; track parent) { + + @for (child of parent.children; track child) { + + {{ child.name }} + + } + + } `, - imports: [IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownGroupComponent, NgFor] + imports: [IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownGroupComponent] }) class GroupDropDownComponent { @ViewChild(IgxDropDownComponent, { read: IgxDropDownComponent, static: true }) diff --git a/projects/igniteui-angular/src/lib/drop-down/drop-down.component.ts b/projects/igniteui-angular/src/lib/drop-down/drop-down.component.ts index d40ae93e004..30d8ccab1eb 100644 --- a/projects/igniteui-angular/src/lib/drop-down/drop-down.component.ts +++ b/projects/igniteui-angular/src/lib/drop-down/drop-down.component.ts @@ -30,7 +30,7 @@ import { IgxDropDownItemBaseDirective } from './drop-down-item.base'; import { IgxForOfToken } from '../directives/for-of/for_of.directive'; import { take } from 'rxjs/operators'; import { OverlaySettings } from '../services/overlay/utilities'; -import { DOCUMENT, NgIf } from '@angular/common'; +import { DOCUMENT } from '@angular/common'; import { ConnectedPositioningStrategy } from '../services/public_api'; /** @@ -54,7 +54,7 @@ import { ConnectedPositioningStrategy } from '../services/public_api'; selector: 'igx-drop-down', templateUrl: './drop-down.component.html', providers: [{ provide: IGX_DROPDOWN_BASE, useExisting: IgxDropDownComponent }], - imports: [IgxToggleDirective, NgIf] + imports: [IgxToggleDirective] }) export class IgxDropDownComponent extends IgxDropDownBaseDirective implements IDropDownBase, OnChanges, AfterViewInit, OnDestroy { /** diff --git a/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel-header.component.html b/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel-header.component.html index abdf2d1d6bf..685d574bce9 100644 --- a/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel-header.component.html +++ b/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel-header.component.html @@ -6,12 +6,15 @@
- - - + @if (iconTemplate) { + + } + @if (!iconTemplate) { + + + }
diff --git a/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel-header.component.ts b/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel-header.component.ts index 9f6649582ad..a3702617f75 100644 --- a/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel-header.component.ts +++ b/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel-header.component.ts @@ -17,7 +17,6 @@ import { IgxExpansionPanelIconDirective } from './expansion-panel.directives'; import { IGX_EXPANSION_PANEL_COMPONENT, IgxExpansionPanelBase, IExpansionPanelCancelableEventArgs } from './expansion-panel.common'; import { mkenum } from '../core/utils'; import { IgxIconComponent } from '../icon/icon.component'; -import { NgIf } from '@angular/common'; /** * @hidden @@ -33,7 +32,7 @@ export type ExpansionPanelHeaderIconPosition = (typeof ExpansionPanelHeaderIconP @Component({ selector: 'igx-expansion-panel-header', templateUrl: 'expansion-panel-header.component.html', - imports: [NgIf, IgxIconComponent] + imports: [IgxIconComponent] }) export class IgxExpansionPanelHeaderComponent { /** diff --git a/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.component.html b/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.component.html index 78902268be3..da28c2f0e1e 100644 --- a/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.component.html +++ b/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.component.html @@ -1,2 +1,4 @@ - +@if (!collapsed) { + +} diff --git a/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.component.ts b/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.component.ts index f2f643adb21..dbbf42b64ae 100644 --- a/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.component.ts +++ b/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.component.ts @@ -22,7 +22,6 @@ import { IGX_EXPANSION_PANEL_COMPONENT } from './expansion-panel.common'; import { ToggleAnimationPlayer, ToggleAnimationSettings } from './toggle-animation-component'; -import { NgIf } from '@angular/common'; let NEXT_ID = 0; @@ -30,7 +29,7 @@ let NEXT_ID = 0; selector: 'igx-expansion-panel', templateUrl: 'expansion-panel.component.html', providers: [{ provide: IGX_EXPANSION_PANEL_COMPONENT, useExisting: IgxExpansionPanelComponent }], - imports: [NgIf] + imports: [] }) export class IgxExpansionPanelComponent extends ToggleAnimationPlayer implements IgxExpansionPanelBase, AfterContentInit { /** diff --git a/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.spec.ts b/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.spec.ts index 5b8d1fb1c26..c743e019df5 100644 --- a/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.spec.ts +++ b/projects/igniteui-angular/src/lib/expansion-panel/expansion-panel.spec.ts @@ -11,7 +11,6 @@ import { By } from '@angular/platform-browser'; import { IgxExpansionPanelBodyComponent } from './expansion-panel-body.component'; import { IgxListComponent } from '../list/list.component'; import { IgxListItemComponent } from '../list/list-item.component'; -import { NgIf } from '@angular/common'; import { IGX_EXPANSION_PANEL_DIRECTIVES } from './public_api'; const CSS_CLASS_EXPANSION_PANEL = 'igx-expansion-panel'; @@ -1364,19 +1363,27 @@ export class IgxExpansionPanelListComponent { - - Example Title - Example Description - - TEST_ICON - - - - Example body - + @if (showHeader) { + + @if (showTitle) { + Example Title + } + Example Description + @if (customIcon) { + + TEST_ICON + + } + + } + @if (showBody) { + + Example body + + } `, - imports: [IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelBodyComponent, IgxExpansionPanelTitleDirective, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelIconDirective, NgIf] + imports: [IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelBodyComponent, IgxExpansionPanelTitleDirective, IgxExpansionPanelDescriptionDirective, IgxExpansionPanelIconDirective] }) export class IgxExpansionPanelSampleComponent { @ViewChild(IgxExpansionPanelHeaderComponent, { read: IgxExpansionPanelHeaderComponent }) diff --git a/projects/igniteui-angular/src/lib/grids/cell.component.html b/projects/igniteui-angular/src/lib/grids/cell.component.html index 47531b44d61..b6f3f84656c 100644 --- a/projects/igniteui-angular/src/lib/grids/cell.component.html +++ b/projects/igniteui-angular/src/lib/grids/cell.component.html @@ -1,37 +1,38 @@ - {{ grid.resourceStrings.igx_grid_pinned_row_indicator }} + @if (displayPinnedChip) { + {{ grid.resourceStrings.igx_grid_pinned_row_indicator }} + } -
{{ + @if (column.dataType !== 'boolean' && column.dataType !== 'image' || (column.dataType === 'boolean' && this.formatter)) { +
{{ formatter ? (value | columnFormatter:formatter:rowData:columnData) : column.dataType === "number" @@ -44,48 +45,57 @@ ? (value | percent:column.pipeArgs.digitsInfo:grid.locale) : value }}
- - - + } + @if (column.dataType === 'boolean' && !this.formatter) { + + + } + @if (column.dataType === 'image') { + + } -
{{ - !isEmptyAddRowCell ? value : (column.header || column.field) - }}
+ @if (column.dataType !== 'boolean' || (column.dataType === 'boolean' && this.formatter)) { +
{{ + !isEmptyAddRowCell ? value : (column.header || column.field) + }}
+ }
- - - - - - + @if (column.dataType === 'string' || column.dataType === 'image') { + + + + + + } + @if (column.dataType === 'number') { - - - - - - - - - - - - + } + @if (column.dataType === 'boolean') { + + + + } + @if (column.dataType === 'date') { + + + + + } + @if (column.dataType === 'time') { + + + + } + @if (column.dataType === 'dateTime') { - - + } + @if (column.dataType === 'currency') { - {{ currencyCodeSymbol }} + @if (grid.currencyPositionLeft) { + {{ currencyCodeSymbol }} + } - {{ currencyCodeSymbol }} + @if (!grid.currencyPositionLeft) { + {{ currencyCodeSymbol }} + } - - + } + @if (column.dataType === 'percent') { {{ editValue | percent:column.pipeArgs.digitsInfo:grid.locale }} - + } - +@if (isInvalid) {
- +} -
- {{grid.resourceStrings.igx_grid_required_validation_error}} -
-
- {{grid.resourceStrings.igx_grid_min_length_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.minlength.requiredLength }} -
-
- {{grid.resourceStrings.igx_grid_max_length_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.maxlength.requiredLength }} -
-
- {{grid.resourceStrings.igx_grid_min_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.min.min }} -
-
- {{grid.resourceStrings.igx_grid_max_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.max.max }} -
-
- {{grid.resourceStrings.igx_grid_email_validation_error }} -
-
- {{grid.resourceStrings.igx_grid_pattern_validation_error}} -
+ @if (formGroup?.get(column?.field).errors?.['required']) { +
+ {{grid.resourceStrings.igx_grid_required_validation_error}} +
+ } + @if (formGroup?.get(column?.field).errors?.['minlength']) { +
+ {{grid.resourceStrings.igx_grid_min_length_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.minlength.requiredLength }} +
+ } + @if (formGroup?.get(column?.field).errors?.['maxlength']) { +
+ {{grid.resourceStrings.igx_grid_max_length_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.maxlength.requiredLength }} +
+ } + @if (formGroup?.get(column?.field).errors?.['min']) { +
+ {{grid.resourceStrings.igx_grid_min_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.min.min }} +
+ } + @if (formGroup?.get(column?.field).errors?.['max']) { +
+ {{grid.resourceStrings.igx_grid_max_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.max.max }} +
+ } + @if (formGroup?.get(column?.field).errors?.['email']) { +
+ {{grid.resourceStrings.igx_grid_email_validation_error }} +
+ } + @if (formGroup?.get(column?.field).errors?.['pattern']) { +
+ {{grid.resourceStrings.igx_grid_pattern_validation_error}} +
+ }
diff --git a/projects/igniteui-angular/src/lib/grids/cell.component.ts b/projects/igniteui-angular/src/lib/grids/cell.component.ts index 53f64a97360..eaacd3064e5 100644 --- a/projects/igniteui-angular/src/lib/grids/cell.component.ts +++ b/projects/igniteui-angular/src/lib/grids/cell.component.ts @@ -19,7 +19,7 @@ AfterViewInit, booleanAttribute } from '@angular/core'; -import { formatPercent, NgIf, NgClass, NgTemplateOutlet, DecimalPipe, PercentPipe, CurrencyPipe, DatePipe, getLocaleCurrencyCode, getCurrencySymbol } from '@angular/common'; +import { formatPercent, NgClass, NgTemplateOutlet, DecimalPipe, PercentPipe, CurrencyPipe, DatePipe, getLocaleCurrencyCode, getCurrencySymbol } from '@angular/common'; import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { first, takeUntil, takeWhile } from 'rxjs/operators'; @@ -72,7 +72,6 @@ import { IgxChipComponent } from '../chips/chip.component'; templateUrl: './cell.component.html', providers: [HammerGesturesManager], imports: [ - NgIf, NgClass, NgTemplateOutlet, DecimalPipe, diff --git a/projects/igniteui-angular/src/lib/grids/column-actions/column-actions.component.html b/projects/igniteui-angular/src/lib/grids/column-actions/column-actions.component.html index 35455cf958d..071b64a2ac8 100644 --- a/projects/igniteui-angular/src/lib/grids/column-actions/column-actions.component.html +++ b/projects/igniteui-angular/src/lib/grids/column-actions/column-actions.component.html @@ -1,30 +1,37 @@
-

{{ title }}

+ @if (title) { +

{{ title }}

+ } - - - + @if (!hideFilter) { + + + + }
- - {{ column.header || column.field }} - + @for ( + column of $any(grid)?._columns + | columnActionEnabled:actionsDirective.actionEnabledColumnsFilter:pipeTrigger + | filterActionColumns:filterCriteria:pipeTrigger + | sortActionColumns:columnDisplayOrder:pipeTrigger; track column + ) { + + {{ column.header || column.field }} + + }
diff --git a/projects/igniteui-angular/src/lib/grids/column-actions/column-actions.component.ts b/projects/igniteui-angular/src/lib/grids/column-actions/column-actions.component.ts index 2c2c6075c55..43c6c34b0dd 100644 --- a/projects/igniteui-angular/src/lib/grids/column-actions/column-actions.component.ts +++ b/projects/igniteui-angular/src/lib/grids/column-actions/column-actions.component.ts @@ -9,7 +9,6 @@ import { IgxButtonDirective } from '../../directives/button/button.directive'; import { IgxInputDirective } from '../../directives/input/input.directive'; import { FormsModule } from '@angular/forms'; import { IgxInputGroupComponent } from '../../input-group/input-group.component'; -import { NgIf, NgFor } from '@angular/common'; let NEXT_ID = 0; /** @@ -21,7 +20,7 @@ let NEXT_ID = 0; @Component({ selector: 'igx-column-actions', templateUrl: './column-actions.component.html', - imports: [NgIf, IgxInputGroupComponent, FormsModule, IgxInputDirective, NgFor, IgxCheckboxComponent, IgxButtonDirective, IgxRippleDirective, forwardRef(() => IgxColumnActionEnabledPipe), forwardRef(() => IgxFilterActionColumnsPipe), forwardRef(() => IgxSortActionColumnsPipe)] + imports: [IgxInputGroupComponent, FormsModule, IgxInputDirective, IgxCheckboxComponent, IgxButtonDirective, IgxRippleDirective, forwardRef(() => IgxColumnActionEnabledPipe), forwardRef(() => IgxFilterActionColumnsPipe), forwardRef(() => IgxSortActionColumnsPipe)] }) export class IgxColumnActionsComponent implements DoCheck { diff --git a/projects/igniteui-angular/src/lib/grids/columns/column.component.ts b/projects/igniteui-angular/src/lib/grids/columns/column.component.ts index 281b6ad7d93..9333d911c50 100644 --- a/projects/igniteui-angular/src/lib/grids/columns/column.component.ts +++ b/projects/igniteui-angular/src/lib/grids/columns/column.component.ts @@ -2182,8 +2182,11 @@ export class IgxColumnComponent implements AfterContentInit, OnDestroy, ColumnTy grid._pinnedColumns.splice(args.insertAtIndex, 0, this); } else { // insert based only on root collection - rootPinnedCols.splice(args.insertAtIndex, 0, this); + if (this.level === 0) { + rootPinnedCols.splice(args.insertAtIndex, 0, this); + } let allPinned = []; + // FIX: this is duplicated on every step in the hierarchy.... // re-create hierarchy rootPinnedCols.forEach(group => { allPinned.push(group); diff --git a/projects/igniteui-angular/src/lib/grids/common/grid.interface.ts b/projects/igniteui-angular/src/lib/grids/common/grid.interface.ts index 782f5276ec1..f0ea80c2def 100644 --- a/projects/igniteui-angular/src/lib/grids/common/grid.interface.ts +++ b/projects/igniteui-angular/src/lib/grids/common/grid.interface.ts @@ -302,13 +302,13 @@ export interface FieldType { header?: string; /* alternateType: GridColumnDataType */ dataType: DataType; - editorOptions: IFieldEditorOptions; - filters: IgxFilteringOperand; - pipeArgs: IFieldPipeArgs; - defaultTimeFormat: string; - defaultDateTimeFormat: string; + editorOptions?: IFieldEditorOptions; + filters?: IgxFilteringOperand; + pipeArgs?: IFieldPipeArgs; + defaultTimeFormat?: string; + defaultDateTimeFormat?: string; - formatter(value: any, rowData?: any): any; + formatter?(value: any, rowData?: any): any; } /** @@ -1490,3 +1490,11 @@ export interface IClipboardOptions { */ separator: string; } + +/** + * An interface describing entity + */ +export interface EntityType { + name: string; + fields: FieldType[]; +} diff --git a/projects/igniteui-angular/src/lib/grids/filtering/advanced-filtering/advanced-filtering-dialog.component.html b/projects/igniteui-angular/src/lib/grids/filtering/advanced-filtering/advanced-filtering-dialog.component.html index 215cd1bc9fc..eb11d0aaa6c 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/advanced-filtering/advanced-filtering-dialog.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/advanced-filtering/advanced-filtering-dialog.component.html @@ -1,35 +1,38 @@ -
- - - - +@if (grid) { +
+ + + + -
-
- -
-
- -
-
- -
-
-
+
+
+ +
+
+ +
+
+ +
+
+
+} diff --git a/projects/igniteui-angular/src/lib/grids/filtering/advanced-filtering/advanced-filtering-dialog.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/advanced-filtering/advanced-filtering-dialog.component.ts index ae4bb8e1b74..3a733ddd475 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/advanced-filtering/advanced-filtering-dialog.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/advanced-filtering/advanced-filtering-dialog.component.ts @@ -12,7 +12,7 @@ import { GridResourceStringsEN } from '../../../core/i18n/grid-resources'; import { IFilteringExpressionsTree } from '../../../data-operations/filtering-expressions-tree'; import { IgxButtonDirective } from '../../../directives/button/button.directive'; import { IgxQueryBuilderHeaderComponent } from '../../../query-builder/query-builder-header.component'; -import { NgIf, NgClass } from '@angular/common'; +import { NgClass } from '@angular/common'; import { getCurrentResourceStrings } from '../../../core/i18n/resources'; import { QueryBuilderResourceStringsEN } from '../../../core/i18n/query-builder-resources'; @@ -30,7 +30,7 @@ import { QueryBuilderResourceStringsEN } from '../../../core/i18n/query-builder- @Component({ selector: 'igx-advanced-filtering-dialog', templateUrl: './advanced-filtering-dialog.component.html', - imports: [NgIf, IgxDragDirective, NgClass, IgxQueryBuilderComponent, IgxQueryBuilderHeaderComponent, IgxDragHandleDirective, IgxButtonDirective] + imports: [IgxDragDirective, NgClass, IgxQueryBuilderComponent, IgxQueryBuilderHeaderComponent, IgxDragHandleDirective, IgxButtonDirective] }) export class IgxAdvancedFilteringDialogComponent implements AfterViewInit, OnDestroy { /** @@ -130,9 +130,7 @@ export class IgxAdvancedFilteringDialogComponent implements AfterViewInit, OnDes public onKeyDown(eventArgs: KeyboardEvent) { eventArgs.stopPropagation(); const key = eventArgs.key; - if (this.queryBuilder.isContextMenuVisible && (key === this.platform.KEYMAP.ESCAPE)) { - this.queryBuilder.clearSelection(); - } else if (key === this.platform.KEYMAP.ESCAPE) { + if (key === this.platform.KEYMAP.ESCAPE) { this.closeDialog(); } } @@ -193,6 +191,20 @@ export class IgxAdvancedFilteringDialogComponent implements AfterViewInit, OnDes this.closeDialog(); } + + /** + * @hidden @internal + */ + public generateEntity() { + const entities = [ + { + name: null, + fields: this.filterableFields + } + ]; + return entities; + } + private assignResourceStrings() { // If grid has custom resource strings set for the advanced filtering, // they are passed to the query builder resource strings. diff --git a/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-cell.component.html b/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-cell.component.html index f3b49671574..3fb62f3b3b1 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-cell.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-cell.component.html @@ -14,23 +14,28 @@ - - - - - - {{filteringService.getChipLabel(item.expression)}} - - - {{filteringService.getOperatorAsString(item.afterOperator)}} - + + @for (item of expressionsList; track item.expression; let last = $last; let index = $index) { + @if (isChipVisible(index)) { + + + + + {{filteringService.getChipLabel(item.expression)}} + + + } + @if (!last && isChipVisible(index + 1)) { + {{filteringService.getOperatorAsString(item.afterOperator)}} + } + }
diff --git a/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-cell.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-cell.component.ts index 620d99b1c5e..a2b08705437 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-cell.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-cell.component.ts @@ -18,7 +18,7 @@ import { IgxChipsAreaComponent } from '../../../chips/chips-area.component'; import { IBaseChipEventArgs, IgxChipComponent } from '../../../chips/chip.component'; import { ColumnType } from '../../common/grid.interface'; import { IgxBadgeComponent } from '../../../badge/badge.component'; -import { NgFor, NgIf, NgClass, NgTemplateOutlet } from '@angular/common'; +import { NgClass, NgTemplateOutlet } from '@angular/common'; import { IgxPrefixDirective } from '../../../directives/prefix/prefix.directive'; import { IgxIconComponent } from '../../../icon/icon.component'; import { Size } from '../../common/enums'; @@ -35,8 +35,6 @@ import { Size } from '../../common/enums'; IgxChipComponent, IgxIconComponent, IgxPrefixDirective, - NgFor, - NgIf, NgClass, IgxBadgeComponent, NgTemplateOutlet diff --git a/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.html b/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.html index 03728071432..48bf1c5c0a1 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.html @@ -1,13 +1,15 @@ - -
- - {{ translateCondition(condition) }} -
-
+ @for (condition of conditions; track condition) { + +
+ + {{ translateCondition(condition) }} +
+
+ }
@@ -34,22 +36,24 @@ (compositionend)="onCompositionEnd()" (keydown)="onInputKeyDown($event)" (keyup)="onInputKeyUp()"/> - - - - - - + @if (value || value === 0) { + + + + + + + } @@ -75,22 +79,24 @@ [igxDropDownItemNavigation]="inputGroupConditions"> - - - - - - + @if (value) { + + + + + + + } @@ -120,22 +126,24 @@ [igxDropDownItemNavigation]="inputGroupConditions"> - - - - - - + @if (value) { + + + + + + + } @@ -166,7 +174,8 @@ (click)="onInputClick()" (keydown)="onInputKeyDown($event)" (keyup)="onInputKeyUp()"/> - + @if (value || value === 0) { + + } - +@if (showArrows) { + +}
- - - - - - {{filteringService.getChipLabel(item.expression)}} - - - - - - {{filteringService.grid.resourceStrings.igx_grid_filter_operator_and}} - {{filteringService.grid.resourceStrings.igx_grid_filter_operator_or}} - - - + + + @for (item of expressionsList; track item.expression; let i = $index; let last = $last) { + + + + + {{filteringService.getChipLabel(item.expression)}} + + @if (!last) { + + + + {{filteringService.grid.resourceStrings.igx_grid_filter_operator_and}} + {{filteringService.grid.resourceStrings.igx_grid_filter_operator_or}} + + + } + + }
- +@if (showArrows) { + +}
- + @if (!isNarrowWidth) { - - + } + @if (isNarrowWidth) { - + }
diff --git a/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.ts index c816e840053..ef7ab4f3b0a 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.ts @@ -43,7 +43,7 @@ import { IgxDropDownItemNavigationDirective } from '../../../drop-down/drop-down import { IgxPrefixDirective } from '../../../directives/prefix/prefix.directive'; import { IgxInputGroupComponent } from '../../../input-group/input-group.component'; import { IgxIconComponent } from '../../../icon/icon.component'; -import { NgFor, NgIf, NgTemplateOutlet, NgClass } from '@angular/common'; +import { NgTemplateOutlet, NgClass } from '@angular/common'; import { IgxIconButtonDirective } from '../../../directives/button/icon-button.directive'; import { Size } from '../../common/enums'; @@ -54,7 +54,7 @@ import { Size } from '../../common/enums'; changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-grid-filtering-row', templateUrl: './grid-filtering-row.component.html', - imports: [NgFor, IgxDropDownComponent, IgxDropDownItemComponent, IgxChipsAreaComponent, IgxChipComponent, IgxIconComponent, IgxInputGroupComponent, IgxPrefixDirective, IgxDropDownItemNavigationDirective, IgxInputDirective, NgIf, IgxSuffixDirective, IgxDatePickerComponent, IgxPickerToggleComponent, IgxPickerClearComponent, IgxTimePickerComponent, IgxDateTimeEditorDirective, NgTemplateOutlet, IgxButtonDirective, NgClass, IgxRippleDirective, IgxIconButtonDirective] + imports: [IgxDropDownComponent, IgxDropDownItemComponent, IgxChipsAreaComponent, IgxChipComponent, IgxIconComponent, IgxInputGroupComponent, IgxPrefixDirective, IgxDropDownItemNavigationDirective, IgxInputDirective, IgxSuffixDirective, IgxDatePickerComponent, IgxPickerToggleComponent, IgxPickerClearComponent, IgxTimePickerComponent, IgxDateTimeEditorDirective, NgTemplateOutlet, IgxButtonDirective, NgClass, IgxRippleDirective, IgxIconButtonDirective] }) export class IgxGridFilteringRowComponent implements AfterViewInit, OnDestroy { @Input() @@ -87,14 +87,8 @@ export class IgxGridFilteringRowComponent implements AfterViewInit, OnDestroy { this.expression.searchVal = null; this._value = null; const index = this.expressionsList.findIndex(item => item.expression === this.expression); - if (index === 0 && this.expressionsList.length === 1) { + if (index === 0 && this.expressionsList.length === 1 && !this.expression.condition.isUnary) { this.filteringService.clearFilter(this.column.field); - - if (this.expression.condition.isUnary) { - this.resetExpression(this.expression.condition.name); - } - - return; } } else { if (val === '') { @@ -789,6 +783,7 @@ export class IgxGridFilteringRowComponent implements AfterViewInit, OnDestroy { this.expression = { fieldName: this.column.field, condition: null, + conditionName: null, searchVal: null, ignoreCase: this.column.filteringIgnoreCase }; diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/common.ts b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/common.ts index eb7c55928e8..d48448c1f46 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/common.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/common.ts @@ -1,5 +1,6 @@ +import { isTree } from '../../../data-operations/expressions-tree-util'; import { FilteringLogic, IFilteringExpression } from '../../../data-operations/filtering-expression.interface'; -import { FilteringExpressionsTree, IFilteringExpressionsTree } from '../../../data-operations/filtering-expressions-tree'; +import { IFilteringExpressionsTree } from '../../../data-operations/filtering-expressions-tree'; /** * @hidden @internal @@ -20,11 +21,17 @@ export class FilterListItem { * @hidden */ export class ExpressionUI { + public expressionId: string; public expression: IFilteringExpression; public beforeOperator: FilteringLogic; public afterOperator: FilteringLogic; public isSelected = false; public isVisible = true; + + constructor() { + // Use IDs to identify expressions clearly and use to track them in template @for cycles. + this.expressionId = crypto.randomUUID(); + } } /** @@ -55,17 +62,16 @@ function generateExpressionsListRecursive(expressions: IFilteringExpressionsTree return; } - if (expressions instanceof FilteringExpressionsTree) { - const expressionsTree = expressions as FilteringExpressionsTree; - for (const operand of expressionsTree.filteringOperands) { - generateExpressionsListRecursive(operand, expressionsTree.operator, expressionsUIs); + if (isTree(expressions)) { + for (const operand of expressions.filteringOperands) { + generateExpressionsListRecursive(operand, expressions.operator, expressionsUIs); } if (expressionsUIs.length) { expressionsUIs[expressionsUIs.length - 1].afterOperator = operator; } } else { const exprUI = new ExpressionUI(); - exprUI.expression = expressions as IFilteringExpression; + exprUI.expression = expressions; exprUI.afterOperator = operator; const prevExprUI = expressionsUIs[expressionsUIs.length - 1]; 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 e4745fc79d4..a724862428e 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 @@ -1,10 +1,12 @@ -
- {{ esf.grid.resourceStrings.igx_grid_excel_filter_clear }} - -
+@if (esf.column) { +
+ {{ esf.grid.resourceStrings.igx_grid_excel_filter_clear }} + +
+} diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-clear-filters.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-clear-filters.component.ts index 2a78c304f0e..65449e4ad25 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-clear-filters.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-clear-filters.component.ts @@ -2,7 +2,7 @@ import { Component } from '@angular/core'; import { PlatformUtil } from '../../../core/utils'; import { BaseFilteringComponent } from './base-filtering.component'; import { IgxIconComponent } from '../../../icon/icon.component'; -import { NgIf, NgClass } from '@angular/common'; +import { NgClass } from '@angular/common'; /** * A component used for presenting Excel style clear filters UI. @@ -10,7 +10,7 @@ import { NgIf, NgClass } from '@angular/common'; @Component({ selector: 'igx-excel-style-clear-filters', templateUrl: './excel-style-clear-filters.component.html', - imports: [NgIf, NgClass, IgxIconComponent] + imports: [NgClass, IgxIconComponent] }) export class IgxExcelStyleClearFiltersComponent { constructor( 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 6aa4f2f8a8c..0e10c481086 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 @@ -1,4 +1,4 @@ - +@if (esf.column) {
- {{ subMenuText }} ({{filterNumber}}) + + {{ subMenuText }} + @if (filterNumber > 0) { ({{filterNumber}}) } +
@@ -19,22 +22,25 @@ (selectionChanging)="onSubMenuSelection($event)" (closed)="onSubMenuClosed()">
- -
- - {{ translateCondition(condition) }} -
-
- -
- - {{ esf.grid.resourceStrings.igx_grid_excel_custom_filter }} -
-
+ @for (condition of conditions; track condition) { + +
+ + {{ translateCondition(condition) }} +
+
+ } + @if (showCustomFilterItem()) { + +
+ + {{ esf.grid.resourceStrings.igx_grid_excel_custom_filter }} +
+
+ }
@@ -44,4 +50,4 @@ [filteringService]="esf.grid.filteringService" [overlayComponentId]="esf.overlayComponentId"> -
+} diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-conditional-filter.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-conditional-filter.component.ts index 4cbd41d7e25..fa35a644bd1 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-conditional-filter.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-conditional-filter.component.ts @@ -14,7 +14,7 @@ import { IgxDropDownItemComponent } from '../../../drop-down/drop-down-item.comp import { IgxDropDownComponent } from '../../../drop-down/drop-down.component'; import { IgxIconComponent } from '../../../icon/icon.component'; import { IgxDropDownItemNavigationDirective } from '../../../drop-down/drop-down-navigation.directive'; -import { NgIf, NgFor, NgClass } from '@angular/common'; +import { NgClass } from '@angular/common'; import { ISelectionEventArgs } from '../../../drop-down/drop-down.common'; @@ -24,7 +24,7 @@ import { ISelectionEventArgs } from '../../../drop-down/drop-down.common'; @Component({ selector: 'igx-excel-style-conditional-filter', templateUrl: './excel-style-conditional-filter.component.html', - imports: [NgIf, NgClass, IgxDropDownItemNavigationDirective, IgxIconComponent, IgxDropDownComponent, NgFor, IgxDropDownItemComponent, IgxExcelStyleCustomDialogComponent] + imports: [NgClass, IgxDropDownItemNavigationDirective, IgxIconComponent, IgxDropDownComponent, IgxDropDownItemComponent, IgxExcelStyleCustomDialogComponent] }) export class IgxExcelStyleConditionalFilterComponent implements OnDestroy { /** diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-custom-dialog.component.html b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-custom-dialog.component.html index 419d11d42cb..9998443fd1f 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-custom-dialog.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-custom-dialog.component.html @@ -14,29 +14,33 @@

- - - - + @if (column.dataType === 'date' || column.dataType === 'dateTime' || column.dataType === 'time') { + @for (expression of expressionsList; track expression.expressionId) { + + + } + } - - - - + @if (column.dataType !== 'date' && column.dataType !== 'dateTime' && column.dataType !== 'time') { + @for (expression of expressionsList; track expression.expressionId) { + + + } + } +@if (column.dataType === 'dateTime') { + + + +} - - - {{ grid.resourceStrings.igx_grid_filter_operator_and }} - +@if (!isSingle) { + +} - - {{ grid.resourceStrings.igx_grid_filter_operator_or }} - - +@if (!isLast) { + + + {{ grid.resourceStrings.igx_grid_filter_operator_and }} + + + {{ grid.resourceStrings.igx_grid_filter_operator_or }} + + +}
- - + @if (expressionUI.expression.condition) { + + } + @if (!expressionUI.expression.condition) { + + } - -
- - {{translateCondition(condition)}} -
-
+ @for (condition of conditions; track condition) { + +
+ + {{translateCondition(condition)}} +
+
+ } @@ -29,32 +35,34 @@ /> - +@if (!isSingle) { + +} - - - {{ grid.resourceStrings.igx_grid_filter_operator_and }} - - - - {{ grid.resourceStrings.igx_grid_filter_operator_or }} - - +@if (!isLast) { + + + {{ grid.resourceStrings.igx_grid_filter_operator_and }} + + + {{ grid.resourceStrings.igx_grid_filter_operator_or }} + + +}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-filtering.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-filtering.component.ts index 856355c92fe..d0d3056c8aa 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-filtering.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-filtering.component.ts @@ -25,7 +25,7 @@ import { GridColumnDataType } from '../../../data-operations/data-util'; import { Subscription } from 'rxjs'; import { GridSelectionMode } from '../../common/enums'; import { IgxFilterItem } from '../../../data-operations/filtering-strategy'; -import { formatNumber, formatPercent, getLocaleCurrencyCode, NgIf, NgClass, DOCUMENT } from '@angular/common'; +import { formatNumber, formatPercent, getLocaleCurrencyCode, NgClass, DOCUMENT } from '@angular/common'; import { BaseFilteringComponent } from './base-filtering.component'; import { ExpressionUI, FilterListItem, generateExpressionsList } from './common'; import { ColumnType, GridType, IGX_GRID_BASE } from '../../common/grid.interface'; @@ -40,6 +40,7 @@ import { IgxExcelStylePinningComponent } from './excel-style-pinning.component'; import { IgxExcelStyleMovingComponent } from './excel-style-moving.component'; import { IgxExcelStyleSortingComponent } from './excel-style-sorting.component'; import { IgxExcelStyleHeaderComponent } from './excel-style-header.component'; +import { isTree } from '../../../data-operations/expressions-tree-util'; @Directive({ selector: 'igx-excel-style-column-operations,[igxExcelStyleColumnOperations]', @@ -69,7 +70,7 @@ export class IgxExcelStyleFilterOperationsTemplateDirective { } providers: [{ provide: BaseFilteringComponent, useExisting: forwardRef(() => IgxGridExcelStyleFilteringComponent) }], selector: 'igx-grid-excel-style-filtering', templateUrl: './excel-style-filtering.component.html', - imports: [IgxExcelStyleHeaderComponent, NgIf, IgxExcelStyleSortingComponent, IgxExcelStyleMovingComponent, IgxExcelStylePinningComponent, IgxExcelStyleHidingComponent, IgxExcelStyleSelectingComponent, IgxExcelStyleClearFiltersComponent, IgxExcelStyleConditionalFilterComponent, IgxExcelStyleSearchComponent, NgClass] + imports: [IgxExcelStyleHeaderComponent, IgxExcelStyleSortingComponent, IgxExcelStyleMovingComponent, IgxExcelStylePinningComponent, IgxExcelStyleHidingComponent, IgxExcelStyleSelectingComponent, IgxExcelStyleClearFiltersComponent, IgxExcelStyleConditionalFilterComponent, IgxExcelStyleSearchComponent, NgClass] }) export class IgxGridExcelStyleFilteringComponent extends BaseFilteringComponent implements AfterViewInit, OnDestroy { @@ -585,7 +586,7 @@ export class IgxGridExcelStyleFilteringComponent extends BaseFilteringComponent const expressionsTree = new FilteringExpressionsTree(gridExpressionsTree.operator, gridExpressionsTree.fieldName); for (const operand of gridExpressionsTree.filteringOperands) { - if (operand instanceof FilteringExpressionsTree) { + if (isTree(operand)) { const columnExprTree = operand as FilteringExpressionsTree; if (columnExprTree.fieldName === this.column.field) { continue; diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-header.component.html b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-header.component.html index 6df5e38486d..7aa8df61600 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-header.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-header.component.html @@ -1,31 +1,38 @@ -
-

{{ esf.column.header || esf.column.field }}

-
- - - -
-
+@if (esf.column) { +
+

{{ esf.column.header || esf.column.field }}

+
+ @if (showSelecting) { + + } + @if (showPinning) { + + } + @if (showHiding) { + + } +
+
+} diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-header.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-header.component.ts index f56b1831acd..53a0af9f703 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-header.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-header.component.ts @@ -1,7 +1,7 @@ import { Component, Input, booleanAttribute } from '@angular/core'; import { BaseFilteringComponent } from './base-filtering.component'; import { IgxIconComponent } from '../../../icon/icon.component'; -import { NgIf, NgClass } from '@angular/common'; +import { NgClass } from '@angular/common'; import { IgxIconButtonDirective } from '../../../directives/button/icon-button.directive'; /** @@ -10,7 +10,7 @@ import { IgxIconButtonDirective } from '../../../directives/button/icon-button.d @Component({ selector: 'igx-excel-style-header', templateUrl: './excel-style-header.component.html', - imports: [NgIf, NgClass, IgxIconComponent, IgxIconButtonDirective] + imports: [NgClass, IgxIconComponent, IgxIconButtonDirective] }) export class IgxExcelStyleHeaderComponent { /** 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 a6d584a3049..5f24451e259 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,8 +1,10 @@ - +@if (esf.column) { + +} diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-hiding.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-hiding.component.ts index ceb35b4b19f..f529efef6df 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-hiding.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-hiding.component.ts @@ -1,7 +1,6 @@ import { Component } from '@angular/core'; import { BaseFilteringComponent } from './base-filtering.component'; import { IgxIconComponent } from '../../../icon/icon.component'; -import { NgIf } from '@angular/common'; /** * A component used for presenting Excel style column hiding UI. @@ -9,7 +8,7 @@ import { NgIf } from '@angular/common'; @Component({ selector: 'igx-excel-style-hiding', templateUrl: './excel-style-hiding.component.html', - imports: [NgIf, IgxIconComponent] + imports: [IgxIconComponent] }) export class IgxExcelStyleHidingComponent { constructor(public esf: BaseFilteringComponent) { } diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-moving.component.html b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-moving.component.html index 6224f831ac8..a85b1c229eb 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-moving.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-moving.component.html @@ -1,31 +1,31 @@ - -
- {{ esf.grid.resourceStrings.igx_grid_excel_filter_moving_header }} -
- - - - -
+@if (esf.column) { +
+ {{ esf.grid.resourceStrings.igx_grid_excel_filter_moving_header }} +
+ + + + +} diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-moving.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-moving.component.ts index f41538c4c81..80aa1564310 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-moving.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-moving.component.ts @@ -4,7 +4,6 @@ import { BaseFilteringComponent } from './base-filtering.component'; import { IgxIconComponent } from '../../../icon/icon.component'; import { IgxButtonDirective } from '../../../directives/button/button.directive'; import { IgxButtonGroupComponent } from '../../../buttonGroup/buttonGroup.component'; -import { NgIf } from '@angular/common'; /** * A component used for presenting Excel style column moving UI. @@ -12,7 +11,7 @@ import { NgIf } from '@angular/common'; @Component({ selector: 'igx-excel-style-moving', templateUrl: './excel-style-moving.component.html', - imports: [NgIf, IgxButtonGroupComponent, IgxButtonDirective, IgxIconComponent] + imports: [IgxButtonGroupComponent, IgxButtonDirective, IgxIconComponent] }) export class IgxExcelStyleMovingComponent { /** 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 0c2862fc9b6..47360003197 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,8 +1,10 @@ -
- {{ esf.column.pinned ? esf.grid.resourceStrings.igx_grid_excel_unpin : esf.grid.resourceStrings.igx_grid_excel_pin }} - -
+@if (esf.column) { +
+ {{ 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-pinning.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-pinning.component.ts index 7baa310c653..17cce1aefde 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-pinning.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-pinning.component.ts @@ -1,7 +1,7 @@ import { Component } from '@angular/core'; import { BaseFilteringComponent } from './base-filtering.component'; import { IgxIconComponent } from '../../../icon/icon.component'; -import { NgIf, NgClass } from '@angular/common'; +import { NgClass } from '@angular/common'; /** * A component used for presenting Excel style column pinning UI. @@ -9,7 +9,7 @@ import { NgIf, NgClass } from '@angular/common'; @Component({ selector: 'igx-excel-style-pinning', templateUrl: './excel-style-pinning.component.html', - imports: [NgIf, NgClass, IgxIconComponent] + imports: [NgClass, IgxIconComponent] }) export class IgxExcelStylePinningComponent { constructor(public esf: BaseFilteringComponent) { } diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-search.component.html b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-search.component.html index 946bf531a1b..c5930f3adaf 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-search.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-search.component.html @@ -10,119 +10,141 @@ [placeholder]="esf.column?.grid.resourceStrings.igx_grid_excel_search_placeholder" autocomplete="off"/> - - + @if (searchValue || searchValue === 0) { + + + } - -
- - - {{ item.label }} - - -
- - -
- - +@if (!isHierarchical()) { + +
+ + + {{ item.label }} + +
- - - - - - -
- {{ esf.grid?.resourceStrings.igx_grid_excel_matches_count.replace('{0}', matchesCount) }} -
-
- -
-
-
- - {{ selectAllItem.label }} - + +
+ + +
+
+ + + +
+ {{ esf.grid?.resourceStrings.igx_grid_excel_matches_count.replace('{0}', matchesCount) }}
-
- + +} - {{ addToCurrentFilterItem.label }} - -
-
- - - -
{{item.label}}
- -
{{childLevel1.label}}
- -
{{childLevel2.label}}
- -
{{childLevel3.label}}
- -
{{childLevel4.label}}
- -
{{childLevel5.label}}
- -
{{childLevel6.label}}
- -
{{childLevel7.label}}
- -
{{childLevel8.label}}
- -
{{childLevel9.label}}
-
+@if (isHierarchical()) { +
+ @if (!isTreeEmpty()) { +
+
+ + {{ selectAllItem.label }} + +
+ @if (searchValue) { +
+ + {{ addToCurrentFilterItem.label }} + +
+ } +
+ } + + @for (item of displayedListData; track item.value) { + +
{{item.label}}
+ @for (childLevel1 of item.children; track childLevel1.value) { + +
{{childLevel1.label}}
+ @for (childLevel2 of childLevel1.children; track childLevel2.value) { + +
{{childLevel2.label}}
+ @for (childLevel3 of childLevel2.children; track childLevel3.value) { + +
{{childLevel3.label}}
+ @for (childLevel4 of childLevel3.children; track childLevel4.value) { + +
{{childLevel4.label}}
+ @for (childLevel5 of childLevel4.children; track childLevel5.value) { + +
{{childLevel5.label}}
+ @for (childLevel6 of childLevel5.children; track childLevel6.value) { + +
{{childLevel6.label}}
+ @for (childLevel7 of childLevel6.children; track childLevel7.value) { + +
{{childLevel7.label}}
+ @for (childLevel8 of childLevel7.children; track childLevel8.value) { + +
{{childLevel8.label}}
+ @for (childLevel9 of childLevel8.children; track childLevel9.value) { + +
{{childLevel9.label}}
+
+ } +
+ } +
+ } +
+ } +
+ } +
+ }
-
+ }
-
+ } - + } - - -
- - -
- - -
-
- - - - -
+ } +
+ +
+ + +
+
+ @if (isTreeEmpty()) { + + } +
+}
diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-search.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-search.component.ts index c8139ddd8fb..25199db8605 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-search.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-search.component.ts @@ -32,7 +32,7 @@ import { IgxDataLoadingTemplateDirective, IgxEmptyListTemplateDirective } from ' import { IgxListItemComponent } from '../../../list/list-item.component'; import { IgxListComponent } from '../../../list/list.component'; import { IgxSuffixDirective } from '../../../directives/suffix/suffix.directive'; -import { NgIf, NgTemplateOutlet, NgFor } from '@angular/common'; +import { NgTemplateOutlet } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { IgxPrefixDirective } from '../../../directives/prefix/prefix.directive'; import { IgxIconComponent } from '../../../icon/icon.component'; @@ -59,7 +59,7 @@ let NEXT_ID = 0; @Component({ selector: 'igx-excel-style-search', templateUrl: './excel-style-search.component.html', - imports: [IgxInputGroupComponent, IgxIconComponent, IgxPrefixDirective, FormsModule, IgxInputDirective, NgIf, IgxSuffixDirective, IgxListComponent, IgxForOfDirective, IgxListItemComponent, IgxCheckboxComponent, IgxDataLoadingTemplateDirective, NgTemplateOutlet, IgxEmptyListTemplateDirective, IgxTreeComponent, NgFor, IgxTreeNodeComponent, IgxCircularProgressBarComponent, IgxButtonDirective] + imports: [IgxInputGroupComponent, IgxIconComponent, IgxPrefixDirective, FormsModule, IgxInputDirective, IgxSuffixDirective, IgxListComponent, IgxForOfDirective, IgxListItemComponent, IgxCheckboxComponent, IgxDataLoadingTemplateDirective, NgTemplateOutlet, IgxEmptyListTemplateDirective, IgxTreeComponent, IgxTreeNodeComponent, IgxCircularProgressBarComponent, IgxButtonDirective] }) export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { private static readonly filterOptimizationThreshold = 2; @@ -462,6 +462,7 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { selectAllBtn.indeterminate = anyFiltered && anyUnfiltered; if (this.isHierarchical() && this.tree) { this._hierarchicalSelectedItems = this.tree.nodes.map(n => n.data as FilterListItem).filter(item => item.isFiltered); + this.tree.collapseAll(); } this.esf.listData.forEach(i => i.isSelected = i.isFiltered); @@ -568,6 +569,7 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { } filterTree.filteringOperands.push({ condition, + conditionName: condition.name, fieldName: this.esf.column.field, ignoreCase: this.esf.column.filteringIgnoreCase, searchVal: element.value @@ -582,6 +584,7 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { } filterTree.filteringOperands.push({ condition: this.createCondition('in'), + conditionName: 'in', fieldName: this.esf.column.field, ignoreCase: this.esf.column.filteringIgnoreCase, searchVal: new Set( @@ -598,6 +601,7 @@ export class IgxExcelStyleSearchComponent implements AfterViewInit, OnDestroy { if (blanksItem) { filterTree.filteringOperands.push({ condition: this.createCondition('empty'), + conditionName: 'empty', fieldName: this.esf.column.field, ignoreCase: this.esf.column.filteringIgnoreCase, searchVal: blanksItem.value 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 f1ba36e2519..34b3b651719 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,9 +1,11 @@ -
- {{esf.grid.resourceStrings.igx_grid_excel_select }} - -
+@if (esf.column) { +
+ {{esf.grid.resourceStrings.igx_grid_excel_select }} + +
+} diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-selecting.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-selecting.component.ts index 36354db79ed..d3fd52a5b69 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-selecting.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-selecting.component.ts @@ -1,7 +1,7 @@ import { Component } from '@angular/core'; import { BaseFilteringComponent } from './base-filtering.component'; import { IgxIconComponent } from '../../../icon/icon.component'; -import { NgIf, NgClass } from '@angular/common'; +import { NgClass } from '@angular/common'; /** * A component used for presenting Excel style conditional filter UI. @@ -9,7 +9,7 @@ import { NgIf, NgClass } from '@angular/common'; @Component({ selector: 'igx-excel-style-selecting', templateUrl: './excel-style-selecting.component.html', - imports: [NgIf, NgClass, IgxIconComponent] + imports: [NgClass, IgxIconComponent] }) export class IgxExcelStyleSelectingComponent { constructor(public esf: BaseFilteringComponent) { } diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.html b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.html index 4491db53da8..35cf79678e6 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.html @@ -1,33 +1,32 @@ - -
- {{ esf.grid.resourceStrings.igx_grid_excel_filter_sorting_header }} -
- - - - - -
+@if (esf.column) { +
+ {{ esf.grid.resourceStrings.igx_grid_excel_filter_sorting_header }} +
+ + + + +} diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.ts index 631fc9fd1ae..1d23c7a78c9 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.ts @@ -11,7 +11,6 @@ import { Subject } from 'rxjs'; import { BaseFilteringComponent } from './base-filtering.component'; import { IgxIconComponent } from '../../../icon/icon.component'; import { IgxButtonDirective } from '../../../directives/button/button.directive'; -import { NgIf } from '@angular/common'; /** * A component used for presenting Excel style column sorting UI. @@ -19,7 +18,7 @@ import { NgIf } from '@angular/common'; @Component({ selector: 'igx-excel-style-sorting', templateUrl: './excel-style-sorting.component.html', - imports: [NgIf, IgxButtonGroupComponent, IgxButtonDirective, IgxIconComponent] + imports: [IgxButtonGroupComponent, IgxButtonDirective, IgxIconComponent] }) export class IgxExcelStyleSortingComponent implements OnDestroy { /** diff --git a/projects/igniteui-angular/src/lib/grids/filtering/grid-filtering.service.ts b/projects/igniteui-angular/src/lib/grids/filtering/grid-filtering.service.ts index 3bc09de4a93..717e78acbcf 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/grid-filtering.service.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/grid-filtering.service.ts @@ -20,7 +20,7 @@ import { ColumnType, GridType } from '../common/grid.interface'; import { formatDate } from '../../core/utils'; import { ExcelStylePositionStrategy } from './excel-style/excel-style-position-strategy'; import { fadeIn } from 'igniteui-angular/animations'; -import { ExpressionsTreeUtil } from '../../data-operations/expressions-tree-util'; +import { ExpressionsTreeUtil, isTree } from '../../data-operations/expressions-tree-util'; /** * @hidden @@ -146,7 +146,7 @@ export class IgxFilteringService implements OnDestroy { this.isFiltering = true; let expressionsTree; - if (expressions instanceof FilteringExpressionsTree) { + if (expressions && 'operator' in expressions) { expressionsTree = expressions; } else { expressionsTree = this.createSimpleFilteringTree(field, expressions); @@ -197,11 +197,10 @@ export class IgxFilteringService implements OnDestroy { const expressionsTreeForColumn = ExpressionsTreeUtil.find(this.grid.filteringExpressionsTree, field); if (!expressionsTreeForColumn) { throw new Error('Invalid condition or Expression Tree!'); - } else if (expressionsTreeForColumn instanceof FilteringExpressionsTree) { + } else if (isTree(expressionsTreeForColumn)) { this.filter_internal(field, value, expressionsTreeForColumn, filteringIgnoreCase); } else { - const expressionForColumn = expressionsTreeForColumn as IFilteringExpression; - this.filter_internal(field, value, expressionForColumn.condition, filteringIgnoreCase); + this.filter_internal(field, value, expressionsTreeForColumn.condition, filteringIgnoreCase); } } const doneEventArgs = ExpressionsTreeUtil.find(this.grid.filteringExpressionsTree, field) as FilteringExpressionsTree; @@ -496,9 +495,8 @@ export class IgxFilteringService implements OnDestroy { } for (const expr of expressionTree.filteringOperands) { - if ((expr instanceof FilteringExpressionsTree)) { - const exprTree = expr as FilteringExpressionsTree; - if (exprTree.filteringOperands && exprTree.filteringOperands.length) { + if (isTree(expr)) { + if (expr.filteringOperands && expr.filteringOperands.length) { return false; } } else { @@ -532,9 +530,9 @@ export class IgxFilteringService implements OnDestroy { insertAtIndex = -1, createNewTree = false): FilteringExpressionsTree { - let expressionsTree = conditionOrExpressionsTree instanceof FilteringExpressionsTree ? - conditionOrExpressionsTree as IFilteringExpressionsTree : null; - const condition = conditionOrExpressionsTree instanceof FilteringExpressionsTree ? + let expressionsTree = conditionOrExpressionsTree && 'operator' in conditionOrExpressionsTree ? + conditionOrExpressionsTree : null; + const condition = conditionOrExpressionsTree && 'operator' in conditionOrExpressionsTree ? null : conditionOrExpressionsTree as IFilteringOperation; let newExpressionsTree = filteringState as FilteringExpressionsTree; @@ -545,7 +543,7 @@ export class IgxFilteringService implements OnDestroy { } if (condition) { - const newExpression: IFilteringExpression = { fieldName, searchVal, condition, ignoreCase }; + const newExpression: IFilteringExpression = { fieldName: fieldName, searchVal, condition, conditionName: condition.name, ignoreCase }; expressionsTree = new FilteringExpressionsTree(filteringState.operator, fieldName); expressionsTree.filteringOperands.push(newExpression); } @@ -567,17 +565,16 @@ export class IgxFilteringService implements OnDestroy { return false; } - if (expressions instanceof FilteringExpressionsTree) { - const expressionsTree = expressions as FilteringExpressionsTree; - if (expressionsTree.operator === FilteringLogic.Or) { - const andOperatorsCount = this.getChildAndOperatorsCount(expressionsTree); + if (isTree(expressions)) { + if (expressions.operator === FilteringLogic.Or) { + const andOperatorsCount = this.getChildAndOperatorsCount(expressions); // having more than one 'And' operator in the sub-tree means that the filter could not be represented without parentheses. return andOperatorsCount > 1; } let isComplex = false; - for (const operand of expressionsTree.filteringOperands) { + for (const operand of expressions.filteringOperands) { isComplex = isComplex || this.isFilteringTreeComplex(operand); } @@ -592,12 +589,12 @@ export class IgxFilteringService implements OnDestroy { let operand; for (let i = 0; i < expressions.filteringOperands.length; i++) { operand = expressions[i]; - if (operand instanceof FilteringExpressionsTree) { + if (operand && isTree(operand)) { if (operand.operator === FilteringLogic.And) { count++; } - count = count + this.getChildAndOperatorsCount(operand); + count = count + this.getChildAndOperatorsCount(operand as IFilteringExpressionsTree); } } 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 3051f5657ef..aa442dff801 100644 --- a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts +++ b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts @@ -37,7 +37,7 @@ import { Subject, pipe, fromEvent, animationFrameScheduler, merge } from 'rxjs'; import { takeUntil, first, filter, throttleTime, map, shareReplay, takeWhile } from 'rxjs/operators'; import { cloneArray, mergeObjects, compareMaps, resolveNestedPath, isObject, PlatformUtil } from '../core/utils'; import { GridColumnDataType } from '../data-operations/data-util'; -import { FilteringLogic, IFilteringExpression } from '../data-operations/filtering-expression.interface'; +import { FilteringLogic } from '../data-operations/filtering-expression.interface'; import { IGroupByRecord } from '../data-operations/groupby-record.interface'; import { IForOfDataChangingEventArgs, IgxGridForOfDirective } from '../directives/for-of/for_of.directive'; import { IgxTextHighlightService } from '../directives/text-highlight/text-highlight.service'; @@ -178,6 +178,7 @@ import { DefaultDataCloneStrategy, IDataCloneStrategy } from '../data-operations import { IgxGridCellComponent } from './cell.component'; import { IgxGridValidationService } from './grid/grid-validation.service'; import { getCurrentResourceStrings } from '../core/i18n/resources'; +import { isTree, recreateTreeFromFields } from '../data-operations/expressions-tree-util'; interface IMatchInfoCache { row: any; @@ -1845,18 +1846,21 @@ export abstract class IgxGridBaseDirective implements GridType, } public set filteringExpressionsTree(value) { - if (value && value instanceof FilteringExpressionsTree) { - const val = (value as FilteringExpressionsTree); - for (let index = 0; index < val.filteringOperands.length; index++) { - if (!(val.filteringOperands[index] instanceof FilteringExpressionsTree)) { - const newExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And, val.filteringOperands[index].fieldName); - newExpressionsTree.filteringOperands.push(val.filteringOperands[index] as IFilteringExpression); - val.filteringOperands[index] = newExpressionsTree; + if (value && isTree(value)) { + for (let index = 0; index < value.filteringOperands.length; index++) { + if (!(isTree(value.filteringOperands[index]))) { + const newExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And, value.filteringOperands[index].fieldName); + newExpressionsTree.filteringOperands.push(value.filteringOperands[index]); + value.filteringOperands[index] = newExpressionsTree; } } value.type = FilteringExpressionsTreeType.Regular; - this._filteringExpressionsTree = value; + if (value && this.columns) { + this._filteringExpressionsTree = recreateTreeFromFields(value, this.columns) as IFilteringExpressionsTree; + } else { + this._filteringExpressionsTree = value; + } this.filteringPipeTrigger++; this.filteringExpressionsTreeChange.emit(this._filteringExpressionsTree); @@ -1900,9 +1904,9 @@ export abstract class IgxGridBaseDirective implements GridType, return; } - if (value && value instanceof FilteringExpressionsTree) { + if (value && isTree(value)) { value.type = FilteringExpressionsTreeType.Advanced; - this._advancedFilteringExpressionsTree = value; + this._advancedFilteringExpressionsTree = recreateTreeFromFields(value, this.columns) as IFilteringExpressionsTree; this.filteringPipeTrigger++; } else { this._advancedFilteringExpressionsTree = null; @@ -6600,6 +6604,9 @@ export abstract class IgxGridBaseDirective implements GridType, .filter((c) => c.pinned); this._unpinnedColumns = newColumns.filter((c) => !c.pinned); this._columns = newColumns; + if (this._columns && this._filteringExpressionsTree) { + this._filteringExpressionsTree = recreateTreeFromFields(this._filteringExpressionsTree, this.columns) as IFilteringExpressionsTree; + } this.resetCaches(); } @@ -6661,6 +6668,9 @@ export abstract class IgxGridBaseDirective implements GridType, this.autogenerateColumns(); } else { this._columns = this.getColumnList(); + if (this._columns && this._filteringExpressionsTree) { + this._filteringExpressionsTree = recreateTreeFromFields(this._filteringExpressionsTree, this._columns) as IFilteringExpressionsTree; + } } this.initColumns(this._columns, (col: IgxColumnComponent) => this.columnInit.emit(col)); diff --git a/projects/igniteui-angular/src/lib/grids/grid/cell.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/cell.spec.ts index 964424676f4..47aa02b7bd0 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/cell.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/cell.spec.ts @@ -12,7 +12,6 @@ import { VirtualGridComponent, NoScrollsComponent, import { GridFunctions } from '../../test-utils/grid-functions.spec'; import { TestNgZone } from '../../test-utils/helper-utils.spec'; import { CellType } from '../common/grid.interface'; -import { NgFor } from '@angular/common'; import { IGridCellEventArgs, IgxColumnComponent } from '../public_api'; describe('IgxGrid - Cell component #grid', () => { @@ -406,19 +405,21 @@ describe('IgxGrid - Cell component #grid', () => { @Component({ template: ` - - + @for (c of columns; track c) { + + + } `, styleUrls: ['../../test-utils/grid-cell-style-testing.scss'], - imports: [IgxGridComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent] }) export class ConditionalCellStyleTestComponent implements OnInit { @ViewChild('grid', { static: true }) public grid: IgxGridComponent; diff --git a/projects/igniteui-angular/src/lib/grids/grid/column-group.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/column-group.spec.ts index fd9c04de40f..9e25636960f 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/column-group.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/column-group.spec.ts @@ -26,7 +26,7 @@ const GRID_COL_THEAD_TITLE_CLASS = 'igx-grid-th__title'; const GRID_COL_GROUP_THEAD_TITLE_CLASS = 'igx-grid-thead__title'; const GRID_COL_GROUP_THEAD_GROUP_CLASS = 'igx-grid-thead__group'; - + describe('IgxGrid - multi-column headers #grid', () => { let fixture: ComponentFixture; let grid: IgxGridComponent; let componentInstance; @@ -76,7 +76,7 @@ describe('IgxGrid - multi-column headers #grid', () => { const headerHeight = grid.nativeElement .querySelector("igx-grid-header-row") .getBoundingClientRect().height; - + expect(Math.round(headerHeight)).toEqual(expectedGridHeaderHeight); }); @@ -1112,8 +1112,9 @@ describe('IgxGrid - multi-column headers #grid', () => { grAdressInf.pinned = true; fixture.detectChanges(); - // Verify group and all its children are not pinned + // Verify group and all its children are pinned testColumnPinning(grAdressInf, true); + expect(grid.pinnedColumnsCount).toEqual(10); expect(grid.getCellByColumn(0, 'ID')).toBeDefined(); expect(grid.getCellByColumn(0, 'Country')).toBeDefined(); @@ -1828,4 +1829,4 @@ class NestedColGroupsTests { 'slaveColGroup', masterColGroupChildrenCount); } } - + diff --git a/projects/igniteui-angular/src/lib/grids/grid/column-resizing.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/column-resizing.spec.ts index b58b5f02b41..b510df76d26 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/column-resizing.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/column-resizing.spec.ts @@ -11,7 +11,6 @@ import { MultiColumnHeadersComponent } from '../../test-utils/grid-samples.spec' import { configureTestSuite } from '../../test-utils/configure-suite'; import { GridFunctions } from '../../test-utils/grid-functions.spec'; import { IgxCellHeaderTemplateDirective, IgxCellTemplateDirective } from '../columns/templates.directive'; -import { NgFor } from '@angular/common'; import { IgxAvatarComponent } from '../../avatar/avatar.component'; import { IColumnResizeEventArgs, IgxColumnComponent } from '../public_api'; import { Size } from "../common/enums"; @@ -961,7 +960,7 @@ export class GridFeaturesComponent { @Component({ template: GridTemplateStrings.declareGrid(`height="800px"`, ``, ColumnDefinitions.resizableColsComponent), - imports: [IgxGridComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent] }) export class NullColumnsComponent implements OnInit { @ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent; diff --git a/projects/igniteui-angular/src/lib/grids/grid/column.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/column.spec.ts index a13f5c76a37..a4287723f28 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/column.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/column.spec.ts @@ -1,7 +1,7 @@ import { Component, DebugElement, TemplateRef, ViewChild } from '@angular/core'; import { TestBed, fakeAsync, tick, waitForAsync, ComponentFixture } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { getLocaleCurrencySymbol, NgFor, registerLocaleData } from '@angular/common'; +import { getLocaleCurrencySymbol, registerLocaleData } from '@angular/common'; import localeFr from '@angular/common/locales/fr'; import localeJa from '@angular/common/locales/ja'; @@ -1662,7 +1662,7 @@ describe('IgxGrid - Column properties #grid', () => { @Component({ template: GridTemplateStrings.declareGrid('', '', ColumnDefinitions.iterableComponent), - imports: [IgxGridComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent] }) export class ColumnsFromIterableComponent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) @@ -1688,7 +1688,7 @@ interface IColumnConfig { `, - imports: [IgxGridComponent, IgxColumnComponent, NgFor, IgxButtonDirective] + imports: [IgxGridComponent, IgxColumnComponent, IgxButtonDirective] }) export class ResizableColumnsComponent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) @@ -1738,10 +1738,12 @@ export class TemplatedColumnsComponent { @Component({ template: ` - - + @for (field of columns; track field) { + + + } @@ -1760,7 +1762,7 @@ export class TemplatedColumnsComponent { {{ summaryResults[0].label }}: {{ summaryResults[0].summaryResult }} `, - imports: [IgxGridComponent, IgxColumnComponent, NgFor, IgxSummaryTemplateDirective] + imports: [IgxGridComponent, IgxColumnComponent, IgxSummaryTemplateDirective] }) export class TemplatedInputColumnsComponent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) diff --git a/projects/igniteui-angular/src/lib/grids/grid/expandable-cell.component.html b/projects/igniteui-angular/src/lib/grids/grid/expandable-cell.component.html index 99cd472e085..e241c39710b 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/expandable-cell.component.html +++ b/projects/igniteui-angular/src/lib/grids/grid/expandable-cell.component.html @@ -1,72 +1,84 @@ - {{ grid.resourceStrings.igx_grid_pinned_row_indicator }} + @if (displayPinnedChip) { + {{ grid.resourceStrings.igx_grid_pinned_row_indicator }} + } -
{{ formatter ? (value | columnFormatter:formatter:rowData) : column.dataType === "number" - ? (value | number:column.pipeArgs.digitsInfo:grid.locale) : (column.dataType === 'date' || column.dataType === 'time' || column.dataType === 'dateTime') - ? (value | date:column.pipeArgs.format:column.pipeArgs.timezone:grid.locale) : column.dataType === 'currency' - ? (value | currency:currencyCode:column.pipeArgs.display:column.pipeArgs.digitsInfo:grid.locale) : column.dataType === 'percent' - ? (value | percent:column.pipeArgs.digitsInfo:grid.locale) : value}}
+ @if (column.dataType !== 'boolean' && column.dataType !== 'image' || (column.dataType === 'boolean' && this.formatter)) { +
+ {{ formatter ? (value | columnFormatter:formatter:rowData) : column.dataType === "number" + ? (value | number:column.pipeArgs.digitsInfo:grid.locale) : (column.dataType === 'date' || column.dataType === 'time' || column.dataType === 'dateTime') + ? (value | date:column.pipeArgs.format:column.pipeArgs.timezone:grid.locale) : column.dataType === 'currency' + ? (value | currency:currencyCode:column.pipeArgs.display:column.pipeArgs.digitsInfo:grid.locale) : column.dataType === 'percent' + ? (value | percent:column.pipeArgs.digitsInfo:grid.locale) : value}}
+ } - - - + @if (column.dataType === 'boolean' && !this.formatter) { + + + } + @if (column.dataType === 'image') { + + }
-
{{ - value ? value : (column.header || column.field) - }}
+ @if (column.dataType !== 'boolean' || (column.dataType === 'boolean' && this.formatter)) { +
+ {{ value ? value : (column.header || column.field) }} +
+ }
- - - - - - + @if (column.dataType === 'string' || column.dataType === 'image') { + + + + + + } + @if (column.dataType === 'number') { - - - - - - - - - - - - + } + @if (column.dataType === 'boolean') { + + + + } + @if (column.dataType === 'date') { + + + + + } + @if (column.dataType === 'time') { + + + + } + @if (column.dataType === 'dateTime') { - - + } + @if (column.dataType === 'currency') { - {{ currencyCodeSymbol }} + @if (grid.currencyPositionLeft) { + {{ currencyCodeSymbol }} + } - {{ currencyCodeSymbol }} + @if (!grid.currencyPositionLeft) { + {{ currencyCodeSymbol }} + } - - + } + @if (column.dataType === 'percent') { {{ editValue | percent:column.pipeArgs.digitsInfo:grid.locale }} - + } - +@if (showExpanderIndicator) {
-
+} - +@if (isInvalid) {
- +} @@ -199,25 +221,39 @@ -
- {{grid.resourceStrings.igx_grid_required_validation_error}} -
-
- {{grid.resourceStrings.igx_grid_min_length_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.minlength.requiredLength }} -
-
- {{grid.resourceStrings.igx_grid_max_length_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.maxlength.requiredLength }} -
-
- {{grid.resourceStrings.igx_grid_min_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.min.min }} -
-
- {{grid.resourceStrings.igx_grid_max_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.max.max }} -
-
- {{grid.resourceStrings.igx_grid_email_validation_error }} -
-
- {{grid.resourceStrings.igx_grid_pattern_validation_error}} -
+ @if (formGroup?.get(column?.field).errors?.['required']) { +
+ {{grid.resourceStrings.igx_grid_required_validation_error}} +
+ } + @if (formGroup?.get(column?.field).errors?.['minlength']) { +
+ {{grid.resourceStrings.igx_grid_min_length_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.minlength.requiredLength }} +
+ } + @if (formGroup?.get(column?.field).errors?.['maxlength']) { +
+ {{grid.resourceStrings.igx_grid_max_length_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.maxlength.requiredLength }} +
+ } + @if (formGroup?.get(column?.field).errors?.['min']) { +
+ {{grid.resourceStrings.igx_grid_min_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.min.min }} +
+ } + @if (formGroup?.get(column?.field).errors?.['max']) { +
+ {{grid.resourceStrings.igx_grid_max_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.max.max }} +
+ } + @if (formGroup?.get(column?.field).errors?.['email']) { +
+ {{grid.resourceStrings.igx_grid_email_validation_error }} +
+ } + @if (formGroup?.get(column?.field).errors?.['pattern']) { +
+ {{grid.resourceStrings.igx_grid_pattern_validation_error}} +
+ }
diff --git a/projects/igniteui-angular/src/lib/grids/grid/expandable-cell.component.ts b/projects/igniteui-angular/src/lib/grids/grid/expandable-cell.component.ts index aa9352b9450..19e4bcd005b 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/expandable-cell.component.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/expandable-cell.component.ts @@ -12,7 +12,7 @@ import { } from '@angular/core'; import { IgxGridCellComponent } from '../cell.component'; import { PlatformUtil } from '../../core/utils'; -import { DOCUMENT, NgIf, NgClass, NgTemplateOutlet, DecimalPipe, PercentPipe, CurrencyPipe, DatePipe } from '@angular/common'; +import { DOCUMENT, NgClass, NgTemplateOutlet, DecimalPipe, PercentPipe, CurrencyPipe, DatePipe } from '@angular/common'; import { IgxGridSelectionService } from '../selection/selection.service'; import { HammerGesturesManager } from '../../core/touch'; import { GridType, IGX_GRID_BASE } from '../common/grid.interface'; @@ -39,7 +39,7 @@ import { IgxChipComponent } from '../../chips/chip.component'; selector: 'igx-expandable-grid-cell', templateUrl: 'expandable-cell.component.html', providers: [HammerGesturesManager], - imports: [NgIf, IgxChipComponent, IgxTextHighlightDirective, IgxIconComponent, NgClass, FormsModule, ReactiveFormsModule, IgxInputGroupComponent, IgxInputDirective, IgxFocusDirective, IgxCheckboxComponent, IgxDatePickerComponent, IgxTimePickerComponent, IgxDateTimeEditorDirective, IgxPrefixDirective, IgxSuffixDirective, NgTemplateOutlet, IgxTooltipTargetDirective, IgxTooltipDirective, IgxGridCellImageAltPipe, IgxStringReplacePipe, IgxColumnFormatterPipe, DecimalPipe, PercentPipe, CurrencyPipe, DatePipe] + imports: [IgxChipComponent, IgxTextHighlightDirective, IgxIconComponent, NgClass, FormsModule, ReactiveFormsModule, IgxInputGroupComponent, IgxInputDirective, IgxFocusDirective, IgxCheckboxComponent, IgxDatePickerComponent, IgxTimePickerComponent, IgxDateTimeEditorDirective, IgxPrefixDirective, IgxSuffixDirective, NgTemplateOutlet, IgxTooltipTargetDirective, IgxTooltipDirective, IgxGridCellImageAltPipe, IgxStringReplacePipe, IgxColumnFormatterPipe, DecimalPipe, PercentPipe, CurrencyPipe, DatePipe] }) export class IgxGridExpandableCellComponent extends IgxGridCellComponent implements OnInit { /** diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-cell-editing.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-cell-editing.spec.ts index cae4b6c5753..d8c15d44868 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-cell-editing.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-cell-editing.spec.ts @@ -274,7 +274,7 @@ describe('IgxGrid - Cell Editing #grid', () => { expect(firstCell.editMode).toBeTruthy(); })); - it('should end cell editing when clearing or applying advanced filter', () => { + it('should end cell editing when clearing or applying advanced filter', fakeAsync(() => { const cell = grid.gridAPI.get_cell_by_index(0, 'fullName'); // Enter cell edit mode @@ -310,7 +310,7 @@ describe('IgxGrid - Cell Editing #grid', () => { fixture.detectChanges(); expect(cell.editMode).toBe(false); - }); + })); it('should focus the first cell when editing mode is cell', fakeAsync(() => { const cell = grid.gridAPI.get_cell_by_index(0, 'fullName'); diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts index 59df53aa7e7..055b7b63ac0 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts @@ -1,14 +1,14 @@ import { fakeAsync, TestBed, tick, flush, ComponentFixture } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './grid.component'; -import { UIInteractions, wait } from '../../test-utils/ui-interactions.spec'; +import { UIInteractions } from '../../test-utils/ui-interactions.spec'; import { configureTestSuite } from '../../test-utils/configure-suite'; import { IgxNumberFilteringOperand, IgxStringFilteringOperand } from '../../data-operations/filtering-condition'; import { GridFunctions } from '../../test-utils/grid-functions.spec'; -import { FilteringExpressionsTree, IFilteringExpressionsTree } from '../../data-operations/filtering-expressions-tree'; +import { FilteringExpressionsTree } from '../../data-operations/filtering-expressions-tree'; import { FilteringLogic } from '../../data-operations/filtering-expression.interface'; import { IgxGridAdvancedFilteringColumnGroupComponent, @@ -19,20 +19,15 @@ import { IgxGridAdvancedFilteringDynamicColumnsComponent, IgxGridAdvancedFilteringWithToolbarComponent } from '../../test-utils/grid-samples.spec'; -import { ControlsFunction } from '../../test-utils/controls-functions.spec'; import { FormattedValuesFilteringStrategy } from '../../data-operations/filtering-strategy'; import { IgxHierGridExternalAdvancedFilteringComponent } from '../../test-utils/hierarchical-grid-components.spec'; import { IgxHierarchicalGridComponent } from '../hierarchical-grid/public_api'; import { IFilteringEventArgs, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarComponent } from '../public_api'; import { SampleTestData } from '../../test-utils/sample-test-data.spec'; +import { QueryBuilderFunctions } from '../../query-builder/query-builder-functions.spec'; import { By } from '@angular/platform-browser'; import { IgxDateTimeEditorDirective } from '../../directives/date-time-editor/date-time-editor.directive'; - -const ADVANCED_FILTERING_OPERATOR_LINE_AND_CSS_CLASS = 'igx-filter-tree__line--and'; -const ADVANCED_FILTERING_OPERATOR_LINE_OR_CSS_CLASS = 'igx-filter-tree__line--or'; -const ADVANCED_FILTERING_OPERATOR_LINE_SELECTED_CSS_CLASS = 'igx-filter-tree__line--selected'; -const ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS = 'igx-filter-tree__expression-item'; -const CHIP_SELECT_CLASS = '.igx-chip__select'; +import { QueryBuilderSelectors } from '../../query-builder/query-builder.common'; describe('IgxGrid - Advanced Filtering #grid - ', () => { configureTestSuite((() => { @@ -85,13 +80,15 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); + const advFilteringDialog = GridFunctions.getAdvancedFilteringComponent(fix); + // Verify AF dialog is opened. - expect(GridFunctions.getAdvancedFilteringComponent(fix)).not.toBeNull(); + expect(advFilteringDialog).not.toBeNull(); + expect(advFilteringDialog.querySelector('igx-query-builder')).not.toBeNull(); // Verify there are not filters present and that the default text is shown. expect(grid.advancedFilteringExpressionsTree).toBeUndefined(); - expect(GridFunctions.getAdvancedFilteringTreeRootGroup(fix)).toBeNull(); - expect(GridFunctions.getAdvancedFilteringEmptyPrompt(fix)).not.toBeNull(); + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 0, 0); // Close Advanced Filtering dialog. GridFunctions.clickAdvancedFilteringCancelButton(fix); @@ -123,19 +120,19 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + // Click the initial 'Add Condition' button of the query builder. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); // Populate edit inputs. - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. - let input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. + let input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); UIInteractions.clickAndSendInputElementValue(input, 'ign', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); fix.detectChanges(); // Close dialog through API. @@ -154,15 +151,15 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - // Double-click the existing chip to enter edit mode. - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [0], true); + // Click the existing chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); tick(50); fix.detectChanges(); // Edit the filter value. - input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); + input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); UIInteractions.clickAndSendInputElementValue(input, 'some non-existing value', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); fix.detectChanges(); // Close dialog through API. @@ -173,519 +170,79 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { // Verify AF dialog is closed. expect(GridFunctions.getAdvancedFilteringComponent(fix)).toBeNull(); // Verify the filter changes are NOT applied. - expect(grid.filteredData.length).toEqual(2); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('Ignite UI for JavaScript'); - expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('Ignite UI for Angular'); - })); - - it('Should show/hide initial adding buttons depending on the existence of groups.', fakeAsync(() => { - // Open Advanced Filtering dialog. - GridFunctions.clickAdvancedFilteringButton(fix); - fix.detectChanges(); - - // Verify that the initial buttons are visible. - expect(GridFunctions.getAdvancedFilteringInitialAddGroupButtons(fix).length).toBe(2); - - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - // Verify that the initial buttons are not visible. - expect(GridFunctions.getAdvancedFilteringInitialAddGroupButtons(fix).length).toBe(0); - - // Discard the new group and verify that the initial buttons are visible. - GridFunctions.clickAdvancedFilteringExpressionCloseButton(fix); - fix.detectChanges(); - expect(GridFunctions.getAdvancedFilteringInitialAddGroupButtons(fix).length).toBe(2); - - // Click the initial 'Add Or Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 1); - tick(100); - fix.detectChanges(); - - // Verify that the initial buttons are not visible. - expect(GridFunctions.getAdvancedFilteringInitialAddGroupButtons(fix).length).toBe(0); - })); - - it('Should correctly initialize a newly added \'And\' group.', fakeAsync(() => { - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - // Verify there is a new root group, which is empty. - const group = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); - expect(group).not.toBeNull('There is no root group.'); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(group).length).toBe(0, 'The group has children.'); - - // Verify the operator line of the root group is an 'And' line. - verifyOperatorLine(GridFunctions.getAdvancedFilteringTreeRootGroupOperatorLine(fix), 'and'); - - // Verify the enabled/disabled state of each input of the expression in edit mode. - verifyEditModeExpressionInputStates(fix, true, false, false, false); - - // Verify the edit inputs are empty. - verifyEditModeExpressionInputValues(fix, '', '', ''); - - // Verify adding buttons are disabled. - const buttons = GridFunctions.getAdvancedFilteringTreeRootGroupButtons(fix, 0); - for (const button of buttons) { - ControlsFunction.verifyButtonIsDisabled(button); - } - })); - - it('Should correctly initialize a newly added \'Or\' group.', fakeAsync(() => { - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Click the initial 'Add Or Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 1); - tick(100); - fix.detectChanges(); - - // Verify there is a new root group, which is empty. - const group = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); - expect(group).not.toBeNull('There is no root group.'); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(group).length).toBe(0, 'The group has children.'); - - // Verify the operator line of the root group is an 'Or' line. - verifyOperatorLine(GridFunctions.getAdvancedFilteringTreeRootGroupOperatorLine(fix), 'or'); - - // Verify the enabled/disabled state of each input of the expression in edit mode. - verifyEditModeExpressionInputStates(fix, true, false, false, false); - - // Verify the edit inputs are empty. - verifyEditModeExpressionInputValues(fix, '', '', ''); - - // Verify adding buttons are disabled. - const buttons = GridFunctions.getAdvancedFilteringTreeRootGroupButtons(fix, 0); - for (const button of buttons) { - ControlsFunction.verifyButtonIsDisabled(button); - } - })); - - it('Should add a new group through initial adding button and filter by it.', fakeAsync(() => { - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - // Verify the enabled/disabled state of each input of the expression in edit mode. - verifyEditModeExpressionInputStates(fix, true, false, false, false); - - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - verifyEditModeExpressionInputStates(fix, true, true, false, false); - - selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. - verifyEditModeExpressionInputStates(fix, true, true, true, false); - - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'ign', fix); // Type filter value. - tick(); - fix.detectChanges(); - verifyEditModeExpressionInputStates(fix, true, true, true, true); - - // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); - fix.detectChanges(); - - // Verify the new expression has been added to the group. - const group = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); - expect(GridFunctions.getAdvancedFilteringTreeChildExpressions(group).length).toBe(1, 'Incorrect children count.'); - - // Apply the filters. - GridFunctions.clickAdvancedFilteringApplyButton(fix); - fix.detectChanges(); - - // Verify the filter results. - expect(grid.filteredData.length).toEqual(2); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('Ignite UI for JavaScript'); - expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('Ignite UI for Angular'); - })); - - it('Should update the Advanced Filtering button in toolbar when (filtering)/(clear filtering).', - fakeAsync(() => { - // Verify that the advanced filtering button indicates there are no filters. - let advFilterBtn = GridFunctions.getAdvancedFilteringButton(fix); - expect(Array.from(advFilterBtn.children).some(c => (c as any).classList.contains('igx-adv-filter--column-number'))) - .toBe(false, 'Button indicates there is active filtering.'); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - // Populate edit inputs. - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'angular', fix); // Type filter value. - // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); - fix.detectChanges(); - - // Apply the filters. - GridFunctions.clickAdvancedFilteringApplyButton(fix); - fix.detectChanges(); - - // Verify that the advanced filtering button indicates there are filters. - advFilterBtn = GridFunctions.getAdvancedFilteringButton(fix); - expect(Array.from(advFilterBtn.children).some(c => (c as any).classList.contains('igx-adv-filter--column-number'))) - .toBe(true, 'Button indicates there is no active filtering.'); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Clear the filters. - GridFunctions.clickAdvancedFilteringClearFilterButton(fix); - fix.detectChanges(); - - // Close the dialog. - GridFunctions.clickAdvancedFilteringApplyButton(fix); - fix.detectChanges(); - - // Verify that the advanced filtering button indicates there are no filters. - advFilterBtn = GridFunctions.getAdvancedFilteringButton(fix); - expect(Array.from(advFilterBtn.children).some(c => (c as any).classList.contains('igx-adv-filter--column-number'))) - .toBe(false, 'Button indicates there is active filtering.'); - })); - - it('The Clear/Cancel/Apply buttons type should be set to "button"', () => { - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Get Clear/Cancel/Apply buttons types. - const clearButtonType = GridFunctions.getAdvancedFilteringClearFilterButton(fix).getAttributeNode('type').value; - const cancelButtonType = GridFunctions.getAdvancedFilteringCancelButton(fix).getAttributeNode('type').value; - const applyButtonType = GridFunctions.getAdvancedFilteringApplyButton(fix).getAttributeNode('type').value; - - const expectedButtonType = 'button'; - - // Verify buttons type is set to "button". - expect(clearButtonType).toBe(expectedButtonType, 'Clear button type is not "button"'); - expect(cancelButtonType).toBe(expectedButtonType, 'Cancel button type is not "button"'); - expect(applyButtonType).toBe(expectedButtonType, 'Apply button type is not "button"'); - }); - - it('Should correctly display header name in select dropdown and in chip expression.', fakeAsync(() => { - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - // Open column dropdown and verify header name is displayed for first item - GridFunctions.clickAdvancedFilteringColumnSelect(fix); - fix.detectChanges(); - const dropdownItems = GridFunctions.getAdvancedFilteringSelectDropdownItems(fix); - expect(dropdownItems[0].innerText).toBe('HeaderID'); - - selectColumnInEditModeExpression(fix, 0); // Select 'HeaderID' column - selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'a', fix); // Type filter value. - - // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); - fix.detectChanges(); - - // Verify header name in chip text - verifyExpressionChipContent(fix, [0], 'HeaderID', 'Contains', 'a'); - - // Apply the filters. - GridFunctions.clickAdvancedFilteringApplyButton(fix); - fix.detectChanges(); - - // Close Advanced Filtering dialog. - GridFunctions.clickAdvancedFilteringCancelButton(fix); - tick(100); - fix.detectChanges(); - - // Open Advanced Filtering dialog again. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify header name in chip text - verifyExpressionChipContent(fix, [0], 'HeaderID', 'Contains', 'a'); - })); - - it('Should correctly filter by a \'string\' column through UI.', fakeAsync(() => { - // Test prerequisites - grid.height = '800px'; - fix.detectChanges(); - tick(50); - - // Verify no filters are present. - expect(grid.filteredData).toBeNull(); - expect(grid.rowList.length).toBe(8); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('Ignite UI for JavaScript'); - expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('NetAdvantage'); - - // Open Advanced Filtering dialog. - GridFunctions.clickAdvancedFilteringButton(fix); - fix.detectChanges(); - - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'ign', fix); // Type filter value. - - // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); - fix.detectChanges(); - - // Apply the filters. - GridFunctions.clickAdvancedFilteringApplyButton(fix); - fix.detectChanges(); - - // Verify the filter results. - expect(grid.filteredData.length).toEqual(2); - expect(grid.rowList.length).toBe(2); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('Ignite UI for JavaScript'); - expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('Ignite UI for Angular'); - })); - - it('Should correctly filter by a \'Greater Than\' with \'number\' column through UI.', fakeAsync(() => { - // Test prerequisites - grid.height = '800px'; - fix.detectChanges(); - tick(50); - - // Verify no filters are present. - expect(grid.filteredData).toBeNull(); - expect(grid.rowList.length).toBe(8); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('Ignite UI for JavaScript'); - expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('NetAdvantage'); - - // Open Advanced Filtering dialog. - GridFunctions.clickAdvancedFilteringButton(fix); - fix.detectChanges(); - - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - selectColumnInEditModeExpression(fix, 2); // Select 'Downloads' column. - selectOperatorInEditModeExpression(fix, 2); // Select 'Greater Than' operator. - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, '20', fix); // Type filter value. - - // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); - fix.detectChanges(); - - // Apply the filters. - GridFunctions.clickAdvancedFilteringApplyButton(fix); - fix.detectChanges(); - - // Verify the filter results. - expect(grid.filteredData.length).toEqual(5); - expect(grid.rowList.length).toBe(5); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('Ignite UI for JavaScript'); - expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('NetAdvantage'); - })); - - it('Should correctly filter by a \'Equals\' with \'number\' column through UI.', fakeAsync(() => { - // Test prerequisites - grid.height = '800px'; - fix.detectChanges(); - tick(50); - - // Verify no filters are present. - expect(grid.filteredData).toBeNull(); - expect(grid.rowList.length).toBe(8); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('Ignite UI for JavaScript'); - expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('NetAdvantage'); - - // Open Advanced Filtering dialog. - GridFunctions.clickAdvancedFilteringButton(fix); - fix.detectChanges(); - - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - selectColumnInEditModeExpression(fix, 2); // Select 'Downloads' column. - selectOperatorInEditModeExpression(fix, 0); // Select 'Equals' operator. - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, '127', fix); // Type filter value. - - // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); - fix.detectChanges(); - - // Apply the filters. - GridFunctions.clickAdvancedFilteringApplyButton(fix); - fix.detectChanges(); - - // Verify the filter results. - expect(grid.filteredData.length).toEqual(1); - expect(grid.rowList.length).toBe(1); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('NetAdvantage'); - })); - - it('Should correctly filter by a \'boolean\' column through UI.', fakeAsync(() => { - // Test prerequisites - grid.height = '800px'; - fix.detectChanges(); - tick(50); - - // Verify no filters are present. - expect(grid.filteredData).toBeNull(); - expect(grid.rowList.length).toBe(8); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('Ignite UI for JavaScript'); - expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('NetAdvantage'); - - // Open Advanced Filtering dialog. - GridFunctions.clickAdvancedFilteringButton(fix); - fix.detectChanges(); - - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - selectColumnInEditModeExpression(fix, 3); // Select 'Released' column. - selectOperatorInEditModeExpression(fix, 1); // Select 'True' operator. - verifyEditModeExpressionInputStates(fix, true, true, false, true); // Third input should be disabled for unary operators. - - // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); - fix.detectChanges(); - - // Apply the filters. - GridFunctions.clickAdvancedFilteringApplyButton(fix); - fix.detectChanges(); - - // Verify the filter results. - expect(grid.filteredData.length).toEqual(3); - expect(grid.rowList.length).toBe(3); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('NetAdvantage'); - expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe(null); - })); - - it('Should correctly filter by a \'date\' column through UI with unary operator.', fakeAsync(() => { - // Test prerequisites - grid.height = '800px'; - fix.detectChanges(); - tick(50); - - // Verify no filters are present. - expect(grid.filteredData).toBeNull(); - expect(grid.rowList.length).toBe(8); + expect(grid.filteredData.length).toEqual(2); expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('Ignite UI for JavaScript'); - expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('NetAdvantage'); + expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('Ignite UI for Angular'); + })); + + it('Should update the Advanced Filtering button in toolbar when (filtering)/(clear filtering).', fakeAsync(() => { + // Verify that the advanced filtering button indicates there are no filters. + let advFilterBtn = GridFunctions.getAdvancedFilteringButton(fix); + expect(Array.from(advFilterBtn.children).some(c => (c as any).classList.contains('igx-adv-filter--column-number'))) + .toBe(false, 'Button indicates there is active filtering.'); // Open Advanced Filtering dialog. - GridFunctions.clickAdvancedFilteringButton(fix); + grid.openAdvancedFilteringDialog(); fix.detectChanges(); - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + // Click the initial 'Add Condition' button of the query builder. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); - selectColumnInEditModeExpression(fix, 4); // Select 'ReleaseDate' column. - selectOperatorInEditModeExpression(fix, 9); // Select 'This Year' operator. - verifyEditModeExpressionInputStates(fix, true, true, false, true); // Third input should be disabled for unary operators. - const input = GridFunctions.getAdvancedFilteringValueInput(fix, true); - input.click(); - fix.detectChanges(); + // Populate edit inputs. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, 'angular', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); fix.detectChanges(); // Apply the filters. GridFunctions.clickAdvancedFilteringApplyButton(fix); fix.detectChanges(); - // Verify the filter results. - const expectedData = fix.componentInstance.data.filter(r => - r.ReleaseDate && r.ReleaseDate.getFullYear() === (new Date()).getFullYear()); - expect(grid.filteredData.length).toEqual(expectedData.length); - expect(grid.rowList.length).toBe(expectedData.length); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe(expectedData[0].ProductName); - expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe(expectedData[1].ProductName); - })); - - it('Should correctly filter by a \'date\' column through UI with value from calendar.', fakeAsync(() => { - // Test prerequisites - grid.height = '800px'; - fix.detectChanges(); - tick(50); - - // Verify no filters are present. - expect(grid.filteredData).toBeNull(); - expect(grid.rowList.length).toBe(8); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 1).value).toBe('Ignite UI for JavaScript'); - expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('NetAdvantage'); + // Verify that the advanced filtering button indicates there are filters. + advFilterBtn = GridFunctions.getAdvancedFilteringButton(fix); + expect(Array.from(advFilterBtn.children).some(c => (c as any).classList.contains('igx-adv-filter--column-number'))) + .toBe(true, 'Button indicates there is no active filtering.'); // Open Advanced Filtering dialog. - GridFunctions.clickAdvancedFilteringButton(fix); - fix.detectChanges(); - - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); + grid.openAdvancedFilteringDialog(); fix.detectChanges(); - selectColumnInEditModeExpression(fix, 4); // Select 'ReleaseDate' column. - selectOperatorInEditModeExpression(fix, 0); // Select 'Equals' operator. - verifyEditModeExpressionInputStates(fix, true, true, true, false); - const input = GridFunctions.getAdvancedFilteringValueInput(fix, true); - input.click(); + // Clear the filters. + GridFunctions.clickAdvancedFilteringClearFilterButton(fix); fix.detectChanges(); - // Click on 'today' item in calendar. - const calendar = GridFunctions.getAdvancedFilteringCalendar(fix); - const todayItem = calendar.querySelector('.igx-days-view__date--current'); - todayItem.firstChild.click(); - tick(100); + // Close the dialog. + GridFunctions.clickAdvancedFilteringApplyButton(fix); fix.detectChanges(); - verifyEditModeExpressionInputStates(fix, true, true, true, true); + // Verify that the advanced filtering button indicates there are no filters. + advFilterBtn = GridFunctions.getAdvancedFilteringButton(fix); + expect(Array.from(advFilterBtn.children).some(c => (c as any).classList.contains('igx-adv-filter--column-number'))) + .toBe(false, 'Button indicates there is active filtering.'); + })); - // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + it('The Clear/Cancel/Apply buttons type should be set to "button"', fakeAsync(() => { + // Open Advanced Filtering dialog. + grid.openAdvancedFilteringDialog(); fix.detectChanges(); - // Apply the filters. - GridFunctions.clickAdvancedFilteringApplyButton(fix); - fix.detectChanges(); + // Get Clear/Cancel/Apply buttons types. + const clearButtonType = GridFunctions.getAdvancedFilteringClearFilterButton(fix).getAttributeNode('type').value; + const cancelButtonType = GridFunctions.getAdvancedFilteringCancelButton(fix).getAttributeNode('type').value; + const applyButtonType = GridFunctions.getAdvancedFilteringApplyButton(fix).getAttributeNode('type').value; - // Verify the filter results. - expect(grid.filteredData.length).toEqual(1); - expect(grid.rowList.length).toBe(1); - expect(GridFunctions.getCurrentCellFromGrid(grid, 0, 0).value.toString()).toBe('8'); + const expectedButtonType = 'button'; - flush(); + // Verify buttons type is set to "button". + expect(clearButtonType).toBe(expectedButtonType, 'Clear button type is not "button"'); + expect(cancelButtonType).toBe(expectedButtonType, 'Cancel button type is not "button"'); + expect(applyButtonType).toBe(expectedButtonType, 'Apply button type is not "button"'); })); it('Should emit the filtering event when applying filters.', fakeAsync(() => { @@ -695,19 +252,19 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + // Click the initial 'Add Condition' button of the query builder. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); // Populate edit inputs. - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'ign', fix); // Type filter value. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, 'angular', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); fix.detectChanges(); // Apply the filters. @@ -732,19 +289,19 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + // Click the initial 'Add Condition' button of the query builder. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); // Populate edit inputs. - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'ign', fix); // Type filter value. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, 'angular', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); fix.detectChanges(); // Apply the filters. @@ -768,19 +325,19 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + // Click the initial 'Add Condition' button of the query builder. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); // Populate edit inputs. - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'ign', fix); // Type filter value. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, 'angular', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); fix.detectChanges(); // Apply the filters. @@ -804,15 +361,18 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { // Apply advanced filter through API. const tree = new FilteringExpressionsTree(FilteringLogic.And); tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') + fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), + conditionName: 'greaterThan' }); const orTree = new FilteringExpressionsTree(FilteringLogic.Or); orTree.filteringOperands.push({ fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', ignoreCase: true }); orTree.filteringOperands.push({ fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', ignoreCase: true }); tree.filteringOperands.push(orTree); @@ -849,15 +409,18 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { // Apply advanced filter through API. const tree = new FilteringExpressionsTree(FilteringLogic.And); tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') + fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), + conditionName: 'greaterThan' }); const orTree = new FilteringExpressionsTree(FilteringLogic.Or); orTree.filteringOperands.push({ fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', ignoreCase: true }); orTree.filteringOperands.push({ fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', ignoreCase: true }); tree.filteringOperands.push(orTree); @@ -875,21 +438,21 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Verfiy there is a root group with 'And' operator line and 2 children. - const rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); + const rootGroup = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix); expect(rootGroup).not.toBeNull(); - verifyOperatorLine(GridFunctions.getAdvancedFilteringTreeRootGroupOperatorLine(fix), 'and'); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup).length).toBe(2); + QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeRootGroupOperatorLine(fix) as HTMLElement, 'and'); + expect(QueryBuilderFunctions.getQueryBuilderTreeChildItems(rootGroup as HTMLElement).length).toBe(2); // Verify the contnet of the first child (expression) of the root group. - verifyExpressionChipContent(fix, [0], 'Downloads', 'Greater Than', '100'); + QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'Downloads', 'Greater Than', '100'); // Verify the content of the second child (group) of the root group. - const group = GridFunctions.getAdvancedFilteringTreeItem(fix, [1]); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(group, false).length).toBe(2); - verifyExpressionChipContent(fix, [1, 0], 'ProductName', 'Contains', 'angular'); - verifyExpressionChipContent(fix, [1, 1], 'ProductName', 'Contains', 'script'); + const group = QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [0]); + expect(QueryBuilderFunctions.getQueryBuilderTreeChildItems(group as HTMLElement, false).length).toBe(2); + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0, 0], 'ProductName', 'Contains', 'angular'); + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0, 1], 'ProductName', 'Contains', 'script'); // Verify the operator line of the child group. - verifyOperatorLine(GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]), 'or'); + QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeGroupOperatorLine(fix, [0]) as HTMLElement, 'or'); // Close Advanced Filtering dialog. GridFunctions.clickAdvancedFilteringCancelButton(fix); @@ -906,8 +469,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { // Verify there are not filters present and that the default text is shown. expect(grid.advancedFilteringExpressionsTree).toBeNull(); - expect(GridFunctions.getAdvancedFilteringTreeRootGroup(fix)).toBeNull(); - expect(GridFunctions.getAdvancedFilteringEmptyPrompt(fix)).not.toBeNull(); + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 0, 0); })); it('Applying/Clearing filter through the UI should correctly update the API.', fakeAsync(() => { @@ -927,48 +489,19 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - // Add a root 'and' group. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - // Populate edit inputs. - selectColumnInEditModeExpression(fix, 2); // Select 'Downloads' column. - selectOperatorInEditModeExpression(fix, 2); // Select 'Greater Than' operator. - let input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, '100', fix); // Type filter value. - // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); - fix.detectChanges(); - - // Add a child 'or' group. - const addOrGroupBtn = GridFunctions.getAdvancedFilteringTreeRootGroupButtons(fix, 0)[2]; - addOrGroupBtn.click(); - tick(100); - fix.detectChanges(); - - // Populate edit inputs. - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'angular', fix); // Type filter value. - // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); - fix.detectChanges(); - - // Add new expression to the child group. - const addExpressionBtn = GridFunctions.getAdvancedFilteringTreeGroupButtons(fix, [1], 0)[0]; - addExpressionBtn.click(); + // Click the initial 'Add Condition' button of the query builder. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); // Populate edit inputs. - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); UIInteractions.clickAndSendInputElementValue(input, 'script', fix); // Type filter value. + // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); fix.detectChanges(); // Apply the filters. @@ -1001,46 +534,19 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { expect(GridFunctions.getCurrentCellFromGrid(grid, 1, 1).value).toBe('NetAdvantage'); })); - it('Should discard the newly added group when clicking the \'close\' button of its initial condition.', fakeAsync(() => { - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - // Verify there is a new group and the initial buttons are not visible. - expect(GridFunctions.getAdvancedFilteringTreeRootGroup(fix)).not.toBeNull(); - expect(GridFunctions.getAdvancedFilteringInitialAddGroupButtons(fix).length).toBe(0); - - // Populate edit inputs - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'ign', fix); // Type filter value. - - // Discard the populated expression, so the whole new group gets discarded. - GridFunctions.clickAdvancedFilteringExpressionCloseButton(fix); - fix.detectChanges(); - - // Verify there are no groups in the dialog and the initial buttons are visible. - expect(GridFunctions.getAdvancedFilteringTreeRootGroup(fix)).toBeNull(); - expect(GridFunctions.getAdvancedFilteringInitialAddGroupButtons(fix).length).toBe(2); - })); - it('Should apply filters on Apply button click without prior Commit button click', fakeAsync(() => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + // Click the initial 'Add Condition' button of the query builder. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); + // Populate edit inputs. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); UIInteractions.clickAndSendInputElementValue(input, 'ign', fix); // Type filter value. GridFunctions.clickAdvancedFilteringApplyButton(fix); @@ -1058,7 +564,8 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + // Click the initial 'Add Condition' button of the query builder. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); @@ -1073,11 +580,12 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + // Click the initial 'Add Condition' button of the query builder. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. GridFunctions.clickAdvancedFilteringApplyButton(fix); tick(100); @@ -1089,12 +597,13 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + // Click the initial 'Add Condition' button of the query builder. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. GridFunctions.clickAdvancedFilteringApplyButton(fix); tick(100); @@ -1105,10 +614,6 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { })); it('Column dropdown should contain only filterable columns.', fakeAsync(() => { - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - // Make the 'Downloads', 'Released' and 'ReleaseDate' columns non-filterable. grid.getColumnByName('Downloads').filterable = false; grid.getColumnByName('Released').filterable = false; @@ -1116,126 +621,26 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.cdr.detectChanges(); tick(100); - // Click the initial 'Add and Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - // Open column dropdown and verify that only filterable columns are present. - GridFunctions.clickAdvancedFilteringColumnSelect(fix); - fix.detectChanges(); - const dropdownItems = GridFunctions.getAdvancedFilteringSelectDropdownItems(fix); - expect(dropdownItems.length).toBe(4); - expect(dropdownItems[0].innerText).toBe('HeaderID'); - expect(dropdownItems[1].innerText).toBe('ProductName'); - expect(dropdownItems[2].innerText).toBe('Another Field'); - })); - - it('Operator dropdown should contain operators based on the column\'s datatype (\'string\' or \'number\').', fakeAsync(() => { // Open Advanced Filtering dialog. grid.openAdvancedFilteringDialog(); fix.detectChanges(); - // Add a new group. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - // Select 'string' type column ('ProductName'). - selectColumnInEditModeExpression(fix, 1); - // Open the operator dropdown and verify they are 'string' specific. - GridFunctions.clickAdvancedFilteringOperatorSelect(fix); - fix.detectChanges(); - let dropdownValues: string[] = GridFunctions.getAdvancedFilteringSelectDropdownItems(fix).map((x: any) => x.innerText); - let expectedValues = ['Contains', 'Does Not Contain', 'Starts With', 'Ends With', 'Equals', - 'Does Not Equal', 'Empty', 'Not Empty', 'Null', 'Not Null']; - expect(dropdownValues).toEqual(expectedValues); - - // Close current dropdown by a random select. - GridFunctions.clickAdvancedFilteringSelectDropdownItem(fix, 0); - tick(); - fix.detectChanges(); - - // Select 'number' type column ('Downloads'). - selectColumnInEditModeExpression(fix, 2); - // Open the operator dropdown and verify they are 'number' specific. - GridFunctions.clickAdvancedFilteringOperatorSelect(fix); - fix.detectChanges(); - dropdownValues = GridFunctions.getAdvancedFilteringSelectDropdownItems(fix).map((x: any) => x.innerText); - expectedValues = ['Equals', 'Does Not Equal', 'Greater Than', 'Less Than', 'Greater Than Or Equal To', - 'Less Than Or Equal To', 'Empty', 'Not Empty', 'Null', 'Not Null']; - expect(dropdownValues).toEqual(expectedValues); - })); - - it('Operator dropdown should contain operators based on the column\'s datatype (\'date\' or \'boolean\').', fakeAsync(() => { - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); + const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[0].nativeElement; - // Add a new group. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + // Click the initial 'Add Condition' button of the query builder. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); - // Select 'date' type column ('ReleaseDate'). - selectColumnInEditModeExpression(fix, 4); - // Open the operator dropdown and verify they are 'date' specific. - GridFunctions.clickAdvancedFilteringOperatorSelect(fix); - fix.detectChanges(); - let dropdownValues: string[] = GridFunctions.getAdvancedFilteringSelectDropdownItems(fix).map((x: any) => x.innerText); - let expectedValues = ['Equals', 'Does Not Equal', 'Before', 'After', 'Today', 'Yesterday', - 'This Month', 'Last Month', 'Next Month', 'This Year', 'Last Year', - 'Next Year', 'Empty', 'Not Empty', 'Null', 'Not Null']; - expect(dropdownValues).toEqual(expectedValues); - - // Close current dropdown by a random select. - GridFunctions.clickAdvancedFilteringSelectDropdownItem(fix, 0); - tick(); - fix.detectChanges(); - - // Select 'boolean' type column ('Released'). - selectColumnInEditModeExpression(fix, 3); - // Open the operator dropdown and verify they are 'boolean' specific. - GridFunctions.clickAdvancedFilteringOperatorSelect(fix); - fix.detectChanges(); - dropdownValues = GridFunctions.getAdvancedFilteringSelectDropdownItems(fix).map((x: any) => x.innerText); - expectedValues = ['All', 'True', 'False', 'Empty', 'Not Empty', 'Null', 'Not Null']; - expect(dropdownValues).toEqual(expectedValues); - })); - - it('Should not commit and close currently edited condition when the \'close\' button is clicked.', fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') - }); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - verifyExpressionChipContent(fix, [0], 'Downloads', 'Greater Than', '100'); - - // Edit the first expression in the inner 'or' group. - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [0], true); // Double-click the chip - tick(200); - fix.detectChanges(); - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, '500', fix); // Type filter value. - - // Verify the edit mode container is visible. - expect(GridFunctions.getAdvancedFilteringEditModeContainer(fix)).not.toBeNull(); - - // Close the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCloseButton(fix); + // Open column dropdown and verify that only filterable columns are present. + QueryBuilderFunctions.clickQueryBuilderColumnSelect(fix); fix.detectChanges(); - - // Verify the edit mode container is no longer visible. - expect(GridFunctions.getAdvancedFilteringEditModeContainer(fix)).toBeNull(); - - verifyExpressionChipContent(fix, [0], 'Downloads', 'Greater Than', '100'); + const dropdownItems = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement); + expect(dropdownItems.length).toBe(4); + expect((dropdownItems[0] as HTMLElement).innerText).toBe('HeaderID'); + expect((dropdownItems[1] as HTMLElement).innerText).toBe('ProductName'); + expect((dropdownItems[2] as HTMLElement).innerText).toBe('Another Field'); + expect((dropdownItems[3] as HTMLElement).innerText).toBe('ReleaseTime'); })); it('Should scroll the adding buttons into view when the add icon of a chip is clicked.', fakeAsync(() => { @@ -1243,7 +648,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { const tree = new FilteringExpressionsTree(FilteringLogic.Or); for (let index = 0; index < 30; index++) { tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: index, condition: IgxNumberFilteringOperand.instance().condition('equals') + fieldName: 'Downloads', searchVal: index, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' }); } grid.advancedFilteringExpressionsTree = tree; @@ -1254,25 +659,25 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Scroll to the top. - const exprContainer = GridFunctions.getAdvancedFilteringExpressionsContainer(fix); + const exprContainer = QueryBuilderFunctions.getQueryBuilderExpressionsContainer(fix); tick(50); exprContainer.scrollTop = 0; // Hover the last visible expression chip - const expressionItem = fix.nativeElement.querySelectorAll(`.${ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS}`)[9]; + const expressionItem = fix.nativeElement.querySelectorAll(`.${QueryBuilderSelectors.FILTER_TREE_EXPRESSION_ITEM}`)[9]; expressionItem.dispatchEvent(new MouseEvent('mouseenter')); tick(); fix.detectChanges(); // Click the add icon to display the adding buttons. - GridFunctions.clickAdvancedFilteringTreeExpressionChipAddIcon(fix, [9]); + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChipIcon(fix, [9], 'add'); fix.detectChanges(); tick(50); // Verify the adding buttons are in view. - const addingButtons = GridFunctions.getAdvancedFilteringTreeRootGroupButtons(fix, 0); + const addingButtons = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0); for (const addingButton of addingButtons) { - verifyElementIsInExpressionsContainerView(fix, addingButton); + verifyElementIsInExpressionsContainerView(fix, addingButton as HTMLElement); } })); @@ -1281,7 +686,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { const tree = new FilteringExpressionsTree(FilteringLogic.Or); for (let index = 0; index < 30; index++) { tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: index, condition: IgxNumberFilteringOperand.instance().condition('equals') + fieldName: 'Downloads', searchVal: index, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' }); } grid.advancedFilteringExpressionsTree = tree; @@ -1292,27 +697,28 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Scroll to the top. - const exprContainer = GridFunctions.getAdvancedFilteringExpressionsContainer(fix); + const exprContainer = QueryBuilderFunctions.getQueryBuilderExpressionsContainer(fix); tick(50); exprContainer.scrollTop = 0; // Hover the previous to last visible expression chip. - const expressionItem = fix.nativeElement.querySelectorAll(`.${ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS}`)[8]; + const expressionItem = fix.nativeElement.querySelectorAll(`.${QueryBuilderSelectors.FILTER_TREE_EXPRESSION_ITEM}`)[9]; expressionItem.dispatchEvent(new MouseEvent('mouseenter')); tick(); fix.detectChanges(); // Click the add icon to display the adding buttons. - GridFunctions.clickAdvancedFilteringTreeExpressionChipAddIcon(fix, [8]); + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChipIcon(fix, [9], 'add'); + fix.detectChanges(); tick(50); // Click the 'add condition' button. - const addCondButton = GridFunctions.getAdvancedFilteringTreeRootGroupButtons(fix, 0)[0]; + const addCondButton = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0)[0] as HTMLElement; addCondButton.click(); fix.detectChanges(); // Verify the edit mode container (the one with the editing inputs) is in view. - verifyElementIsInExpressionsContainerView(fix, GridFunctions.getAdvancedFilteringEditModeContainer(fix)); + verifyElementIsInExpressionsContainerView(fix, QueryBuilderFunctions.getQueryBuilderEditModeContainer(fix, false) as HTMLElement); })); it('Should scroll to the expression when entering its edit mode.', fakeAsync(() => { @@ -1320,7 +726,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { const tree = new FilteringExpressionsTree(FilteringLogic.Or); for (let index = 0; index < 30; index++) { tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: index, condition: IgxNumberFilteringOperand.instance().condition('equals') + fieldName: 'Downloads', searchVal: index, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' }); } grid.advancedFilteringExpressionsTree = tree; @@ -1331,73 +737,41 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Scroll to the top. - const exprContainer = GridFunctions.getAdvancedFilteringExpressionsContainer(fix); + const exprContainer = QueryBuilderFunctions.getQueryBuilderExpressionsContainer(fix); tick(50); exprContainer.scrollTop = 0; // Hover the last visible expression chip - const expressionItem = fix.nativeElement.querySelectorAll(`.${ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS}`)[9]; + const expressionItem = fix.nativeElement.querySelectorAll(`.${QueryBuilderSelectors.FILTER_TREE_EXPRESSION_ITEM}`)[9]; expressionItem.dispatchEvent(new MouseEvent('mouseenter')); tick(); fix.detectChanges(); - // Click the edit icon to enter edit mode of the expression. - GridFunctions.clickAdvancedFilteringTreeExpressionChipEditIcon(fix, [9]); - tick(50); - - // Verify the edit mode container (the one with the editing inputs) is in view. - verifyElementIsInExpressionsContainerView(fix, GridFunctions.getAdvancedFilteringEditModeContainer(fix)); - })); - - it('Should keep the context menu in view when scrolling the expressions container.', fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.Or); - for (let index = 0; index < 20; index++) { - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: index, condition: IgxNumberFilteringOperand.instance().condition('equals') - }); - } - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); + // Click the chip to enter edit mode of the expression. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [9]); fix.detectChanges(); - - // Scroll to the top. - const exprContainer = GridFunctions.getAdvancedFilteringExpressionsContainer(fix); tick(50); - exprContainer.scrollTop = 0; - - // Select the first two chips. - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [0]); - fix.detectChanges(); - - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [1]); - tick(200); // Await click timeout - fix.detectChanges(); - - // Scroll to the bottom. - exprContainer.scrollTop = exprContainer.scrollHeight; - // Verify that the context menu is correctly repositioned and in view. - const contextMenu = GridFunctions.getAdvancedFilteringContextMenu(fix); - verifyElementIsInExpressionsContainerView(fix, contextMenu); + // Verify the edit mode container (the one with the editing inputs) is in view. + verifyElementIsInExpressionsContainerView(fix, QueryBuilderFunctions.getQueryBuilderEditModeContainer(fix, false) as HTMLElement); })); it('Should clear all conditions and groups when the \'clear filter\' button is clicked.', fakeAsync(() => { // Apply advanced filter through API. const tree = new FilteringExpressionsTree(FilteringLogic.And); tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') + fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), + conditionName: 'greaterThan' }); const orTree = new FilteringExpressionsTree(FilteringLogic.Or); orTree.filteringOperands.push({ fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', ignoreCase: true }); orTree.filteringOperands.push({ fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', ignoreCase: true }); tree.filteringOperands.push(orTree); @@ -1409,8 +783,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Verify there are filters in the dialog. - expect(GridFunctions.getAdvancedFilteringTreeRootGroup(fix)).not.toBeNull(); - expect(GridFunctions.getAdvancedFilteringEmptyPrompt(fix)).toBeNull(); + expect(QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix)).not.toBeNull(); // Clear the filters. GridFunctions.clickAdvancedFilteringClearFilterButton(fix); @@ -1418,24 +791,25 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Verify there are no filters in the dialog. - expect(GridFunctions.getAdvancedFilteringTreeRootGroup(fix)).toBeNull(); - expect(GridFunctions.getAdvancedFilteringEmptyPrompt(fix)).not.toBeNull(); + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 0, 0); })); - it('Should keep edited conditions and groups inside AF dialog when applying and opening it again.', - fakeAsync(() => { + it('Should keep edited conditions and groups inside AF dialog when applying and opening it again.', fakeAsync(() => { // Apply advanced filter through API. const tree = new FilteringExpressionsTree(FilteringLogic.And); tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') + fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), + conditionName: 'greaterThan' }); const orTree = new FilteringExpressionsTree(FilteringLogic.Or); orTree.filteringOperands.push({ fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', ignoreCase: true }); orTree.filteringOperands.push({ fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', ignoreCase: true }); tree.filteringOperands.push(orTree); @@ -1453,17 +827,17 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Verify the content of the first expression in the inner 'or' group. - verifyExpressionChipContent(fix, [1, 0], 'ProductName', 'Contains', 'angular'); + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0, 0], 'ProductName', 'Contains', 'angular'); // Edit the first expression in the inner 'or' group. - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [1, 0], true); // Double-click the chip + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0, 0]); // Click the chip tick(200); fix.detectChanges(); - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); UIInteractions.clickAndSendInputElementValue(input, 'a', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); fix.detectChanges(); // Apply the filters. @@ -1482,23 +856,25 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Verify the content of the first expression in the inner 'or' group. - verifyExpressionChipContent(fix, [1, 0], 'ProductName', 'Contains', 'a'); + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0, 0], 'ProductName', 'Contains', 'a'); })); - it('Should not keep changes over edited conditions and groups inside AF dialog when canceling and opening it again.', - fakeAsync(() => { + it('Should not keep changes over edited conditions and groups inside AF dialog when canceling and opening it again.', fakeAsync(() => { // Apply advanced filter through API. const tree = new FilteringExpressionsTree(FilteringLogic.And); tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') + fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), + conditionName: 'greaterThan' }); const orTree = new FilteringExpressionsTree(FilteringLogic.Or); orTree.filteringOperands.push({ fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', ignoreCase: true }); orTree.filteringOperands.push({ fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', ignoreCase: true }); tree.filteringOperands.push(orTree); @@ -1516,17 +892,17 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Verify the content of the first expression in the inner 'or' group. - verifyExpressionChipContent(fix, [1, 0], 'ProductName', 'Contains', 'angular'); + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0, 0], 'ProductName', 'Contains', 'angular'); // Edit the first expression in the inner 'or' group. - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [1, 0], true); // Double-click the chip + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0, 0]); // Click the chip tick(200); fix.detectChanges(); - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); UIInteractions.clickAndSendInputElementValue(input, 'a', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); fix.detectChanges(); // Cancel the filters. @@ -1545,7 +921,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Verify the content of the first expression in the inner 'or' group. - verifyExpressionChipContent(fix, [1, 0], 'ProductName', 'Contains', 'angular'); + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0, 0], 'ProductName', 'Contains', 'angular'); })); it('Should not close the AF dialog when clicking outside of it.', fakeAsync(() => { @@ -2045,18 +1421,18 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Add root group. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); // Add a new expression - selectColumnInEditModeExpression(fix, 2); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 2); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); UIInteractions.clickAndSendInputElementValue(input, '1', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); tick(100); fix.detectChanges(); GridFunctions.clickAdvancedFilteringApplyButton(fix); @@ -2079,18 +1455,18 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Add root group. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); // Add a new expression - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - const input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); UIInteractions.clickAndSendInputElementValue(input, '1:', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); tick(100); fix.detectChanges(); GridFunctions.clickAdvancedFilteringApplyButton(fix); @@ -2112,17 +1488,18 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[0].nativeElement; + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); - GridFunctions.clickAdvancedFilteringColumnSelect(fix); + QueryBuilderFunctions.clickQueryBuilderColumnSelect(fix); fix.detectChanges(); - const dropdownItems = GridFunctions.getAdvancedFilteringSelectDropdownItems(fix); - expect(dropdownItems[4].innerText).toBe('ReleaseDate'); + const dropdownItems = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement); + expect((dropdownItems[4] as HTMLElement).innerText).toBe('ReleaseDate'); - selectColumnInEditModeExpression(fix, 4); // Select 'ReleaseDate' column - selectOperatorInEditModeExpression(fix, 0); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 4); // Select 'ReleaseDate' column + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); const dateTimeEditor = fix.debugElement.query(By.directive(IgxDateTimeEditorDirective)) .injector.get(IgxDateTimeEditorDirective); @@ -2142,15 +1519,15 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); - GridFunctions.clickAdvancedFilteringColumnSelect(fix); + QueryBuilderFunctions.clickQueryBuilderColumnSelect(fix); fix.detectChanges(); - selectColumnInEditModeExpression(fix, 4); - selectOperatorInEditModeExpression(fix, 0); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 4); + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); const dateTimeEditor = fix.debugElement.query(By.directive(IgxDateTimeEditorDirective)) .injector.get(IgxDateTimeEditorDirective); @@ -2168,15 +1545,15 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); - GridFunctions.clickAdvancedFilteringColumnSelect(fix); + QueryBuilderFunctions.clickQueryBuilderColumnSelect(fix); fix.detectChanges(); - selectColumnInEditModeExpression(fix, 6); - selectOperatorInEditModeExpression(fix, 0); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 6); + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); const dateTimeEditor = fix.debugElement.query(By.directive(IgxDateTimeEditorDirective)) .injector.get(IgxDateTimeEditorDirective); @@ -2193,15 +1570,15 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); - GridFunctions.clickAdvancedFilteringColumnSelect(fix); + QueryBuilderFunctions.clickQueryBuilderColumnSelect(fix); fix.detectChanges(); - selectColumnInEditModeExpression(fix, 6); - selectOperatorInEditModeExpression(fix, 0); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 6); + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); const dateTimeEditor = fix.debugElement.query(By.directive(IgxDateTimeEditorDirective)) .injector.get(IgxDateTimeEditorDirective); @@ -2222,19 +1599,19 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { GridFunctions.clickAdvancedFilteringButton(fixture); fixture.detectChanges(); - // Click the initial 'Add And Group' button - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fixture, 0); + // Click the initial 'Add Condition' button + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fixture, 0); tick(100); fixture.detectChanges(); // Populate edit inputs - selectColumnInEditModeExpression(fixture, 1); - selectOperatorInEditModeExpression(fixture, 2); - const input = GridFunctions.getAdvancedFilteringValueInput(fixture).querySelector('input'); + QueryBuilderFunctions.selectColumnInEditModeExpression(fixture, 1); + QueryBuilderFunctions.selectOperatorInEditModeExpression(fixture, 2); + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fixture).querySelector('input'); UIInteractions.clickAndSendInputElementValue(input, 'ign', fixture); // Commit the populated expression - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fixture); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fixture); fixture.detectChanges(); // Apply the filters @@ -2250,7 +1627,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { // Change the grid's columns collection fixture.componentInstance.columns = [ { field: 'ID', header: 'ID', width: '200px', type: 'string' }, - { field: 'CompanyName', header: 'Company Name', width: '200px', type: 'string'}, + { field: 'CompanyName', header: 'Company Name', width: '200px', type: 'string' }, { field: 'ContactName', header: 'Contact Name', width: '200px', type: 'string' }, { field: 'ContactTitle', header: 'Contact Title', width: '200px', type: 'string' }, { field: 'City', header: 'City', width: '200px', type: 'string' }, @@ -2279,885 +1656,6 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { // Check for error messages in the console expect(consoleSpy).not.toHaveBeenCalled(); })); - - it('should not trigger accessibility errors when interacting with the edit icon in the advanced filtering expression chip', fakeAsync(() => { - // Apply advanced filter through API to generate chips. - const tree = new FilteringExpressionsTree(FilteringLogic.Or); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 1, condition: IgxNumberFilteringOperand.instance().condition('equals') - }); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - GridFunctions.clickAdvancedFilteringButton(fix); - tick(50); - fix.detectChanges(); - - // Hover over the first visible expression chip to show edit icon. - const expressionItem = fix.nativeElement.querySelectorAll(`.${ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS}`)[0]; - expressionItem.dispatchEvent(new MouseEvent('mouseenter')); - tick(50); - fix.detectChanges(); - - // Click the edit icon on the hovered and focused edit icon. - const editIcon = GridFunctions.getAdvancedFilteringTreeExpressionEditIcon(fix, [0]); - tick(50); - fix.detectChanges(); - expect(editIcon.getAttribute('aria-hidden')).toBe('true'); - expect(editIcon.getAttribute('tabIndex')).toBeFalsy(); - })); - - describe('Context Menu - ', () => { - it('Should discard added group when clicking its operator line without having a single expression.', fakeAsync(() => { - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Add initial 'and' group. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); - tick(100); - fix.detectChanges(); - - // Click operator line. - const rootOperatorLine = GridFunctions.getAdvancedFilteringTreeRootGroupOperatorLine(fix); - rootOperatorLine.click(); - tick(200); - fix.detectChanges(); - - // Verify group is discarded and the context menu was not opened. - expect(GridFunctions.getAdvancedFilteringTreeRootGroup(fix)).toBeNull('Group is not discarded.'); - verifyContextMenuVisibility(fix, false); - })); - - it('Selecting multiple conditions should display the (create group)/(delete filters) context menu.', fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') - }); - const orTree = new FilteringExpressionsTree(FilteringLogic.Or); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push(orTree); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify context menu is not visible. - verifyContextMenuVisibility(fix, false); - - // Select two chips. - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [0]); - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [1, 1]); - tick(200); - fix.detectChanges(); - - // Verify context menu is visible. - verifyContextMenuVisibility(fix, true); - verifyContextMenuType(fix, false); - - // Unselect one of the two selected chips. - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [0]); - tick(200); - fix.detectChanges(); - - // Verify context menu is no longer visible. - verifyContextMenuVisibility(fix, false); - })); - - it('Should create an \'and\' group from multiple selected conditions when respective context menu button is clicked.', - fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') - }); - const orTree = new FilteringExpressionsTree(FilteringLogic.Or); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push(orTree); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify tree layout before the creation of a new group with context menu. - let rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(4); - - let firstItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [0]); // expression - expect(firstItem.classList.contains(ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS)).toBe(true); - - let secondItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [1]); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, false).length).toBe(2); - - // Select two chips. - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [0]); - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [1, 1]); - tick(200); - - // Click "Create And Group" in context menu. - const buttons = GridFunctions.getAdvancedFilteringContextMenuButtons(fix); - buttons[1].click(); - tick(100); - fix.detectChanges(); - - // Verify tree layout after the creation of a new group with context menu. - rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(5); - - firstItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [0]); // the new group - verifyOperatorLine(GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [0]), 'and'); - expect(firstItem.classList.contains(ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS)).toBe(false); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(firstItem, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(firstItem, false).length).toBe(2); - - secondItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [1]); // group - verifyOperatorLine(GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]), 'or'); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, true).length).toBe(1); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, false).length).toBe(1); - })); - - it('Should create an \'or\' group from multiple selected conditions when respective context menu button is clicked.', - fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') - }); - const orTree = new FilteringExpressionsTree(FilteringLogic.Or); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push(orTree); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify tree layout before the creation of a new group with context menu. - let rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(4); - - let firstItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [0]); // expression - expect(firstItem.classList.contains(ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS)).toBe(true); - - let secondItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [1]); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, false).length).toBe(2); - - // Select two chips. - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [0]); - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [1, 1]); - tick(200); - - // Click "Create Or Group" in context menu. - const buttons = GridFunctions.getAdvancedFilteringContextMenuButtons(fix); - buttons[2].click(); - tick(100); - fix.detectChanges(); - - // Verify tree layout after the creation of a new group with context menu. - rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(5); - - firstItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [0]); // the new group - verifyOperatorLine(GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [0]), 'or'); - expect(firstItem.classList.contains(ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS)).toBe(false); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(firstItem, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(firstItem, false).length).toBe(2); - - secondItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [1]); // group - verifyOperatorLine(GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]), 'or'); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, true).length).toBe(1); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, false).length).toBe(1); - })); - - it('Should respect the changes of the groups applied from the context menu.', - fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Verify the filter changes are applied. - expect(grid.filteredData.length).toEqual(0); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify tree layout before the group change through context menu. - let rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(2); - - // Select two chips. - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [0]); - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [1]); - tick(200); - - // Click "Create Or Group" in context menu. - const buttons = GridFunctions.getAdvancedFilteringContextMenuButtons(fix); - buttons[2].click(); - tick(100); - fix.detectChanges(); - - // Close dialog through API. - grid.closeAdvancedFilteringDialog(true); - tick(100); - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify tree layout after the group change through context menu. - rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(1); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(3); - - // Verify the filter changes are applied. - expect(grid.filteredData.length).toEqual(3); - })); - - - it('Should delete all selected conditions when the \'delete filters\' option from context menu is clicked.', - fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') - }); - const orTree = new FilteringExpressionsTree(FilteringLogic.Or); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push(orTree); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify tree layout before the creation of a new group with context menu. - let rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(4); - - let firstItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [0]); // expression - expect(firstItem.classList.contains(ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS)).toBe(true); - - const secondItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [1]); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, false).length).toBe(2); - - // Select two chips. - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [0]); - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [1, 1]); - tick(200); - - // Click "Delete Filters" in context menu. - const buttons = GridFunctions.getAdvancedFilteringContextMenuButtons(fix); - buttons[3].click(); - tick(100); - fix.detectChanges(); - - // Verify tree layout after deleting some expressions with the context menu. - rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(1); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(2); - - firstItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [0]); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(firstItem, true).length).toBe(1); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(firstItem, false).length).toBe(1); - verifyExpressionChipContent(fix, [0, 0], 'ProductName', 'Contains', 'angular'); - })); - - it('Should show/hide group\'s context menu when clicking its operator line.', fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') - }); - const orTree = new FilteringExpressionsTree(FilteringLogic.Or); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push(orTree); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify context menu is not visible. - verifyContextMenuVisibility(fix, false); - - // Click the innner group's operator line. - const operatorLine = GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]); - operatorLine.click(); - fix.detectChanges(); - - // Verify context menu is visible. - verifyContextMenuVisibility(fix, true); - verifyContextMenuType(fix, true); - - // Click the innner group's operator line again. - operatorLine.click(); - tick(); - fix.detectChanges(); - - // Verify context menu is no longer visible. - verifyContextMenuVisibility(fix, false); - })); - - it('Should change the group\'s operator when using its context menu buttons.', async () => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') - }); - const orTree = new FilteringExpressionsTree(FilteringLogic.Or); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push(orTree); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify current operator of inner group. - let operatorLine = GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]); - verifyOperatorLine(operatorLine, 'or'); - - // Click the innner group's operator line. - operatorLine.click(); - await wait(400); - fix.detectChanges(); - - // Click the 'and' button of the button group in the context menu. - const buttonGroup = GridFunctions.getAdvancedFilteringContextMenuButtonGroup(fix); - const andOperatorButton: any = Array.from(buttonGroup.querySelectorAll('.igx-button-group__item')) - .find((b: any) => b.textContent.toLowerCase() === 'and'); - andOperatorButton.click(); - await wait(); - fix.detectChanges(); - - // Verify new operator of inner group. - operatorLine = GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]); - verifyOperatorLine(operatorLine, 'and'); - - // Click the 'or' button of the button group in the context menu. - const orOperatorButton: any = Array.from(buttonGroup.querySelectorAll('.igx-button-group__item')) - .find((b: any) => b.textContent.toLowerCase() === 'or'); - orOperatorButton.click(); - await wait(); - fix.detectChanges(); - - // Verify new operator of inner group. - operatorLine = GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]); - verifyOperatorLine(operatorLine, 'or'); - }); - - it('Should apply changes in the group\'s operator made via its context menu buttons.', fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') - }); - const orTree = new FilteringExpressionsTree(FilteringLogic.Or); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push(orTree); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify current operator of inner group. - let operatorLine = GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]); - verifyOperatorLine(operatorLine, 'or'); - - // Verify the advancedFilteringExpressionsTree inner group's filteringOperand's operator - expect(grid.advancedFilteringExpressionsTree.filteringOperands.length).toEqual(2); - expect((grid.advancedFilteringExpressionsTree.filteringOperands[1] as IFilteringExpressionsTree).operator).toEqual(1); - - // Click the innner group's operator line. - operatorLine.click(); - tick(400); - fix.detectChanges(); - - // Click the 'and' button of the button group in the context menu. - const buttonGroup = GridFunctions.getAdvancedFilteringContextMenuButtonGroup(fix); - const andOperatorButton: any = Array.from(buttonGroup.querySelectorAll('.igx-button-group__item')) - .find((b: any) => b.textContent.toLowerCase() === 'and'); - andOperatorButton.click(); - fix.detectChanges(); - - // Verify new operator of inner group. - operatorLine = GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]); - verifyOperatorLine(operatorLine, 'and'); - - // Apply new advanced filtering logic - GridFunctions.clickAdvancedFilteringApplyButton(fix); - tick(100); - fix.detectChanges(); - - // Open the advanced filtering dialog - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify the operator of inner group should persist as "And" - operatorLine = GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]); - verifyOperatorLine(operatorLine, 'and'); - - // Verify the advancedFilteringExpressionsTree inner group's filteringOperand's operator - expect(grid.advancedFilteringExpressionsTree.filteringOperands.length).toEqual(2); - expect((grid.advancedFilteringExpressionsTree.filteringOperands[1] as IFilteringExpressionsTree).operator).toEqual(0); - })); - - it('Should ungroup the group\'s children and append them to next parent group when click \'ungroup\' from context menu.', - fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') - }); - const orTree = new FilteringExpressionsTree(FilteringLogic.Or); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push(orTree); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify tree layout before the the ungrouping with context menu. - let rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(4); - - let firstItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [0]); // expression - expect(firstItem.classList.contains(ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS)).toBe(true); - - const secondItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [1]); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, false).length).toBe(2); - - // Click the innner group's operator line. - const operatorLine = GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]); - operatorLine.click(); - tick(400); - fix.detectChanges(); - - // Click "Ungroup" in context menu. - const buttons = GridFunctions.getAdvancedFilteringContextMenuButtons(fix); - buttons[3].click(); - tick(100); - fix.detectChanges(); - - // Verify tree layout after ungrouping a group with the context menu. - rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(3); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(3); - // Verify three expression in the root group are what remains. - for (let index = 0; index < 3; index++) { - firstItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [index]); // expression - expect(firstItem.classList.contains(ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS)).toBe(true); - } - - // Should apply this change to the advancedFilteringExpressionsTree - GridFunctions.clickAdvancedFilteringApplyButton(fix); - tick(100); - fix.detectChanges(); - - // Open the advanced filtering dialog - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify the layout after as above - rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(3); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(3); - // Verify three expression in the root group are what remains, no inner groups - for (let index = 0; index < 3; index++) { - firstItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [index]); // expression - expect(firstItem.classList.contains(ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS)).toBe(true); - } - })); - - it('Ungroup button of the root group\'s context menu should be disabled.', - fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') - }); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Click root group's operator line. - const rootOperatorLine = GridFunctions.getAdvancedFilteringTreeRootGroupOperatorLine(fix); - rootOperatorLine.click(); - tick(200); - fix.detectChanges(); - - // Verify the ungroup button is disabled. - const ungroupButton = GridFunctions.getAdvancedFilteringContextMenuButtons(fix)[3]; - ControlsFunction.verifyButtonIsDisabled(ungroupButton); - })); - - it('Should delete the group from the tree when click \'delete\' from context menu.', - fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') - }); - const orTree = new FilteringExpressionsTree(FilteringLogic.Or); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push(orTree); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify tree layout before deleting a group through context menu. - let rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(4); - - let firstItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [0]); // expression - expect(firstItem.classList.contains(ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS)).toBe(true); - - const secondItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [1]); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, true).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(secondItem, false).length).toBe(2); - - // Click the innner group's operator line. - const operatorLine = GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]); - operatorLine.click(); - tick(400); - fix.detectChanges(); - - // Click "Delete" in context menu. - const buttons = GridFunctions.getAdvancedFilteringContextMenuButtons(fix); - buttons[4].click(); - tick(100); - fix.detectChanges(); - - // Verify tree layout after deleting a group through context menu. - rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(1); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(1); - - firstItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [0]); // expression - expect(firstItem.classList.contains(ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS)).toBe(true); - - // Should apply this change to the advancedFilteringExpressionsTree - GridFunctions.clickAdvancedFilteringApplyButton(fix); - tick(100); - fix.detectChanges(); - - // Open the advanced filtering dialog - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify the layout after as above - rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); // group - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, true).length).toBe(1); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(1); - - firstItem = GridFunctions.getAdvancedFilteringTreeItem(fix, [0]); // expression - expect(firstItem.classList.contains(ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS)).toBe(true); - - // Verify the advancedFilteringExpressionsTree filteringOperands operator - expect(grid.advancedFilteringExpressionsTree.filteringOperands.length).toEqual(1); - })); - - it('Should close the context menu when clicking its close button.' , fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.Or); - tree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Click root operator line to open the context menu. - const rootOperatorLine = GridFunctions.getAdvancedFilteringTreeRootGroupOperatorLine(fix); - rootOperatorLine.click(); - fix.detectChanges(); - - // Verify context menu is opened. - verifyContextMenuVisibility(fix, true); - - // Click close button of context menu. - const buttons = GridFunctions.getAdvancedFilteringContextMenuButtons(fix); - buttons[0].click(); - tick(); - - // Verify context menu is closed. - verifyContextMenuVisibility(fix, false); - })); - }); - - describe('Keyboard Navigation/Interaction - ', () => { - it('Should close the context menu when pressing \'Escape\' on it.' , fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.Or); - tree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Click root operator line to open the context menu. - const rootOperatorLine = GridFunctions.getAdvancedFilteringTreeRootGroupOperatorLine(fix); - rootOperatorLine.click(); - fix.detectChanges(); - - // Verify context menu is opened. - verifyContextMenuVisibility(fix, true); - - // Press 'Escape' on the context menu. - UIInteractions.triggerKeyDownEvtUponElem('Escape', GridFunctions.getAdvancedFilteringContextMenu(fix)); - tick(); - - // Verify context menu is closed. - verifyContextMenuVisibility(fix, false); - })); - - it('Should select/deselect a condition when pressing \'Enter\' on its respective chip.' , fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.Or); - tree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify first chip is not selected. - verifyExpressionChipSelection(fix, [1], false); - - // Press 'Enter' on the second chip and verify it is selected. - UIInteractions.triggerKeyDownEvtUponElem('Enter', GridFunctions.getAdvancedFilteringTreeExpressionChip(fix, [1])); - tick(200); - fix.detectChanges(); - verifyExpressionChipSelection(fix, [1], true); - - // Press 'Enter' on the second chip again and verify it is not selected. - UIInteractions.triggerKeyDownEvtUponElem('Enter', GridFunctions.getAdvancedFilteringTreeExpressionChip(fix, [1])); - tick(200); - fix.detectChanges(); - verifyExpressionChipSelection(fix, [1], false); - })); - - it('Should remove a chip in when pressing \'Enter\' on its \'remove\' icon.' , fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.Or); - tree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify the there are two chip expressions. - let rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(2); - expect(GridFunctions.getAdvancedFilteringTreeChildExpressions(rootGroup, true).length).toBe(2); - - // Press 'Enter' on the remove icon of the second chip. - const chip = GridFunctions.getAdvancedFilteringTreeExpressionChip(fix, [1]); - const removeIcon = ControlsFunction.getChipRemoveButton(chip); - UIInteractions.triggerKeyDownEvtUponElem('Enter', removeIcon); - tick(200); - fix.detectChanges(); - - // Verify the there is only one chip expression. - rootGroup = GridFunctions.getAdvancedFilteringTreeRootGroup(fix); - expect(GridFunctions.getAdvancedFilteringTreeChildItems(rootGroup, false).length).toBe(1); - expect(GridFunctions.getAdvancedFilteringTreeChildExpressions(rootGroup, true).length).toBe(1); - })); - - it('Should select/deselect all child conditions and groups when pressing \'Enter\' on a group\'s operator line.', - fakeAsync(() => { - // Apply advanced filter through API. - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') - }); - const orTree = new FilteringExpressionsTree(FilteringLogic.Or); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'angular', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - orTree.filteringOperands.push({ - fieldName: 'ProductName', searchVal: 'script', condition: IgxStringFilteringOperand.instance().condition('contains'), - ignoreCase: true - }); - tree.filteringOperands.push(orTree); - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Press 'Enter' on the root group's operator line - let rootOperatorLine = GridFunctions.getAdvancedFilteringTreeRootGroupOperatorLine(fix); - const keyboardEvent = new KeyboardEvent('keydown', { key: 'Enter' }); - rootOperatorLine.dispatchEvent(keyboardEvent); - tick(); - fix.detectChanges(); - - // Simulate end of chip selection animation - const chipSelect = fix.nativeElement.querySelector(CHIP_SELECT_CLASS); - const transitionEvent = new TransitionEvent('transitionend', { - propertyName: 'width' - }); - chipSelect.dispatchEvent(transitionEvent); - - // Verify items are selected and context menu is opened - verifyChildrenSelection(GridFunctions.getAdvancedFilteringExpressionsContainer(fix), true); - verifyContextMenuVisibility(fix, true); - - // Press 'Enter' on the root group's operator line again - rootOperatorLine = GridFunctions.getAdvancedFilteringTreeRootGroupOperatorLine(fix); - rootOperatorLine.dispatchEvent(keyboardEvent); - tick(); - - // Verify items are not selected and context menu is closed - verifyChildrenSelection(GridFunctions.getAdvancedFilteringExpressionsContainer(fix), false); - verifyContextMenuVisibility(fix, false); - })); - - }); - }); describe('Advanced filtering with toolbar', () => { @@ -3227,18 +1725,14 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { igx_grid_filter_operator_and: 'My and', igx_grid_filter_operator_or: 'My or', igx_grid_advanced_filter_title: 'My advanced filter', - igx_grid_advanced_filter_and_group: 'My and group', - igx_grid_advanced_filter_or_group: 'My or group', igx_grid_advanced_filter_end_group: 'My end group', igx_grid_advanced_filter_create_and_group: 'My create and group', - igx_grid_advanced_filter_create_or_group: 'My create or group', igx_grid_advanced_filter_and_label: 'My and', igx_grid_advanced_filter_or_label: 'My or', - igx_grid_advanced_filter_add_condition: 'My condition', + igx_grid_advanced_filter_add_condition_root: 'My condition', + igx_grid_advanced_filter_add_group_root: 'My group', igx_grid_advanced_filter_ungroup: 'My ungroup', - igx_grid_advanced_filter_delete: 'My delete', - igx_grid_advanced_filter_delete_filters: 'My delete filters', - igx_grid_advanced_filter_initial_text: 'My initial text' + igx_grid_advanced_filter_delete_filters: 'My delete filters' }); fix.detectChanges(); @@ -3246,92 +1740,28 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - expect(GridFunctions.getAdvancedFilteringHeaderText(fix)).toBe('My advanced filter'); - expect(GridFunctions.getAdvancedFilteringHeaderLegendItemAnd(fix).innerText).toBe('My and'); - expect(GridFunctions.getAdvancedFilteringHeaderLegendItemOr(fix).innerText).toBe('My or'); - expect(GridFunctions.getAdvancedFilteringInitialAddGroupButtons(fix)[0].querySelector('span').innerText) - .toBe('My and group'); - expect(GridFunctions.getAdvancedFilteringInitialAddGroupButtons(fix)[1].querySelector('span').innerText) - .toBe('My or group'); - expect(GridFunctions.getAdvancedFilteringEmptyPrompt(fix).innerText).toBe('My initial text'); + expect(QueryBuilderFunctions.getQueryBuilderHeaderText(fix).trim()).toBe('My advanced filter'); + expect(QueryBuilderFunctions.getQueryBuilderInitialAddConditionBtn(fix).querySelector('span').innerText) + .toBe('My condition'); - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); - expect(GridFunctions.getAdvancedFilteringTreeRootGroupButtons(fix, 0)[0].querySelector('span').innerText) - .toBe('My condition'); - expect(GridFunctions.getAdvancedFilteringTreeRootGroupButtons(fix, 0)[1].querySelector('span').innerText) - .toBe('My and group'); - expect(GridFunctions.getAdvancedFilteringTreeRootGroupButtons(fix, 0)[2].querySelector('span').innerText) - .toBe('My or group'); // Populate edit inputs. - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - let input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); + let input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); UIInteractions.clickAndSendInputElementValue(input, 'angular', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); - fix.detectChanges(); - - const rootOperatorLine = GridFunctions.getAdvancedFilteringTreeRootGroupOperatorLine(fix); - rootOperatorLine.click(); - fix.detectChanges(); - - const buttonGroupItems = GridFunctions.sortNativeElementsHorizontally( - Array.from(GridFunctions.getAdvancedFilteringContextMenuButtonGroup(fix) - .querySelectorAll('.igx-button-group__item-content'))); - expect(buttonGroupItems[0].textContent).toBe('My and'); - expect(buttonGroupItems[1].textContent).toBe('My or'); - expect(GridFunctions.getAdvancedFilteringContextMenuButtons(fix)[3].querySelector('span').innerText) - .toBe('My ungroup'); - expect(GridFunctions.getAdvancedFilteringContextMenuButtons(fix)[4].querySelector('span').innerText) - .toBe('My delete'); - - // Close context menu. - GridFunctions.clickAdvancedFilteringContextMenuCloseButton(fix); - fix.detectChanges(); - - // Add another expression to root group. - let btn = GridFunctions.getAdvancedFilteringTreeRootGroupButtons(fix, 0)[0]; - btn.click(); - fix.detectChanges(); - - // Populate edit inputs. - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - - input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'script', fix); // Type filter value. - // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); - fix.detectChanges(); - - // Select two chips. - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [0]); - GridFunctions.clickAdvancedFilteringTreeExpressionChip(fix, [1]); - tick(200); - fix.detectChanges(); - - expect(GridFunctions.getAdvancedFilteringContextMenuButtons(fix)[1].innerText).toBe('My create and group'); - expect(GridFunctions.getAdvancedFilteringContextMenuButtons(fix)[2].innerText).toBe('My create or group'); - expect(GridFunctions.getAdvancedFilteringContextMenuButtons(fix)[3].innerText).toBe('My delete filters'); - - // Close context menu. - GridFunctions.clickAdvancedFilteringContextMenuCloseButton(fix); - tick(100); - fix.detectChanges(); - - // Add an 'or' group to root group. - btn = GridFunctions.getAdvancedFilteringTreeRootGroupButtons(fix, 0)[2]; - btn.click(); - tick(100); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); fix.detectChanges(); - - const endGroupButton = GridFunctions.getAdvancedFilteringTreeGroupButtons(fix, [2], 0)[3]; - expect(endGroupButton.querySelector('span').innerText).toBe('My end group'); + expect((QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0)[0] as HTMLElement).querySelector('span').innerText) + .toBe('My condition'); + expect((QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0)[1] as HTMLElement).querySelector('span').innerText) + .toBe('My group'); })); }); @@ -3348,48 +1778,20 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { grid.openAdvancedFilteringDialog(); fix.detectChanges(); - // Click the initial 'Add And Group' button. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[0].nativeElement; + + // Click the initial 'Add Condition' button. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); // Open column dropdown and verify that there are no column groups present. - GridFunctions.clickAdvancedFilteringColumnSelect(fix); + QueryBuilderFunctions.clickQueryBuilderColumnSelect(fix); fix.detectChanges(); - const dropdownValues = GridFunctions.getAdvancedFilteringSelectDropdownItems(fix).map((x: any) => x.innerText); + const dropdownValues = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText); const expectedValues = ['ID', 'ProductName', 'Downloads', 'Released', 'ReleaseDate', 'Another Field', 'DateTimeCreated']; expect(expectedValues).toEqual(dropdownValues); })); - - it('Should correctly focus the search value input when editing the filtering expression', fakeAsync(() => { - // Open dialog through API. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - //Create dateTime filtering expression - const tree = new FilteringExpressionsTree(FilteringLogic.And); - tree.filteringOperands.push({ - fieldName: 'DateTimeCreated', searchVal: '11/11/2000 10:11:11 AM', condition: IgxStringFilteringOperand.instance().condition('equals') - }); - - grid.advancedFilteringExpressionsTree = tree; - fix.detectChanges(); - - // Hover the last visible expression chip - const expressionItem = fix.nativeElement.querySelectorAll(`.${ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS}`)[0]; - expressionItem.dispatchEvent(new MouseEvent('mouseenter')); - tick(); - fix.detectChanges(); - - // Click the edit icon to enter edit mode of the expression. - GridFunctions.clickAdvancedFilteringTreeExpressionChipEditIcon(fix, [0]); - tick(); - fix.detectChanges(); - - //Check for the active element - const searchValueInput = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); - expect(document.activeElement).toBe(searchValueInput, 'The input should be the active element.'); - })); }); describe('External - ', () => { @@ -3402,32 +1804,32 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { it('Should allow hosting Advanced Filtering dialog outside of the grid.', fakeAsync(() => { // Add a root 'and' group. - GridFunctions.clickAdvancedFilteringInitialAddGroupButton(fix, 0); + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); tick(100); fix.detectChanges(); // Populate edit inputs. - selectColumnInEditModeExpression(fix, 2); // Select 'Downloads' column. - selectOperatorInEditModeExpression(fix, 2); // Select 'Greater Than' operator. - let input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 2); // Select 'Downloads' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2); // Select 'Greater Than' operator. + let input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); UIInteractions.clickAndSendInputElementValue(input, '100', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); fix.detectChanges(); // Add new expression to the root group. - const addExpressionBtn = GridFunctions.getAdvancedFilteringTreeRootGroupButtons(fix, 0)[0]; + const addExpressionBtn = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0)[0] as HTMLElement; addExpressionBtn.click(); tick(100); fix.detectChanges(); // Populate edit inputs. - selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - input = GridFunctions.getAdvancedFilteringValueInput(fix).querySelector('input'); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); UIInteractions.clickAndSendInputElementValue(input, 'ignite', fix); // Type filter value. // Commit the populated expression. - GridFunctions.clickAdvancedFilteringExpressionCommitButton(fix); + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); fix.detectChanges(); // Apply the filters. @@ -3511,190 +1913,15 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { expect(grid.filteredData).toBe(null); })); }); - - describe('Overlay settings - ', () => { - it('Should respect the overlay settings set in the component.', fakeAsync(() => { - const fix = TestBed.createComponent(IgxGridAdvancedFilteringOverlaySettingsComponent); - const grid: IgxGridComponent = fix.componentInstance.grid; - fix.detectChanges(); - - // Open Advanced Filtering dialog. - grid.openAdvancedFilteringDialog(); - fix.detectChanges(); - - // Verify context menu is opened. - expect(GridFunctions.getAdvancedFilteringComponent(fix)).not.toBeNull(); - - // Press 'Escape' on the context menu. - UIInteractions.triggerKeyDownEvtUponElem('Escape', GridFunctions.getRowEditingOverlay(fix)); - tick(); - fix.detectChanges(); - - // Verify context menu is opened. - expect(GridFunctions.getAdvancedFilteringComponent(fix)).not.toBeNull(); - })); - }); }); -const selectColumnInEditModeExpression = (fix, dropdownItemIndex: number) => { - GridFunctions.clickAdvancedFilteringColumnSelect(fix); - fix.detectChanges(); - GridFunctions.clickAdvancedFilteringSelectDropdownItem(fix, dropdownItemIndex); - tick(); - fix.detectChanges(); -}; - -const selectOperatorInEditModeExpression = (fix, dropdownItemIndex: number) => { - GridFunctions.clickAdvancedFilteringOperatorSelect(fix); - fix.detectChanges(); - GridFunctions.clickAdvancedFilteringSelectDropdownItem(fix, dropdownItemIndex); - tick(); - fix.detectChanges(); -}; - -/** - * Verifies the type of the operator line ('and' or 'or'). - * (NOTE: The 'operator' argument must be a string with a value that is either 'and' or 'or'.) - */ -const verifyOperatorLine = (operatorLine: HTMLElement, operator: string) => { - expect(operator === 'and' || operator === 'or').toBe(true, 'operator must be \'and\' or \'or\''); - - if (operator === 'and') { - expect(operatorLine.classList.contains(ADVANCED_FILTERING_OPERATOR_LINE_AND_CSS_CLASS)).toBe(true, 'incorrect operator line'); - expect(operatorLine.classList.contains(ADVANCED_FILTERING_OPERATOR_LINE_OR_CSS_CLASS)).toBe(false, 'incorrect operator line'); - } else { - expect(operatorLine.classList.contains(ADVANCED_FILTERING_OPERATOR_LINE_AND_CSS_CLASS)).toBe(false, 'incorrect operator line'); - expect(operatorLine.classList.contains(ADVANCED_FILTERING_OPERATOR_LINE_OR_CSS_CLASS)).toBe(true, 'incorrect operator line'); - } -}; - -const verifyOperatorLineSelection = (operatorLine: HTMLElement, shouldBeSelected: boolean) => { - expect(operatorLine.classList.contains(ADVANCED_FILTERING_OPERATOR_LINE_SELECTED_CSS_CLASS)) - .toBe(shouldBeSelected, 'incorrect selection state of the operator line'); -}; - -const verifyExpressionChipContent = (fix, path: number[], columnText: string, operatorText: string, valueText: string) => { - const chip = GridFunctions.getAdvancedFilteringTreeExpressionChip(fix, path); - const chipSpans = GridFunctions.sortNativeElementsHorizontally(Array.from(chip.querySelectorAll('span'))); - const columnSpan = chipSpans[0]; - const operatorSpan = chipSpans[1]; - const valueSpan = chipSpans[2]; - expect(columnSpan.textContent.toLowerCase().trim()).toBe(columnText.toLowerCase(), 'incorrect chip column'); - expect(operatorSpan.textContent.toLowerCase().trim()).toBe(operatorText.toLowerCase(), 'incorrect chip operator'); - expect(valueSpan.textContent.toLowerCase().trim()).toBe(valueText.toLowerCase(), 'incorrect chip filter value'); -}; - -const verifyExpressionChipSelection = (fix, path: number[], shouldBeSelected: boolean) => { - const chip = GridFunctions.getAdvancedFilteringTreeExpressionChip(fix, path); - verifyExpressionChipSelectionByChip(chip, shouldBeSelected); -}; - -const verifyExpressionChipSelectionByChip = (chip: HTMLElement, shouldBeSelected: boolean) => { - const chipItem = chip.querySelector('.igx-chip__item'); - if (shouldBeSelected) { - expect(chipItem.classList.contains('igx-chip__item--selected')).toBe(true, 'chip is not selected'); - expect(chipItem.querySelector(CHIP_SELECT_CLASS)).not.toBeNull(); - } else { - expect(chipItem.classList.contains('igx-chip__item--selected')).toBe(false, 'chip is selected'); - expect(chipItem.querySelector(CHIP_SELECT_CLASS)).toBeNull(); - } -}; - -/** - * Verifies that all children (operator lines and expression chips) of the provided 'parent' are selected. - */ -const verifyChildrenSelection = (parent: HTMLElement, shouldBeSelected: boolean) => { - const allOperatorLines: any[] = Array.from(parent.querySelectorAll('.igx-filter-tree__line')); - const allExpressionChips: any[] = Array.from(parent.querySelectorAll(`.${ADVANCED_FILTERING_EXPRESSION_ITEM_CLASS}`)); - for (const operatorLine of allOperatorLines) { - verifyOperatorLineSelection(operatorLine, shouldBeSelected); - } - for (const expressionChip of allExpressionChips) { - verifyExpressionChipSelectionByChip(expressionChip, shouldBeSelected); - } -}; - -const verifyEditModeExpressionInputStates = (fix, - columnSelectEnabled: boolean, - operatorSelectEnabled: boolean, - valueInputEnabled: boolean, - commitButtonEnabled: boolean) => { - // Verify the column select state. - const columnInputGroup = GridFunctions.getAdvancedFilteringColumnSelect(fix).querySelector('igx-input-group'); - expect(!columnInputGroup.classList.contains('igx-input-group--disabled')).toBe(columnSelectEnabled, - 'incorrect column select state'); - - // Verify the operator select state. - const operatorInputGroup = GridFunctions.getAdvancedFilteringOperatorSelect(fix).querySelector('igx-input-group'); - expect(!operatorInputGroup.classList.contains('igx-input-group--disabled')).toBe(operatorSelectEnabled, - 'incorrect operator select state'); - - // Verify the value input state. - const editModeContainer = GridFunctions.getAdvancedFilteringEditModeContainer(fix); - const valueInputGroup = GridFunctions.sortNativeElementsHorizontally( - Array.from(editModeContainer.querySelectorAll('igx-input-group')))[2]; - expect(!valueInputGroup.classList.contains('igx-input-group--disabled')).toBe(valueInputEnabled, - 'incorrect value input state'); - - // Verify commit expression button state - const commitButton = GridFunctions.getAdvancedFilteringExpressionCommitButton(fix); - ControlsFunction.verifyButtonIsDisabled(commitButton, !commitButtonEnabled); - - - // Verify close expression button is enabled. - const closeButton = GridFunctions.getAdvancedFilteringExpressionCloseButton(fix); - ControlsFunction.verifyButtonIsDisabled(closeButton, false); -}; - -const verifyEditModeExpressionInputValues = (fix, - columnText: string, - operatorText: string, - valueText: string) => { - const columnInput = GridFunctions.getAdvancedFilteringColumnSelect(fix).querySelector('input'); - const operatorInput = GridFunctions.getAdvancedFilteringColumnSelect(fix).querySelector('input'); - const editModeContainer = GridFunctions.getAdvancedFilteringEditModeContainer(fix); - const valueInput = GridFunctions.sortNativeElementsHorizontally(Array.from(editModeContainer.querySelectorAll('input')))[2]; - expect(columnInput.value).toBe(columnText); - expect(operatorInput.value).toBe(operatorText); - expect(valueInput.value).toBe(valueText); -}; const verifyElementIsInExpressionsContainerView = (fix, element: HTMLElement) => { const elementRect = element.getBoundingClientRect(); - const exprContainer: HTMLElement = GridFunctions.getAdvancedFilteringExpressionsContainer(fix); + const exprContainer: HTMLElement = QueryBuilderFunctions.getQueryBuilderExpressionsContainer(fix) as HTMLElement; const exprContainerRect = exprContainer.getBoundingClientRect(); expect(elementRect.top >= exprContainerRect.top).toBe(true, 'top is not in view'); expect(elementRect.bottom <= exprContainerRect.bottom).toBe(true, 'bottom is not in view'); expect(elementRect.left >= exprContainerRect.left).toBe(true, 'left is not in view'); expect(elementRect.right <= exprContainerRect.right).toBe(true, 'right is not in view'); }; - -const verifyContextMenuVisibility = (fix, shouldBeVisible: boolean) => { - const contextMenu: HTMLElement = GridFunctions.getAdvancedFilteringContextMenu(fix); - const contextMenuRect = contextMenu.getBoundingClientRect(); - expect(contextMenu.classList.contains('igx-toggle--hidden')).toBe(!shouldBeVisible, 'incorrect context menu visibility'); - expect(contextMenuRect.width === 0 && contextMenuRect.height === 0).toBe(!shouldBeVisible, 'incorrect context menu dimensions'); -}; - -/** - * Verifies the type of the context menu (menu for specific group or menu for combining expressions). - * If contextual group is expected, the context menu should contain buttons for operator change, ungroup and delete. - * If contextual group is not expected, the context menu should contain buttons for creating new group by combining expressions. - */ -const verifyContextMenuType = (fix, shouldBeContextualGroup: boolean) => { - const contextMenuButtons = GridFunctions.getAdvancedFilteringContextMenuButtons(fix); - expect(GridFunctions.getAdvancedFilteringContextMenuButtonGroup(fix) !== null).toBe(shouldBeContextualGroup); - - if (shouldBeContextualGroup) { - expect(contextMenuButtons.length).toBe(5, 'incorrect buttons count in context menu'); - expect(contextMenuButtons[0].innerText.toLowerCase()).toBe('close'); - expect(contextMenuButtons[3].querySelector('span').innerText.toLowerCase()).toBe('ungroup'); - expect(contextMenuButtons[4].querySelector('span').innerText.toLowerCase()).toBe('delete'); - } else { - expect(contextMenuButtons.length).toBe(4, 'incorrect buttons count in context menu'); - expect(contextMenuButtons[0].innerText.toLowerCase()).toBe('close'); - expect(contextMenuButtons[1].innerText.toLowerCase().trim()).toBe('create "and" group'); - expect(contextMenuButtons[2].innerText.toLowerCase().trim()).toBe('create "or" group'); - expect(contextMenuButtons[3].innerText.toLowerCase().trim()).toBe('delete filters'); - } -}; diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-ui.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-ui.spec.ts index b065673afae..c84074b4e36 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-ui.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-ui.spec.ts @@ -547,12 +547,14 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const expression = { fieldName: 'ProductName', searchVal: 'g', - condition: IgxStringFilteringOperand.instance().condition('contains') + condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains' }; const expression1 = { fieldName: 'ProductName', searchVal: 'I', - condition: IgxStringFilteringOperand.instance().condition('contains') + condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains' }; filteringExpressionsTree.filteringOperands.push(expression); filteringExpressionsTree.filteringOperands.push(expression1); @@ -596,7 +598,8 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const expression = { fieldName: 'ProductName', searchVal: 'Ignite', - condition: IgxStringFilteringOperand.instance().condition('startsWith') + condition: IgxStringFilteringOperand.instance().condition('startsWith'), + conditionName: 'startsWith' }; filteringExpressionsTree.filteringOperands.push(expression); @@ -668,12 +671,14 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const expression = { fieldName: 'ProductName', searchVal: 'Ignite', - condition: IgxStringFilteringOperand.instance().condition('startsWith') + condition: IgxStringFilteringOperand.instance().condition('startsWith'), + conditionName: 'startsWith' }; const expression1 = { fieldName: 'ProductName', searchVal: 'Angular', - condition: IgxStringFilteringOperand.instance().condition('contains') + condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains' }; filteringExpressionsTree.filteringOperands.push(expression); filteringExpressionsTree.filteringOperands.push(expression1); @@ -832,7 +837,8 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const expression = { fieldName: 'ProductName', searchVal: 'I', - condition: IgxStringFilteringOperand.instance().condition('startsWith') + condition: IgxStringFilteringOperand.instance().condition('startsWith'), + conditionName: 'startsWith' }; filteringExpressionsTree.filteringOperands.push(expression); } @@ -898,13 +904,15 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const expression1 = { fieldName: 'ProductName', searchVal: 'Ignite', - condition: IgxStringFilteringOperand.instance().condition('startsWith') + condition: IgxStringFilteringOperand.instance().condition('startsWith'), + conditionName: 'startsWith' }; const expression2 = { fieldName: 'ProductName', searchVal: 'test', - condition: IgxStringFilteringOperand.instance().condition('contains') + condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains' }; filteringExpressionsTree.filteringOperands.push(expression1); @@ -1064,12 +1072,14 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const expression = { fieldName: 'ProductName', searchVal: 'Ignite', - condition: IgxStringFilteringOperand.instance().condition('startsWith') + condition: IgxStringFilteringOperand.instance().condition('startsWith'), + conditionName: 'startsWith' }; const expression1 = { fieldName: 'ProductName', searchVal: 'Angular', - condition: IgxStringFilteringOperand.instance().condition('contains') + condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains' }; filteringExpressionsTree.filteringOperands.push(expression); filteringExpressionsTree.filteringOperands.push(expression1); @@ -1100,12 +1110,14 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const expression = { fieldName: 'ProductName', searchVal: 'Ignite', - condition: IgxStringFilteringOperand.instance().condition('startsWith') + condition: IgxStringFilteringOperand.instance().condition('startsWith'), + conditionName: 'startsWith' }; const expression1 = { fieldName: 'ProductName', searchVal: 'for', - condition: IgxStringFilteringOperand.instance().condition('contains') + condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains' }; filteringExpressionsTree.filteringOperands.push(expression); filteringExpressionsTree.filteringOperands.push(expression1); @@ -1147,8 +1159,8 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'o', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'o', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -1466,9 +1478,9 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'z', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'n', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'g', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'z', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'n', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'g', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -1492,9 +1504,9 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'n', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'z', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'g', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'n', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'z', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'g', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -1550,9 +1562,9 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'e', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'i', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'e', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'i', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -1749,9 +1761,9 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'e', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'i', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'e', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'i', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -1783,9 +1795,9 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'e', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'i', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'e', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'i', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -1821,9 +1833,9 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'e', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'i', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'e', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'i', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -1858,8 +1870,8 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'e', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'e', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -1949,10 +1961,10 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'e', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'i', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'n', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'e', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'i', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'n', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -2441,11 +2453,11 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'x', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'y', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'i', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'g', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'n', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'x', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'y', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'i', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'g', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'n', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -2517,8 +2529,8 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'o', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'o', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -2605,8 +2617,8 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'Downloads'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'Downloads', searchVal: 25, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') }, - { fieldName: 'Downloads', searchVal: 200, condition: IgxNumberFilteringOperand.instance().condition('lessThan') } + { fieldName: 'Downloads', searchVal: 25, condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), conditionName: 'greaterThan' }, + { fieldName: 'Downloads', searchVal: 200, condition: IgxNumberFilteringOperand.instance().condition('lessThan'), conditionName: 'lessThan' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -2729,7 +2741,8 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const expression = { fieldName: 'ProductName', searchVal: 'Ignite', - condition: IgxStringFilteringOperand.instance().condition('startsWith') + condition: IgxStringFilteringOperand.instance().condition('startsWith'), + conditionName: 'startsWith' }; filteringExpressionsTree.filteringOperands.push(expression); grid.filteringExpressionsTree = filteringExpressionsTree; @@ -3019,16 +3032,6 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { ); })); - it('Should emit filteringDone when we clicked reset - Boolean column type', fakeAsync(() => { - emitFilteringDoneOnResetClick( - fix, - grid, - true, - 'Released', - IgxBooleanFilteringOperand.instance().condition('true') - ); - })); - it('Should emit filteringDone when we clicked reset - DateTime column type', fakeAsync(() => { emitFilteringDoneOnResetClick( fix, @@ -3079,16 +3082,6 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { ); })); - it('Should emit filteringDone when clear the input of filteringUI - Boolean column type', fakeAsync(() => { - emitFilteringDoneOnInputClear( - fix, - grid, - true, - 'Released', - IgxBooleanFilteringOperand.instance().condition('true') - ); - })); - it('Should emit filteringDone when clear the input of filteringUI - DateTime column type', fakeAsync(() => { emitFilteringDoneOnInputClear( fix, @@ -3440,8 +3433,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.And, 'Downloads'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals') }, - { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals') } + { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' }, + { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -3460,7 +3453,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.Or, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'Angular', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'Angular', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -3494,7 +3487,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.Or, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'Angular', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'Angular', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -3528,8 +3521,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.Or, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'Angular', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'Ignite', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'Angular', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'Ignite', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -3557,8 +3550,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.Or, 'Downloads'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'Downloads', searchVal: 254, condition: IgxNumberFilteringOperand.instance().condition('equals') }, - { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals') } + { fieldName: 'Downloads', searchVal: 254, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' }, + { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -3583,8 +3576,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.Or, 'Downloads'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'Downloads', searchVal: 254, condition: IgxNumberFilteringOperand.instance().condition('equals') }, - { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals') } + { fieldName: 'Downloads', searchVal: 254, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' }, + { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -3616,8 +3609,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.Or, 'Downloads'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'Downloads', searchVal: 254, condition: IgxNumberFilteringOperand.instance().condition('equals') }, - { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals') } + { fieldName: 'Downloads', searchVal: 254, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' }, + { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -3672,8 +3665,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.Or, 'Downloads'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'Downloads', searchVal: 254, condition: IgxNumberFilteringOperand.instance().condition('equals') }, - { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('lessThan') } + { fieldName: 'Downloads', searchVal: 254, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' }, + { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('lessThan'), conditionName: 'lessThan' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -3716,8 +3709,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.Or, 'Downloads'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'Downloads', searchVal: 254, condition: IgxNumberFilteringOperand.instance().condition('equals') }, - { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals') } + { fieldName: 'Downloads', searchVal: 254, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' }, + { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -3735,8 +3728,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.Or, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'Angular', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'Ignite', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'Angular', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'Ignite', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -3763,8 +3756,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.Or, 'ProductName'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'ProductName', searchVal: 'Angular', condition: IgxStringFilteringOperand.instance().condition('contains') }, - { fieldName: 'ProductName', searchVal: 'Ignite', condition: IgxStringFilteringOperand.instance().condition('contains') } + { fieldName: 'ProductName', searchVal: 'Angular', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' }, + { fieldName: 'ProductName', searchVal: 'Ignite', condition: IgxStringFilteringOperand.instance().condition('contains'), conditionName: 'contains' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -3862,8 +3855,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); const columnsFilteringTree = new FilteringExpressionsTree(FilteringLogic.Or, 'Downloads'); columnsFilteringTree.filteringOperands = [ - { fieldName: 'Downloads', searchVal: 254, condition: IgxNumberFilteringOperand.instance().condition('equals') }, - { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals') } + { fieldName: 'Downloads', searchVal: 254, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' }, + { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('equals'), conditionName: 'equals' } ]; gridFilteringExpressionsTree.filteringOperands.push(columnsFilteringTree); grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -6552,7 +6545,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const displayContainer = searchComponent.querySelector('igx-display-container'); const displayContainerRect = displayContainer.getBoundingClientRect(); const parentContainerRect = displayContainer.parentElement.getBoundingClientRect(); - + expect(displayContainerRect.top - parentContainerRect.top <= 1).toBe(true, 'search scrollbar did not reset'); }); }); @@ -7228,8 +7221,8 @@ const verifyExcelStyleFilteringSize = (fix: ComponentFixture, expectedSize: expect(getComponentSize(list)).toBe(expectedSize); // Verify size of all flat and contained buttons in excel stlye dialog. - const flatButtons: HTMLElement[] = excelMenu.querySelectorAll('.igx-button--flat'); - const containedButtons: HTMLElement[] = excelMenu.querySelectorAll('.igx-button--contained'); + const flatButtons: HTMLElement[] = excelMenu.querySelectorAll('.igx-button--flat:not(.igx-excel-filter__secondary *):not(.igx-excel-filter__menu-footer)'); + const containedButtons: HTMLElement[] = excelMenu.querySelectorAll('.igx-button--contained:not(.igx-excel-filter__secondary *):not(.igx-excel-filter__menu-footer)'); const buttons: HTMLElement[] = Array.from(flatButtons).concat(Array.from(containedButtons)); buttons.forEach((button) => { expect(getComponentSize(button)).toBe(expectedSize); @@ -7332,10 +7325,12 @@ const verifySortMoveSize = (fix: ComponentFixture, expectedSize: Size) => { const verifyExcelCustomFilterSize = (fix: ComponentFixture, expectedSize: Size) => { // Excel style filtering custom filter dialog const customFilterMenu = GridFunctions.getExcelStyleCustomFilteringDialog(fix); + // Main container of custom filter dialog + const container = customFilterMenu.querySelector('.igx-excel-filter__secondary-main'); // Verify size of all flat and contained buttons in custom filter dialog. - const flatButtons = customFilterMenu.querySelectorAll('.igx-button--flat'); - const containedButtons = customFilterMenu.querySelectorAll('.igx-button--contained'); + const flatButtons = container.querySelectorAll('.igx-button--flat'); + const containedButtons = container.querySelectorAll('.igx-button--contained'); const buttons = Array.from(flatButtons).concat(Array.from(containedButtons)); buttons.forEach((button) => { expect(getComponentSize(button)).toBe(expectedSize); diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-filtering.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-filtering.spec.ts index 9cea1761943..ea11c13df6a 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-filtering.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-filtering.spec.ts @@ -770,8 +770,8 @@ describe('IgxGrid - Filtering actions #grid', () => { const gridExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); gridExpressionsTree.filteringOperands = [ - { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('greaterThanOrEqualTo') }, - { fieldName: 'ID', searchVal: 4, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') } + { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('greaterThanOrEqualTo'), conditionName: 'greaterThanOrEqualTo' }, + { fieldName: 'ID', searchVal: 4, condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), conditionName: 'greaterThan' } ]; grid.filteringExpressionsTree = gridExpressionsTree; @@ -839,14 +839,14 @@ describe('IgxGrid - Filtering actions #grid', () => { it('Should correctly apply two conditions to two columns at once.', fakeAsync(() => { const colDownloadsExprTree = new FilteringExpressionsTree(FilteringLogic.And, 'Downloads'); colDownloadsExprTree.filteringOperands = [ - { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('greaterThanOrEqualTo') }, - { fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('lessThanOrEqualTo') } + { fieldName: 'Downloads', searchVal: 20, condition: IgxNumberFilteringOperand.instance().condition('greaterThanOrEqualTo'), conditionName: 'greaterThanOrEqualTo' }, + { fieldName: 'Downloads', searchVal: 100, condition: IgxNumberFilteringOperand.instance().condition('lessThanOrEqualTo'), conditionName: 'lessThanOrEqualTo' } ]; const colIdExprTree = new FilteringExpressionsTree(FilteringLogic.And, 'ID'); colIdExprTree.filteringOperands = [ - { fieldName: 'ID', searchVal: 1, condition: IgxNumberFilteringOperand.instance().condition('greaterThan') }, - { fieldName: 'ID', searchVal: 5, condition: IgxNumberFilteringOperand.instance().condition('lessThan') } + { fieldName: 'ID', searchVal: 1, condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), conditionName: 'greaterThan' }, + { fieldName: 'ID', searchVal: 5, condition: IgxNumberFilteringOperand.instance().condition('lessThan'), conditionName: 'lessThan' } ]; const gridExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); @@ -870,12 +870,14 @@ describe('IgxGrid - Filtering actions #grid', () => { const expression = { fieldName: 'Downloads', searchVal: 50, - condition: IgxNumberFilteringOperand.instance().condition('greaterThan') + condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), + conditionName: 'greaterThan' }; const expression1 = { fieldName: 'Downloads', searchVal: 500, - condition: IgxNumberFilteringOperand.instance().condition('lessThan') + condition: IgxNumberFilteringOperand.instance().condition('lessThan'), + conditionName: 'lessThan' }; filteringExpressionsTree.filteringOperands.push(expression); filteringExpressionsTree.filteringOperands.push(expression1); @@ -892,12 +894,14 @@ describe('IgxGrid - Filtering actions #grid', () => { const expression = { fieldName: 'ProductName', searchVal: 'Ignite', - condition: IgxStringFilteringOperand.instance().condition('startsWith') + condition: IgxStringFilteringOperand.instance().condition('startsWith'), + conditionName: 'startsWith' }; const expression1 = { fieldName: 'ProductName', searchVal: 'Angular', - condition: IgxStringFilteringOperand.instance().condition('contains') + condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains' }; filteringExpressionsTree.filteringOperands.push(expression); filteringExpressionsTree.filteringOperands.push(expression1); @@ -916,12 +920,14 @@ describe('IgxGrid - Filtering actions #grid', () => { const expression = { fieldName: 'ReleaseDate', searchVal: null, - condition: IgxDateFilteringOperand.instance().condition('yesterday') + condition: IgxDateFilteringOperand.instance().condition('yesterday'), + conditionName: 'yesterday' }; const expression1 = { fieldName: 'ReleaseDate', searchVal: today, - condition: IgxDateFilteringOperand.instance().condition('after') + condition: IgxDateFilteringOperand.instance().condition('after'), + conditionName: 'after' }; filteringExpressionsTree.filteringOperands.push(expression); filteringExpressionsTree.filteringOperands.push(expression1); @@ -939,7 +945,8 @@ describe('IgxGrid - Filtering actions #grid', () => { const expression = { fieldName: 'ReleaseDate', searchVal: null, - condition: IgxDateFilteringOperand.instance().condition('yesterday') + condition: IgxDateFilteringOperand.instance().condition('yesterday'), + conditionName: 'yesterday' }; filteringExpressionsTree.filteringOperands.push(expression); gridExpressionsTree.filteringOperands.push(filteringExpressionsTree); @@ -974,29 +981,34 @@ describe('IgxGrid - Filtering actions #grid', () => { const expression = { fieldName: 'ProductName', searchVal: 'Ignite', - condition: IgxStringFilteringOperand.instance().condition('startsWith') + condition: IgxStringFilteringOperand.instance().condition('startsWith'), + conditionName: 'startsWith' }; const expression1 = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); const expression11 = { fieldName: 'ProductName', searchVal: 'Angular', - condition: IgxStringFilteringOperand.instance().condition('contains') + condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains' }; const expression12 = { fieldName: 'ProductName', searchVal: 'jQuery', - condition: IgxStringFilteringOperand.instance().condition('contains') + condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains' }; const expression2 = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); const expression21 = { fieldName: 'ProductName', searchVal: 'Angular', - condition: IgxStringFilteringOperand.instance().condition('contains') + condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains' }; const expression22 = { fieldName: 'ProductName', searchVal: 'jQuery', - condition: IgxStringFilteringOperand.instance().condition('contains') + condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains' }; expression1.filteringOperands.push(expression11); expression1.filteringOperands.push(expression12); @@ -1063,7 +1075,8 @@ describe('IgxGrid - Filtering actions #grid', () => { const expression11 = { fieldName: 'ProductName', searchVal: 'Angular', - condition: IgxStringFilteringOperand.instance().condition('contains') + condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains' }; // Verify results after filtering. diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-mrl-keyboard-nav.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-mrl-keyboard-nav.spec.ts index b7bbfe08bfc..5a6605b5334 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-mrl-keyboard-nav.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-mrl-keyboard-nav.spec.ts @@ -12,7 +12,6 @@ import { IgxGridGroupByRowComponent } from './groupby-row.component'; import { GridFunctions, GRID_MRL_BLOCK } from '../../test-utils/grid-functions.spec'; import { CellType } from '../common/grid.interface'; import { IgxColumnLayoutComponent } from '../columns/column-layout.component'; -import { NgFor } from '@angular/common'; import { IGridCellEventArgs, IgxColumnComponent } from '../public_api'; const DEBOUNCETIME = 30; @@ -2623,14 +2622,18 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { @Component({ template: ` - - - + @for (group of colGroups; track group) { + + @for (col of group.columns; track col) { + + } + + } `, - imports: [IgxGridComponent, IgxColumnComponent, IgxColumnLayoutComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxColumnLayoutComponent] }) export class ColumnLayoutTestComponent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) 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 41886530de4..bb08b5b7e06 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 @@ -1,5 +1,4 @@ import { ViewChild, Component, DebugElement, OnInit, QueryList } from '@angular/core'; -import { NgFor, NgIf } from '@angular/common'; import { TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @@ -1413,10 +1412,12 @@ describe('Row Pinning #grid', () => { [height]='"500px"' [data]="data" [autoGenerate]="true"> - + @if (paging) { + + } `, - imports: [IgxGridComponent, IgxPaginatorComponent, NgIf] + imports: [IgxGridComponent, IgxPaginatorComponent] }) export class GridRowPinningComponent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) @@ -1435,14 +1436,18 @@ export class GridRowPinningComponent { template: ` - - - + @for (group of colGroups; track group) { + + @for (col of group.columns; track col) { + + } + + } `, - imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent] }) export class GridRowPinningWithMRLComponent extends GridRowPinningComponent { public cols: Array = [ diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-row-selection.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-row-selection.spec.ts index e2e73766d13..d842c41ab56 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-row-selection.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-row-selection.spec.ts @@ -2091,11 +2091,13 @@ describe('IgxGrid - Row Selection #grid', () => { fieldName: 'UnitsInStock', searchVal: 0, condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), + conditionName: 'greaterThan' }); tree.filteringOperands.push({ fieldName: 'ProductName', searchVal: 'a', condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', ignoreCase: true }); grid.advancedFilteringExpressionsTree = tree; diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-row.component.html b/projects/igniteui-angular/src/lib/grids/grid/grid-row.component.html index f262a09e0cc..7289bc16f29 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-row.component.html +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-row.component.html @@ -6,75 +6,77 @@
- + @if (rowDraggable) {
-
- + } + @if (this.showRowSelectors) {
-
- + } + @if (grid.groupingExpressions.length > 0) {
-
+ } - - - - - - + @if (!grid.hasColumnLayouts) { + @if (pinnedColumns.length > 0 && grid.isPinningToStart) { + @for (col of pinnedColumns | igxNotGrouped; track trackPinnedColumn(col)) { + + } + } - - - - - - + @if (pinnedColumns.length > 0 && !grid.isPinningToStart) { + @for (col of pinnedColumns | igxNotGrouped; track trackPinnedColumn(col)) { + + } + } + } - - + @if (grid.hasColumnLayouts) { + @if (pinnedColumns.length > 0 && grid.isPinningToStart) { - + }
- - - + @for (col of col.children; track trackPinnedColumn(col)) { + + }
- - + @if (pinnedColumns.length > 0 && !grid.isPinningToStart) { - -
+ } + }
-
- + @for (col of pinnedColumns | igxTopLevel; track trackPinnedColumn(col)) { +
+ @for (col of col.children; track col) { - -
+ } +
+ }
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 4a6e9ac9527..77bbeef579c 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 @@ -6,7 +6,7 @@ import { IgxGridCellComponent } from '../cell.component'; import { IgxCheckboxComponent } from '../../checkbox/checkbox.component'; import { IgxGridForOfDirective } from '../../directives/for-of/for_of.directive'; import { IgxRowDragDirective } from '../row-drag.directive'; -import { NgTemplateOutlet, NgIf, NgFor, NgStyle, NgClass } from '@angular/common'; +import { NgTemplateOutlet, NgStyle, NgClass } from '@angular/common'; /* blazorIndirectRender */ /* blazorElement */ @@ -15,7 +15,7 @@ import { NgTemplateOutlet, NgIf, NgFor, NgStyle, NgClass } from '@angular/common selector: 'igx-grid-row', templateUrl: './grid-row.component.html', providers: [{ provide: IgxRowDirective, useExisting: forwardRef(() => IgxGridRowComponent) }], - imports: [NgTemplateOutlet, NgIf, IgxRowDragDirective, NgFor, IgxGridForOfDirective, NgStyle, IgxCheckboxComponent, IgxGridCellComponent, NgClass, IgxGridExpandableCellComponent, IgxGridNotGroupedPipe, IgxGridTopLevelColumns, IgxGridCellStylesPipe, IgxGridCellStyleClassesPipe, IgxGridDataMapperPipe, IgxGridTransactionStatePipe] + imports: [NgTemplateOutlet, IgxRowDragDirective, IgxGridForOfDirective, NgStyle, IgxCheckboxComponent, IgxGridCellComponent, NgClass, IgxGridExpandableCellComponent, IgxGridNotGroupedPipe, IgxGridTopLevelColumns, IgxGridCellStylesPipe, IgxGridCellStyleClassesPipe, IgxGridDataMapperPipe, IgxGridTransactionStatePipe] }) export class IgxGridRowComponent extends IgxRowDirective { diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-toolbar.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-toolbar.spec.ts index fd5e5e62f46..6bb40c445ba 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-toolbar.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-toolbar.spec.ts @@ -7,7 +7,6 @@ import { configureTestSuite } from '../../test-utils/configure-suite'; import { GridFunctions } from "../../test-utils/grid-functions.spec"; import { By } from "@angular/platform-browser"; import { IgxGridToolbarComponent } from '../toolbar/grid-toolbar.component'; -import { NgIf } from '@angular/common'; import { IgxGridToolbarActionsComponent, IgxGridToolbarTitleComponent } from '../toolbar/common'; import { IgxGridToolbarPinningComponent } from '../toolbar/grid-toolbar-pinning.component'; import { IgxGridToolbarHidingComponent } from '../toolbar/grid-toolbar-hiding.component'; @@ -256,14 +255,22 @@ describe('IgxGrid - Grid Toolbar #grid - ', () => { @Component({ template: ` - -

{{ customContent }}

- {{ toolbarTitle }} - -
+ @if (toolbarEnabled) { + + @if (customContentEnabled) { +

{{ customContent }}

+ } + @if (toolbarTitleEnabled) { + {{ toolbarTitle }} + } + @if (toolbarActionsEnabled) { + + } +
+ }
`, - imports: [IgxGridComponent, IgxGridToolbarComponent, IgxGridToolbarActionsComponent, IgxGridToolbarTitleComponent, NgIf] + imports: [IgxGridComponent, IgxGridToolbarComponent, IgxGridToolbarActionsComponent, IgxGridToolbarTitleComponent] }) export class DefaultToolbarComponent { public toolbarEnabled = true; 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 374267ba41a..900ac1c9572 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.component.html +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.component.html @@ -2,7 +2,7 @@ - +@if (showGroupArea && (groupingExpressions.length > 0 || hasGroupableColumns)) { - +} - - - - - - -
- - - - -
+ @if (moving && columnInDrag && pinnedColumns.length <= 0) { + + } + @if (moving && columnInDrag && pinnedColumns.length > 0) { + + } + -
+ + @if (data + | gridTransaction:id:pipeTrigger + | visibleColumns:hasVisibleColumns + | gridAddRow:true:pipeTrigger + | gridRowPinning:id:true:pipeTrigger + | gridFiltering:filteringExpressionsTree:filterStrategy:advancedFilteringExpressionsTree:id:pipeTrigger:filteringPipeTrigger:true + | gridSort:sortingExpressions:groupingExpressions:sortStrategy:id:pipeTrigger:true; as pinnedData) { + @if (pinnedData.length > 0) { +
+ @for (rowData of pinnedData; track rowData; let rowIndex = $index) { + + + } +
+ } + } +
- -
-
- + @if (this.groupingExpressions.length > 0) { +
+ } +
@@ -134,11 +140,15 @@
- - + @if (shouldOverlayLoading) { + + + }
- + @if (moving && columnInDrag) { + + }
@@ -158,11 +168,13 @@
- - + @if (hasSummarizedColumns && rootSummariesEnabled) { + + + }
@@ -185,18 +197,22 @@ {{emptyFilteredGridMessage}} - - - + @if (showAddButton) { + + + + } {{emptyGridMessage}} - - - + @if (showAddButton) { + + + + } @@ -226,7 +242,7 @@ - + -
-
- - +@if (rowEditable) { +
+
+ + +
-
+} {{ this.resourceStrings.igx_grid_row_edit_text | igxStringReplace:'{0}':rowChangesCount.toString() | igxStringReplace:'{1}':hiddenColumnsCount.toString() }} @@ -277,7 +295,9 @@ - +@if (colResizingService.showResizer) { + +}
@if (platform.isElements) {
diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.component.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.component.spec.ts index 77856d7b7e1..51ac5b0b53f 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.component.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.component.spec.ts @@ -23,7 +23,7 @@ import { IgxTabContentComponent, IgxTabHeaderComponent, IgxTabItemComponent, Igx import { IgxGridRowComponent } from './grid-row.component'; import { ISortingExpression, SortingDirection } from '../../data-operations/sorting-strategy'; import { GRID_SCROLL_CLASS } from '../../test-utils/grid-functions.spec'; -import { AsyncPipe, NgFor, NgIf } from '@angular/common'; +import { AsyncPipe } from '@angular/common'; import { IgxPaginatorComponent, IgxPaginatorContentDirective } from '../../paginator/paginator.component'; import { IGridRowEventArgs, IgxColumnGroupComponent, IgxGridFooterComponent, IgxGridRow, IgxGroupByRow, IgxSummaryRow } from '../public_api'; import { getComponentSize } from '../../core/utils'; @@ -131,10 +131,10 @@ describe('IgxGrid Component Tests #grid', () => { expect(grid.columns.map(col => col.field)).toEqual(['Number', 'Boolean'], 'Invalid columns after exclusion initialized'); }); - it('should initialize a grid and allow changing columns runtime with ngFor', () => { + it('should initialize a grid and allow changing columns runtime with @for', () => { const fix = TestBed.createComponent(IgxGridTestComponent); fix.detectChanges(); - // reverse order of ngFor bound collection + // reverse order of @for bound collection fix.componentInstance.columns.reverse(); fix.detectChanges(); // check order @@ -562,6 +562,7 @@ describe('IgxGrid Component Tests #grid', () => { grid.filteringExpressionsTree.filteringOperands = [ { condition: IgxNumberFilteringOperand.instance().condition('equals'), + conditionName: 'equals', fieldName: 'index', searchVal: 0 } @@ -2692,7 +2693,7 @@ describe('IgxGrid Component Tests #grid', () => { }); // TODO: Enable performance tests again - xdescribe('IgxGrid - Performance tests #perf', () => { + describe('IgxGrid - Performance tests #perf', () => { const MAX_RAW_RENDER = 1967; // two average diffs from 7.3 rendering performance const MAX_GROUPED_RENDER = 1500; const MAX_VER_SCROLL_O = 220; @@ -2927,12 +2928,14 @@ describe('IgxGrid Component Tests #grid', () => { @Component({ template: `
- - + @for (column of columns; track column) { + + + }
`, - imports: [IgxGridComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent] }) export class IgxGridTestComponent { @ViewChild('grid', { static: true }) public grid: IgxGridComponent; @@ -3001,11 +3004,15 @@ export class IgxGridTestComponent { @Component({ template: ` - - - + @for (col of columns; track col) { + + + } + @if (paging) { + + } `, - imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent, NgFor, NgIf] + imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class IgxGridDefaultRenderingComponent { @ViewChild('grid', { read: IgxGridComponent, static: true }) @@ -3125,10 +3132,12 @@ export class IgxGridColumnHeaderInGroupAutoSizeComponent { @Component({ template: ` - - + @for (col of columns; track col) { + + + } `, - imports: [IgxGridComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent] }) export class IgxGridColumnPercentageWidthComponent extends IgxGridDefaultRenderingComponent { public override initColumns(column) { @@ -3140,10 +3149,12 @@ export class IgxGridColumnPercentageWidthComponent extends IgxGridDefaultRenderi @Component({ template: ` - - + @for (col of columns; track col) { + + + } `, - imports: [IgxGridComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent] }) export class IgxGridColumnHiddenPercentageWidthComponent extends IgxGridDefaultRenderingComponent { public hidden = true; @@ -3169,10 +3180,12 @@ export class IgxGridWithCustomFooterComponent extends IgxGridTestComponent { @Component({ template: `
- + @if (paging) { + + }
`, - imports: [IgxGridComponent, IgxPaginatorComponent, NgIf] + imports: [IgxGridComponent, IgxPaginatorComponent] }) export class IgxGridWrappedInContComponent extends IgxGridTestComponent { public override data = []; @@ -3222,10 +3235,12 @@ export class IgxGridWrappedInContComponent extends IgxGridTestComponent { @Component({ template: `
- + @if (paging) { + + }
`, - imports: [IgxGridComponent, IgxPaginatorComponent, NgIf] + imports: [IgxGridComponent, IgxPaginatorComponent] }) export class IgxGridFixedContainerHeightComponent extends IgxGridWrappedInContComponent { public override paging = false; @@ -3415,12 +3430,13 @@ export class IgxGridFormattingComponent extends BasicGridComponent { - - + @for (column of columns; track column) { + + + } @@ -3430,13 +3446,14 @@ export class IgxGridFormattingComponent extends BasicGridComponent { - - + @for (column of columns; track column) { + + + } @@ -3446,13 +3463,14 @@ export class IgxGridFormattingComponent extends BasicGridComponent { - - + @for (column of columns; track column) { + + + } @@ -3463,13 +3481,14 @@ export class IgxGridFormattingComponent extends BasicGridComponent { - - - + @for (column of columns; track column) { + + + } + @@ -3480,12 +3499,13 @@ export class IgxGridFormattingComponent extends BasicGridComponent {
- - + @for (column of columns; track column) { + + + }
@@ -3493,7 +3513,7 @@ export class IgxGridFormattingComponent extends BasicGridComponent {
`, - imports: [IgxGridComponent, IgxColumnComponent, IgxTabsComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxTabItemComponent, IgxPaginatorComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxTabsComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxTabItemComponent, IgxPaginatorComponent] }) export class IgxGridInsideIgxTabsComponent { @ViewChild('grid2', { read: IgxGridComponent, static: true }) @@ -3538,12 +3558,14 @@ export class IgxGridInsideIgxTabsComponent { -

{{grid.totalRecords}}

+ @if (grid.rendered$ | async) { +

{{grid.totalRecords}}

+ }
`, - imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent, IgxPaginatorContentDirective, NgIf, AsyncPipe] + imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent, IgxPaginatorContentDirective, AsyncPipe] }) export class IgxGridWithCustomPaginationTemplateComponent { @ViewChild('grid', { read: IgxGridComponent, static: true }) @@ -3554,9 +3576,11 @@ export class IgxGridWithCustomPaginationTemplateComponent { @Component({ template: ` - + @for (column of columns; track column) { + + } `, - imports: [IgxGridComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent] }) export class IgxGridPerformanceComponent implements AfterViewInit, OnInit { diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts index 8c735725867..07d3b4cdb9b 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.component.ts @@ -3,7 +3,7 @@ import { QueryList, ViewChild, TemplateRef, DoCheck, AfterContentInit, HostBinding, OnInit, AfterViewInit, ContentChildren, CUSTOM_ELEMENTS_SCHEMA, booleanAttribute } from '@angular/core'; -import { NgIf, NgTemplateOutlet, NgClass, NgFor, NgStyle } from '@angular/common'; +import { NgTemplateOutlet, NgClass, NgStyle } from '@angular/common'; import { IgxGridBaseDirective } from '../grid-base.directive'; import { IgxGridNavigationService } from '../grid-navigation.service'; @@ -116,9 +116,7 @@ export interface IGroupingDoneEventArgs extends IBaseEventArgs { selector: 'igx-grid', templateUrl: './grid.component.html', imports: [ - NgIf, NgClass, - NgFor, NgStyle, NgTemplateOutlet, IgxGridGroupByAreaComponent, diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.groupby.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.groupby.spec.ts index def18ce2722..4eb5a737125 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.groupby.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.groupby.spec.ts @@ -20,7 +20,6 @@ import { GridSelectionMode } from '../common/enums'; import { ControlsFunction } from '../../test-utils/controls-functions.spec'; import { IGroupingExpression } from '../../data-operations/grouping-expression.interface'; import { IgxPaginatorComponent } from '../../paginator/paginator.component'; -import { NgFor, NgIf } from '@angular/common'; import { IgxCheckboxComponent } from '../../checkbox/checkbox.component'; import { IgxGroupByRowSelectorDirective } from '../selection/row-selectors'; import { IgxGridStateDirective, IgxGrouping } from '../public_api'; @@ -2377,7 +2376,7 @@ describe('IgxGrid - GroupBy #grid', () => { expect(dataRows.length).toEqual(6); })); - + it('should update the UI when updating records via the UI after grouping is re-applied so that they more to the correct group', async () => { const fix = TestBed.createComponent(DefaultGridComponent); const grid = fix.componentInstance.instance; @@ -3970,13 +3969,15 @@ describe('IgxGrid - GroupBy #grid', () => { [dropAreaTemplate]='currentDropArea' [data]="data" [autoGenerate]="true" (columnInit)="columnsCreated($event)" (groupingDone)="groupingDoneHandler($event)"> - + @if (paging) { + + } Custom template `, - imports: [IgxGridComponent, IgxPaginatorComponent, NgIf] + imports: [IgxGridComponent, IgxPaginatorComponent] }) export class DefaultGridComponent extends DataParent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) @@ -4122,11 +4123,13 @@ export class CustomTemplateGridComponent extends DataParent { [width]='width' [height]='height' [data]="testData"> - + @for (c of columns; track c) { + + } `, - imports: [IgxGridComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnComponent] }) export class GroupByDataMoreColumnsComponent extends DataParent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.master-detail.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.master-detail.spec.ts index 5c6e6cf5a96..971bfea8388 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.master-detail.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.master-detail.spec.ts @@ -16,7 +16,6 @@ import { IgxCheckboxComponent } from '../../checkbox/checkbox.component'; import { clearGridSubs, setupGridScrollDetection } from '../../test-utils/helper-utils.spec'; import { SortingDirection } from '../../data-operations/sorting-strategy'; import { IgxPaginatorComponent } from '../../paginator/paginator.component'; -import { NgFor, NgIf } from '@angular/common'; import { IgxColumnLayoutComponent } from '../columns/column-layout.component'; import { CellType, IgxColumnComponent, IgxGridDetailTemplateDirective } from '../public_api'; @@ -1258,14 +1257,18 @@ describe('IgxGrid Master Detail #grid', () => { @Component({ template: ` - - - + @for (c of columns; track c) { + + + } + @if (paging) { + + }
- + Available
{{dataItem.Address}}
@@ -1281,7 +1284,7 @@ describe('IgxGrid Master Detail #grid', () => {
`, - imports: [IgxGridComponent, IgxColumnComponent, IgxGridDetailTemplateDirective, IgxCheckboxComponent, IgxPaginatorComponent, IgxInputGroupComponent, IgxInputDirective, NgIf, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxGridDetailTemplateDirective, IgxCheckboxComponent, IgxPaginatorComponent, IgxInputGroupComponent, IgxInputDirective] }) export class DefaultGridMasterDetailComponent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) @@ -1306,9 +1309,13 @@ export class DefaultGridMasterDetailComponent { template: ` - - - + @for (c of columns; track c) { + + + } + @if (paging) { + + }
@@ -1322,7 +1329,7 @@ export class DefaultGridMasterDetailComponent { `, - imports: [IgxGridComponent, IgxColumnComponent, IgxCheckboxComponent, IgxGridDetailTemplateDirective, IgxPaginatorComponent, NgIf, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxCheckboxComponent, IgxGridDetailTemplateDirective, IgxPaginatorComponent] }) export class AllExpandedGridMasterDetailComponent extends DefaultGridMasterDetailComponent implements OnInit { public expStates = new Map(); @@ -1351,7 +1358,9 @@ export class AllExpandedGridMasterDetailComponent extends DefaultGridMasterDetai - + @if (paging) { + + }
@@ -1364,7 +1373,7 @@ export class AllExpandedGridMasterDetailComponent extends DefaultGridMasterDetai `, - imports: [IgxGridComponent, IgxColumnComponent, IgxGridDetailTemplateDirective, IgxColumnLayoutComponent, IgxCheckboxComponent, IgxPaginatorComponent, NgIf, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxGridDetailTemplateDirective, IgxColumnLayoutComponent, IgxCheckboxComponent, IgxPaginatorComponent] }) export class MRLMasterDetailComponent extends DefaultGridMasterDetailComponent { } diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.multi-row-layout.integration.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.multi-row-layout.integration.spec.ts index 6f8be74655a..ee4f9232287 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.multi-row-layout.integration.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.multi-row-layout.integration.spec.ts @@ -15,7 +15,6 @@ import { IgxGridToolbarComponent } from '../toolbar/grid-toolbar.component'; import { IgxGridToolbarActionsComponent } from '../toolbar/common'; import { IgxGridToolbarHidingComponent } from '../toolbar/grid-toolbar-hiding.component'; import { IgxGridToolbarPinningComponent } from '../toolbar/grid-toolbar-pinning.component'; -import { NgFor, NgIf } from '@angular/common'; type FixtureType = ColumnLayoutGroupingTestComponent | ColumnLayouHidingTestComponent | ColumnLayoutResizingTestComponent @@ -904,7 +903,7 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { it('should create only one ghost element when dragging a column', async () => { const headers: DebugElement[] = fixture.debugElement.queryAll(By.css(COLUMN_HEADER_CLASS)); - + const header = headers[1].nativeElement; UIInteractions.simulatePointerEvent('pointerdown', header, 50, 50); await wait(); @@ -1226,19 +1225,25 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { @Component({ template: ` - - - - - - - - + @if (showToolbar) { + + + + + + } + @for (group of colGroups; track group) { + + @for (col of group.columns; track col) { + + } + + } `, - imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, IgxGridToolbarComponent, IgxGridToolbarHidingComponent, IgxGridToolbarActionsComponent, NgIf, NgFor] + imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, IgxGridToolbarComponent, IgxGridToolbarHidingComponent, IgxGridToolbarActionsComponent] }) export class ColumnLayouHidingTestComponent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) @@ -1274,19 +1279,25 @@ export class ColumnLayouHidingTestComponent { @Component({ template: ` - - - - - - - - + @if (showToolbar) { + + + + + + } + @for (group of colGroups; track group.group) { + + @for (col of group.columns; track col.field) { + + } + + } `, - imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, IgxGridToolbarComponent, IgxGridToolbarPinningComponent, IgxGridToolbarActionsComponent, NgFor, NgIf] + imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, IgxGridToolbarComponent, IgxGridToolbarPinningComponent, IgxGridToolbarActionsComponent] }) export class ColumnLayoutPinningTestComponent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) @@ -1322,14 +1333,18 @@ export class ColumnLayoutPinningTestComponent { @Component({ template: ` - - - + @for (group of colGroups; track group) { + + @for (col of group.columns; track col) { + + } + + } `, - imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent] }) export class ColumnLayoutFilteringTestComponent extends ColumnLayoutPinningTestComponent { } @@ -1337,14 +1352,18 @@ export class ColumnLayoutFilteringTestComponent extends ColumnLayoutPinningTestC @Component({ template: ` - - - + @for (group of colGroups; track group) { + + @for (col of group.columns; track col) { + + } + + } `, - imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent] }) export class ColumnLayoutGroupingTestComponent extends ColumnLayoutPinningTestComponent { public override showToolbar = false; @@ -1377,14 +1396,18 @@ export class ColumnLayoutGroupingTestComponent extends ColumnLayoutPinningTestCo @Component({ template: ` - - - - + @for (group of colGroups; track group.group) { + + @for (col of group.columns; track col) { + + + } + + } `, - imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent] }) export class ColumnLayoutResizingTestComponent { diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.multi-row-layout.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid.multi-row-layout.spec.ts index b252f3a6e3f..2b5ffd40f0b 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid.multi-row-layout.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid.multi-row-layout.spec.ts @@ -1,4 +1,4 @@ -import { TestBed, fakeAsync } from '@angular/core/testing'; +import { TestBed, fakeAsync, tick } from '@angular/core/testing'; import { IgxGridComponent } from './grid.component'; import { Component, ViewChild } from '@angular/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @@ -10,7 +10,6 @@ import { DefaultSortingStrategy, SortingDirection } from '../../data-operations/ import { configureTestSuite } from '../../test-utils/configure-suite'; import { ICellPosition } from '../common/events'; import { GridFunctions, GRID_MRL_BLOCK } from '../../test-utils/grid-functions.spec'; -import { NgFor } from '@angular/common'; import { IgxColumnGroupComponent } from '../columns/column-group.component'; import { IgxColumnComponent } from '../columns/column.component'; @@ -98,7 +97,7 @@ describe('IgxGrid - multi-row-layout #grid', () => { // verify block style let sizes = grid.columnList.first.getGridTemplate(false).split(' ').map(width => parseFloat(width).toFixed(2) + "px").join(' '); - + expect(sizes).toBe('200.33px 200.33px 200.33px'); expect(grid.columnList.first.getGridTemplate(true)).toBe('repeat(3,1fr)'); @@ -649,7 +648,7 @@ describe('IgxGrid - multi-row-layout #grid', () => { GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups); fixture.componentInstance.colGroups = [{ - group: 'group1', + group: 'group3', columns: [ { field: 'ID', rowStart: 1, colStart: 1 }, { field: 'CompanyName', rowStart: 1, colStart: 2 }, @@ -845,10 +844,13 @@ describe('IgxGrid - multi-row-layout #grid', () => { ] } ]; - fixture.componentInstance.colGroups = []; + let colGroups = []; for (let i = 0; i < 3; i++) { - fixture.componentInstance.colGroups = fixture.componentInstance.colGroups.concat(uniqueGroups); + const groups = structuredClone(uniqueGroups) + .map(({ group, columns }) => ({ group: group + i, columns })); + colGroups = colGroups.concat(groups); } + fixture.componentInstance.colGroups = colGroups; grid.columnWidth = '200px'; fixture.componentInstance.grid.width = '600px'; fixture.detectChanges(); @@ -894,8 +896,6 @@ describe('IgxGrid - multi-row-layout #grid', () => { it('should apply horizontal virtualization correctly for widths in px, % and no-width columns.', fakeAsync(() => { const fixture = TestBed.createComponent(ColumnLayoutTestComponent); - fixture.detectChanges(); - const grid = fixture.componentInstance.grid; // test with px fixture.componentInstance.colGroups = [{ group: 'group1', @@ -909,6 +909,8 @@ describe('IgxGrid - multi-row-layout #grid', () => { }]; fixture.componentInstance.grid.width = '617px'; fixture.detectChanges(); + tick(); // Required to render scrollbars + const grid = fixture.componentInstance.grid; const horizontalVirtualization = grid.rowList.first.virtDirRow; expect(grid.hasHorizontalScroll()).toBeTruthy(); @@ -1142,14 +1144,18 @@ describe('IgxGrid - multi-row-layout #grid', () => { @Component({ template: ` - - - + @for (group of colGroups; track group.group) { + + @for (col of group.columns; track col.field) { + + } + + } `, - imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, NgFor] + imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent] }) export class ColumnLayoutTestComponent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) @@ -1173,20 +1179,24 @@ export class ColumnLayoutTestComponent { template: ` - + - - - + @for (group of colGroups; track group) { + + @for (col of group.columns; track col) { + + } + + } `, - imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, IgxColumnGroupComponent, NgFor] + imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, IgxColumnGroupComponent] }) export class ColumnLayoutAndGroupsTestComponent extends ColumnLayoutTestComponent { diff --git a/projects/igniteui-angular/src/lib/grids/grid/groupby-row.component.html b/projects/igniteui-angular/src/lib/grids/grid/groupby-row.component.html index cefa0b2d3fd..7362a297960 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/groupby-row.component.html +++ b/projects/igniteui-angular/src/lib/grids/grid/groupby-row.component.html @@ -1,12 +1,12 @@ - + @if (rowDraggable) {
-
+ } - + @if (showRowSelectors) {
-
+ }
diff --git a/projects/igniteui-angular/src/lib/grids/grid/groupby-row.component.ts b/projects/igniteui-angular/src/lib/grids/grid/groupby-row.component.ts index f7736407720..4928dda109a 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/groupby-row.component.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/groupby-row.component.ts @@ -11,7 +11,7 @@ import { OnDestroy, Inject } from '@angular/core'; -import { NgIf, NgTemplateOutlet, DecimalPipe, DatePipe, getLocaleCurrencyCode, PercentPipe, CurrencyPipe } from '@angular/common'; +import { NgTemplateOutlet, DecimalPipe, DatePipe, getLocaleCurrencyCode, PercentPipe, CurrencyPipe } from '@angular/common'; import { takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; @@ -34,7 +34,6 @@ import { IgxColumnFormatterPipe } from '../common/pipes'; selector: 'igx-grid-groupby-row', templateUrl: './groupby-row.component.html', imports: [ - NgIf, NgTemplateOutlet, DecimalPipe, DatePipe, diff --git a/projects/igniteui-angular/src/lib/grids/grouping/grid-group-by-area.component.ts b/projects/igniteui-angular/src/lib/grids/grouping/grid-group-by-area.component.ts index 90fcf051064..4e7b8bf3b1d 100644 --- a/projects/igniteui-angular/src/lib/grids/grouping/grid-group-by-area.component.ts +++ b/projects/igniteui-angular/src/lib/grids/grouping/grid-group-by-area.component.ts @@ -14,7 +14,7 @@ import { IgxGroupAreaDropDirective } from '../grid.directives'; import { IgxSuffixDirective } from '../../directives/suffix/suffix.directive'; import { IgxIconComponent } from '../../icon/icon.component'; import { IgxChipComponent } from '../../chips/chip.component'; -import { NgFor, NgTemplateOutlet } from '@angular/common'; +import { NgTemplateOutlet } from '@angular/common'; import { IgxChipsAreaComponent } from '../../chips/chips-area.component'; /** @@ -26,7 +26,7 @@ import { IgxChipsAreaComponent } from '../../chips/chips-area.component'; selector: 'igx-grid-group-by-area', templateUrl: 'group-by-area.component.html', providers: [{ provide: IgxGroupByAreaDirective, useExisting: IgxGridGroupByAreaComponent }], - imports: [IgxChipsAreaComponent, NgFor, IgxChipComponent, IgxIconComponent, IgxSuffixDirective, IgxGroupAreaDropDirective, IgxDropDirective, NgTemplateOutlet, IgxGroupByMetaPipe] + imports: [IgxChipsAreaComponent, IgxChipComponent, IgxIconComponent, IgxSuffixDirective, IgxGroupAreaDropDirective, IgxDropDirective, NgTemplateOutlet, IgxGroupByMetaPipe] }) export class IgxGridGroupByAreaComponent extends IgxGroupByAreaDirective { @Input() diff --git a/projects/igniteui-angular/src/lib/grids/grouping/group-by-area.component.html b/projects/igniteui-angular/src/lib/grids/grouping/group-by-area.component.html index b44cc270a5d..b9f9dcc62b1 100644 --- a/projects/igniteui-angular/src/lib/grids/grouping/group-by-area.component.html +++ b/projects/igniteui-angular/src/lib/grids/grouping/group-by-area.component.html @@ -1,5 +1,5 @@ - + @for (expression of chipExpressions; track expression.fieldName; let last = $last) { - + }
- +@if (grid.hasColumnLayouts && column.columnGroup) { + @if (grid.moving) { + + }
- - - - + @for (child of column.children; track child) { + @if (!child.hidden) { + + + } + }
- - + @if (grid.moving) { + + } +} @@ -30,8 +36,10 @@ - - +@if (!grid.hasColumnLayouts && column.columnGroup) { + @if (grid.moving) { + + }
- + @if (column.collapsible) {
-
+ }
-
- - - - -
- -
+ @if (grid.type !== 'pivot') { +
+ @for (child of column.children; track child) { + @if (!child.hidden) { + + + } + } +
+ } + @if (grid.moving) { + + } +} - - +@if (!column.columnGroup) { + @if (grid.moving) { + + } - - - - - + @if (grid.allowFiltering && grid.filterMode === 'quickFilter') { + + } + @if (!column.columnGroup && column.resizable) { + + + } + @if (grid.moving) { + + } +} diff --git a/projects/igniteui-angular/src/lib/grids/headers/grid-header-group.component.ts b/projects/igniteui-angular/src/lib/grids/headers/grid-header-group.component.ts index aa1c1352e81..6607a21ff74 100644 --- a/projects/igniteui-angular/src/lib/grids/headers/grid-header-group.component.ts +++ b/projects/igniteui-angular/src/lib/grids/headers/grid-header-group.component.ts @@ -25,7 +25,7 @@ import { IgxResizeHandleDirective } from '../resizing/resize-handle.directive'; import { IgxIconComponent } from '../../icon/icon.component'; import { IgxColumnMovingDropDirective } from '../moving/moving.drop.directive'; import { IgxColumnMovingDragDirective } from '../moving/moving.drag.directive'; -import { NgIf, NgClass, NgStyle, NgFor, NgTemplateOutlet } from '@angular/common'; +import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common'; const Z_INDEX = 9999; @@ -36,7 +36,7 @@ const Z_INDEX = 9999; changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-grid-header-group', templateUrl: './grid-header-group.component.html', - imports: [NgIf, NgClass, NgStyle, NgFor, IgxColumnMovingDragDirective, IgxColumnMovingDropDirective, IgxIconComponent, NgTemplateOutlet, IgxGridHeaderComponent, IgxGridFilteringCellComponent, IgxResizeHandleDirective, IgxHeaderGroupWidthPipe, IgxHeaderGroupStylePipe] + imports: [NgClass, NgStyle, IgxColumnMovingDragDirective, IgxColumnMovingDropDirective, IgxIconComponent, NgTemplateOutlet, IgxGridHeaderComponent, IgxGridFilteringCellComponent, IgxResizeHandleDirective, IgxHeaderGroupWidthPipe, IgxHeaderGroupStylePipe] }) export class IgxGridHeaderGroupComponent implements DoCheck { @@ -261,7 +261,7 @@ export class IgxGridHeaderGroupComponent implements DoCheck { */ @HostListener('mousedown', ['$event']) public onMouseDown(event: MouseEvent): void { - if (!this.grid.allowFiltering || + if (!this.grid.allowFiltering || (event.composedPath().findIndex(el => (el as Element).tagName?.toLowerCase() === 'igx-grid-filtering-cell') < 1)) { // Hack for preventing text selection in IE and Edge while dragging the resize element diff --git a/projects/igniteui-angular/src/lib/grids/headers/grid-header-row.component.html b/projects/igniteui-angular/src/lib/grids/headers/grid-header-row.component.html index 938accf4fe9..fcbb9358d16 100644 --- a/projects/igniteui-angular/src/lib/grids/headers/grid-header-row.component.html +++ b/projects/igniteui-angular/src/lib/grids/headers/grid-header-row.component.html @@ -5,26 +5,26 @@
- + @if (grid.moving && grid.columnInDrag && pinnedColumnCollection.length <= 0) { - - + } + @if (grid.moving && grid.columnInDrag && pinnedColumnCollection.length > 0) { - + } - + @if (grid.rowDraggable) {
-
+ } - + @if (grid.showRowSelectors) {
-
+ } - + @if (isHierarchicalGrid) {
-
+ } - + @if (grid?.groupingExpressions?.length) {
-
+ } - - + @if (pinnedColumnCollection.length && grid.isPinningToStart) { + @for (column of pinnedColumnCollection | igxTopLevel; track trackPinnedColumn(column)) { - - + } + } - - + @if (pinnedColumnCollection.length && !grid.isPinningToStart) { + @for (column of pinnedColumnCollection | igxTopLevel; track trackPinnedColumn(column)) { - - + } + }
- + @if (grid.filteringService.isFilterRowVisible) { - + } - + @if (grid.moving && grid.columnInDrag) { - + }
diff --git a/projects/igniteui-angular/src/lib/grids/headers/grid-header-row.component.ts b/projects/igniteui-angular/src/lib/grids/headers/grid-header-row.component.ts index 80067809dc9..4e664f1f249 100644 --- a/projects/igniteui-angular/src/lib/grids/headers/grid-header-row.component.ts +++ b/projects/igniteui-angular/src/lib/grids/headers/grid-header-row.component.ts @@ -11,7 +11,7 @@ import { ViewChildren, booleanAttribute } from '@angular/core'; -import { flatten } from '../../core/utils'; +import { flatten, trackByIdentity } from '../../core/utils'; import { IgxGridForOfDirective } from '../../directives/for-of/for_of.directive'; import { ColumnType, GridType, IgxHeadSelectorTemplateContext } from '../common/grid.interface'; import { IgxGridFilteringCellComponent } from '../filtering/base/grid-filtering-cell.component'; @@ -22,7 +22,7 @@ import { IgxHeaderGroupWidthPipe, IgxHeaderGroupStylePipe } from './pipes'; import { IgxGridTopLevelColumns } from '../common/pipes'; import { IgxCheckboxComponent } from '../../checkbox/checkbox.component'; import { IgxColumnMovingDropDirective } from '../moving/moving.drop.directive'; -import { NgIf, NgTemplateOutlet, NgClass, NgFor, NgStyle } from '@angular/common'; +import { NgTemplateOutlet, NgClass, NgStyle } from '@angular/common'; /** * @@ -36,7 +36,7 @@ import { NgIf, NgTemplateOutlet, NgClass, NgFor, NgStyle } from '@angular/common changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-grid-header-row', templateUrl: './grid-header-row.component.html', - imports: [NgIf, IgxColumnMovingDropDirective, NgTemplateOutlet, NgClass, NgFor, IgxGridHeaderGroupComponent, NgStyle, IgxGridForOfDirective, IgxGridFilteringRowComponent, IgxCheckboxComponent, IgxGridTopLevelColumns, IgxHeaderGroupWidthPipe, IgxHeaderGroupStylePipe] + imports: [IgxColumnMovingDropDirective, NgTemplateOutlet, NgClass, IgxGridHeaderGroupComponent, NgStyle, IgxGridForOfDirective, IgxGridFilteringRowComponent, IgxCheckboxComponent, IgxGridTopLevelColumns, IgxHeaderGroupWidthPipe, IgxHeaderGroupStylePipe] }) export class IgxGridHeaderRowComponent implements DoCheck { @@ -198,4 +198,7 @@ export class IgxGridHeaderRowComponent implements DoCheck { this.grid.selectionService.selectAllRows(event); } } + + /** state persistence switching all pinned columns resets collection */ + protected trackPinnedColumn = trackByIdentity; } diff --git a/projects/igniteui-angular/src/lib/grids/headers/grid-header.component.html b/projects/igniteui-angular/src/lib/grids/headers/grid-header.component.html index 1864eb10869..d142eeae4b5 100644 --- a/projects/igniteui-angular/src/lib/grids/headers/grid-header.component.html +++ b/projects/igniteui-angular/src/lib/grids/headers/grid-header.component.html @@ -18,19 +18,19 @@ *ngTemplateOutlet="column.headerTemplate ? column.headerTemplate : defaultColumn; context: { $implicit: column, column: column}">
- +@if (!column.columnGroup) {
- + @if (column.sortable && !disabled) {
-
- + } + @if (grid.allowFiltering && column.filterable && grid.filterMode === 'excelStyleFilter') {
-
+ }
-
+} diff --git a/projects/igniteui-angular/src/lib/grids/headers/grid-header.component.ts b/projects/igniteui-angular/src/lib/grids/headers/grid-header.component.ts index b4c719b4a01..c691ba3c8d3 100644 --- a/projects/igniteui-angular/src/lib/grids/headers/grid-header.component.ts +++ b/projects/igniteui-angular/src/lib/grids/headers/grid-header.component.ts @@ -19,7 +19,7 @@ import { ColumnType, GridType, IGX_GRID_BASE } from '../common/grid.interface'; import { GridSelectionMode } from '../common/enums'; import { SortingDirection } from '../../data-operations/sorting-strategy'; import { SortingIndexPipe } from './pipes'; -import { NgTemplateOutlet, NgIf, NgClass } from '@angular/common'; +import { NgTemplateOutlet, NgClass } from '@angular/common'; import { IgxIconComponent } from '../../icon/icon.component'; import { ExpressionsTreeUtil } from '../../data-operations/expressions-tree-util'; @@ -30,7 +30,7 @@ import { ExpressionsTreeUtil } from '../../data-operations/expressions-tree-util changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-grid-header', templateUrl: 'grid-header.component.html', - imports: [IgxIconComponent, NgTemplateOutlet, NgIf, NgClass, SortingIndexPipe] + imports: [IgxIconComponent, NgTemplateOutlet, NgClass, SortingIndexPipe] }) export class IgxGridHeaderComponent implements DoCheck, OnDestroy { diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-cell.component.ts b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-cell.component.ts index 6ec8fa6978e..1ce7118cd4a 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-cell.component.ts +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-cell.component.ts @@ -22,14 +22,14 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { IgxIconComponent } from '../../icon/icon.component'; import { IgxTextHighlightDirective } from '../../directives/text-highlight/text-highlight.directive'; import { IgxChipComponent } from '../../chips/chip.component'; -import { NgIf, NgClass, NgTemplateOutlet, DecimalPipe, PercentPipe, CurrencyPipe, DatePipe } from '@angular/common'; +import { NgClass, NgTemplateOutlet, DecimalPipe, PercentPipe, CurrencyPipe, DatePipe } from '@angular/common'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-hierarchical-grid-cell', templateUrl: '../cell.component.html', providers: [HammerGesturesManager], - imports: [NgIf, IgxChipComponent, IgxTextHighlightDirective, IgxIconComponent, NgClass, FormsModule, ReactiveFormsModule, IgxInputGroupComponent, IgxInputDirective, IgxFocusDirective, IgxTextSelectionDirective, IgxCheckboxComponent, IgxDatePickerComponent, IgxTimePickerComponent, IgxDateTimeEditorDirective, IgxPrefixDirective, IgxSuffixDirective, NgTemplateOutlet, IgxTooltipTargetDirective, IgxTooltipDirective, IgxGridCellImageAltPipe, IgxStringReplacePipe, IgxColumnFormatterPipe, DecimalPipe, PercentPipe, CurrencyPipe, DatePipe] + imports: [IgxChipComponent, IgxTextHighlightDirective, IgxIconComponent, NgClass, FormsModule, ReactiveFormsModule, IgxInputGroupComponent, IgxInputDirective, IgxFocusDirective, IgxTextSelectionDirective, IgxCheckboxComponent, IgxDatePickerComponent, IgxTimePickerComponent, IgxDateTimeEditorDirective, IgxPrefixDirective, IgxSuffixDirective, NgTemplateOutlet, IgxTooltipTargetDirective, IgxTooltipDirective, IgxGridCellImageAltPipe, IgxStringReplacePipe, IgxColumnFormatterPipe, DecimalPipe, PercentPipe, CurrencyPipe, DatePipe] }) export class IgxHierarchicalGridCellComponent extends IgxGridCellComponent implements OnInit { // protected hSelection; 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 604d707b2e3..962169bcf4d 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 @@ -18,32 +18,39 @@
- - + @if (moving && columnInDrag && pinnedColumns.length <= 0) { + + } + @if (moving && columnInDrag && pinnedColumns.length > 0) { + + } - -
- - - - -
-
+ @if (data + | gridTransaction:id:pipeTrigger + | visibleColumns:hasVisibleColumns + | gridAddRow:true:pipeTrigger + | gridRowPinning:id:true:pipeTrigger + | gridFiltering:filteringExpressionsTree:filterStrategy:advancedFilteringExpressionsTree:id:pipeTrigger:filteringPipeTrigger:true + | gridSort:sortingExpressions:[]:sortStrategy:id:pipeTrigger:true; as pinnedData + ) { + @if (pinnedData.length > 0) { +
+ @for (rowData of pinnedData; track rowData; let rowIndex = $index) { + + + } +
+ } + }
@@ -85,25 +92,35 @@ 'igx-grid__tr-container': true, 'igx-grid__tr--highlighted':isRowHighlighted(rowData) }"> - - + @for (layout of childLayoutList; track layout) { + + + }
- + @if (moving && columnInDrag) { + + }
- + @if (!this.parent) { + + }
- - + @if (shouldOverlayLoading) { + + + }
- + @if (moving && columnInDrag) { + + }
@@ -120,12 +137,14 @@
- - + (keydown)="navigation.summaryNav($event)"> + @if (hasSummarizedColumns && rootSummariesEnabled) { + + + }
@@ -149,18 +168,22 @@ {{emptyFilteredGridMessage}} - - - + @if (showAddButton) { + + + + } {{emptyGridMessage}} - - - + @if (showAddButton) { + + + + } @@ -190,13 +213,15 @@ -
-
- - +@if (rowEditable) { +
+
+ + +
-
+} {{ this.resourceStrings.igx_grid_row_edit_text | igxStringReplace:'{0}':rowChangesCount.toString() | igxStringReplace:'{1}':hiddenColumnsCount.toString() }} @@ -226,7 +251,9 @@ - +@if (colResizingService.showResizer) { + +}
@if (platform.isElements) { diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.ts b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.ts index 7e23eff7060..a06f2a229f7 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.ts +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.ts @@ -22,7 +22,7 @@ import { ViewChildren, ViewContainerRef } from '@angular/core'; -import { NgIf, NgClass, NgFor, NgTemplateOutlet, NgStyle } from '@angular/common'; +import { NgClass, NgTemplateOutlet, NgStyle } from '@angular/common'; import { IgxHierarchicalGridAPIService } from './hierarchical-grid-api.service'; import { IgxRowIslandComponent } from './row-island.component'; @@ -314,9 +314,7 @@ export class IgxChildGridRowComponent implements AfterViewInit, OnInit { IgxRowIslandAPIService ], imports: [ - NgIf, NgClass, - NgFor, NgTemplateOutlet, NgStyle, IgxGridHeaderRowComponent, diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.spec.ts b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.spec.ts index 7c6906103bb..baa369f3828 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.spec.ts @@ -13,7 +13,6 @@ import { IgxHeaderCollapsedIndicatorDirective, IgxHeaderExpandedIndicatorDirecti import { GridSelectionMode, Size } from '../common/enums'; import { GridFunctions } from '../../test-utils/grid-functions.spec'; import { IgxGridCellComponent } from '../cell.component'; -import { NgFor, NgIf } from '@angular/common'; import { IgxIconComponent } from '../../icon/icon.component'; import { IgxExcelStyleColumnOperationsTemplateDirective, IgxExcelStyleFilterOperationsTemplateDirective, IgxGridExcelStyleFilteringComponent } from '../filtering/excel-style/excel-style-filtering.component'; import { IgxExcelStyleHeaderComponent } from '../filtering/excel-style/excel-style-header.component'; @@ -1320,7 +1319,7 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { hierarchicalGrid = fixture.componentInstance.hgrid; }); - it('should render correct columns when setting columns for child in AfterViewInit using ngFor', () => { + it('should render correct columns when setting columns for child in AfterViewInit using @for', () => { const gridHead = fixture.debugElement.query(By.css(THEAD_CLASS)); const colHeaders = gridHead.queryAll(By.css('igx-grid-header')); expect(colHeaders.length).toEqual(2); @@ -1356,7 +1355,7 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { expect(child2Headers[2].nativeElement.innerText).toEqual('Col1'); }); - it('should render correct columns when setting columns for parent and child post init using ngFor', fakeAsync(() => { + it('should render correct columns when setting columns for parent and child post init using @for', fakeAsync(() => { const row = hierarchicalGrid.gridAPI.get_row_by_index(0) as IgxHierarchicalRowComponent; UIInteractions.simulateClickAndSelectEvent(row.expander); fixture.detectChanges(); @@ -1882,10 +1881,12 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { @Component({ template: ` - - - + [autoGenerate]="false" [height]="'400px'" [width]="width" #hierarchicalGrid> + + @if (showAnotherCol) { + + } + @@ -1896,7 +1897,7 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { `, - imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent, NgIf] + imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridTestBaseComponent { @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hgrid: IgxHierarchicalGridComponent; @@ -1934,11 +1935,15 @@ export class IgxHierarchicalGridTestBaseComponent { @Component({ template: ` - - + + - - + @if (toggleColumns) { + + } + @if (toggleColumns) { + + } @@ -1946,7 +1951,7 @@ export class IgxHierarchicalGridTestBaseComponent { `, - imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent, NgIf] + imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridMultiLayoutComponent extends IgxHierarchicalGridTestBaseComponent { @ViewChild('rowIsland1', { read: IgxRowIslandComponent, static: true }) public rowIsland1: IgxRowIslandComponent; @@ -2019,15 +2024,21 @@ export class IgxHGridRemoteOnDemandComponent { - + @for (colField of parentCols; track colField) { + + } - + @for (colField of islandCols1; track colField) { + + } - + @for (colField of islandCols2; track colField) { + + } `, - imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent, NgFor] + imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridColumnsUpdateComponent extends IgxHierarchicalGridTestBaseComponent implements AfterViewInit { public cols1 = ['ID', 'ProductName', 'Col1', 'Col2', 'Col3']; @@ -2080,13 +2091,17 @@ export class IgxHierarchicalGridSizingComponent { @Component({ template: ` - - - - + [autoGenerate]="true" [height]="'400px'" [width]="'500px'" #hierarchicalGrid> + @if (toggleRI) { + + @if (toggleChildRI) { + + + } + + } `, - imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent, NgIf] + imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridToggleRIComponent extends IgxHierarchicalGridTestBaseComponent { public toggleRI = true; @@ -2096,13 +2111,19 @@ public toggleChildRI = true; @Component({ template: ` - - - - + [autoGenerate]="false" [height]="'400px'" [width]="'500px'"> + @if (toggleColumns) { + + } + @if (toggleColumns) { + + } + @if (toggleRI) { + + + } `, - imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent, NgIf] + imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridToggleRIAndColsComponent extends IgxHierarchicalGridToggleRIComponent { public override toggleRI = false; diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.virtualization.spec.ts b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.virtualization.spec.ts index 50f673553fa..20b6e94edef 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.virtualization.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.virtualization.spec.ts @@ -110,7 +110,8 @@ describe('IgxHierarchicalGrid Virtualization #hGrid', () => { const expression = { fieldName: 'ProductName', searchVal: 'Product: A0', - condition: IgxStringFilteringOperand.instance().condition('startsWith') + condition: IgxStringFilteringOperand.instance().condition('startsWith'), + conditionName: 'startsWith' }; filteringExpressionsTree.filteringOperands.push(expression); childGrid.filter('ProductName', null, filteringExpressionsTree); diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-row.component.html b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-row.component.html index 918ede26d54..42d4a19c5d3 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-row.component.html +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-row.component.html @@ -19,14 +19,14 @@ - + @if (rowDraggable) {
-
+ } - + @if (showRowSelectors) {
-
+ } -
- - -
+ @if (hasChildren) { +
+ + +
+ } - + @if (pinnedColumns.length > 0 && grid.isPinningToStart) { - + } - + @if (pinnedColumns.length > 0 && !grid.isPinningToStart) { - + }
@@ -99,33 +101,34 @@ - - + @for (col of pinnedColumns | igxNotGrouped; track trackPinnedColumn(col)) { + + + } diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-row.component.ts b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-row.component.ts index 82949482523..e1b448b5b33 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-row.component.ts +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-row.component.ts @@ -17,14 +17,14 @@ import { IgxCheckboxComponent } from '../../checkbox/checkbox.component'; import { IgxGridForOfDirective } from '../../directives/for-of/for_of.directive'; import { IgxRowDragDirective } from '../row-drag.directive'; import { IgxIconComponent } from '../../icon/icon.component'; -import { NgTemplateOutlet, NgIf, NgClass, NgStyle, NgFor } from '@angular/common'; +import { NgTemplateOutlet, NgClass, NgStyle } from '@angular/common'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-hierarchical-grid-row', templateUrl: './hierarchical-row.component.html', providers: [{ provide: IgxRowDirective, useExisting: forwardRef(() => IgxHierarchicalRowComponent) }], - imports: [NgTemplateOutlet, IgxIconComponent, NgIf, IgxRowDragDirective, NgClass, IgxGridForOfDirective, IgxHierarchicalGridCellComponent, NgStyle, IgxCheckboxComponent, NgFor, IgxGridNotGroupedPipe, IgxGridCellStylesPipe, IgxGridCellStyleClassesPipe, IgxGridDataMapperPipe, IgxGridTransactionStatePipe] + imports: [NgTemplateOutlet, IgxIconComponent, IgxRowDragDirective, NgClass, IgxGridForOfDirective, IgxHierarchicalGridCellComponent, NgStyle, IgxCheckboxComponent, IgxGridNotGroupedPipe, IgxGridCellStylesPipe, IgxGridCellStyleClassesPipe, IgxGridDataMapperPipe, IgxGridTransactionStatePipe] }) export class IgxHierarchicalRowComponent extends IgxRowDirective { @ViewChild('expander', { read: ElementRef }) diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-data-selector.component.html b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-data-selector.component.html index 08f0109e206..5a41d48b3bb 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-data-selector.component.html +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-data-selector.component.html @@ -10,160 +10,168 @@ /> - - - {{ item.displayName || item.memberName }} - - - - {{ item.displayName || item.member }} - + @for ( + item of dims | filterPivotItems: input.value:grid?.pipeTrigger; + track item.memberName + ) { + + + {{ item.displayName || item.memberName }} + + } + @for ( + item of values | filterPivotItems: input.value:grid?.pipeTrigger; + track item + ) { + + + {{ item.displayName || item.member }} + + }
- - - -
- {{ grid?.resourceStrings[panel.i18n] }} -
-
- - {{ this.grid ? this.grid[panel.dataKey].length : 0 }} -
-
-
- - - -
-
-
- {{ - item.aggregate.key - }} - ( - {{ item[panel.displayKey] || item[panel.itemKey] }} - ) -
- - -
-
- - - - - - -
+ +
+ {{ grid?.resourceStrings[panel.i18n] }} +
+
+ + {{ this.grid ? this.grid[panel.dataKey].length : 0 }}
- - -
+ + - {{ grid?.resourceStrings.igx_grid_pivot_selector_panel_empty }} -
- - + @if (this.grid && this.grid[panel.dataKey].length > 0) { + + @for ( + item of this.grid[panel.dataKey]; + track (item.memberName || item.member) + ) { + +
+
+
+ @if (panel.type === null) { + {{ + item.aggregate.key + }} + } + @if (panel.type === null) { + ( + } + {{ item[panel.displayKey] || item[panel.itemKey] }} + @if (panel.type === null) { + ) + } +
+ @if (panel.sortable && item.sortDirection) { + + + } +
+
+ @if (panel.type !== null) { + + + } + @if (panel.type === null) { + + + } + @if (panel.dragChannels.length > 0) { + + + } +
+
+
+ } +
+ } + @if (this.grid && this.grid[panel.dataKey].length === 0) { +
+ {{ grid?.resourceStrings.igx_grid_pivot_selector_panel_empty }} +
+ } + + + } - - {{ item.label }} - + @for (item of aggregateList; track item) { + + {{ item.label }} + + } diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-data-selector.component.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-data-selector.component.ts index e530c093bbb..64ebfce8054 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-data-selector.component.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-data-selector.component.ts @@ -40,7 +40,6 @@ import { IgxExpansionPanelComponent } from "../../expansion-panel/expansion-pane import { IgxAccordionComponent } from "../../accordion/accordion.component"; import { IgxCheckboxComponent } from "../../checkbox/checkbox.component"; import { IgxListItemComponent } from "../../list/list-item.component"; -import { NgFor, NgIf } from "@angular/common"; import { IgxListComponent } from "../../list/list.component"; import { IgxInputDirective } from "../../directives/input/input.directive"; import { IgxPrefixDirective } from "../../directives/prefix/prefix.directive"; @@ -85,7 +84,7 @@ interface IDataSelectorPanel { @Component({ selector: "igx-pivot-data-selector", templateUrl: "./pivot-data-selector.component.html", - imports: [IgxInputGroupComponent, IgxIconComponent, IgxPrefixDirective, IgxInputDirective, IgxListComponent, NgFor, IgxListItemComponent, IgxCheckboxComponent, IgxAccordionComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxDropDirective, IgxExpansionPanelTitleDirective, IgxChipComponent, IgxExpansionPanelBodyComponent, NgIf, IgxDragDirective, IgxDropDownItemNavigationDirective, IgxDragHandleDirective, IgxDropDownComponent, IgxDropDownItemComponent, IgxFilterPivotItemsPipe] + imports: [IgxInputGroupComponent, IgxIconComponent, IgxPrefixDirective, IgxInputDirective, IgxListComponent, IgxListItemComponent, IgxCheckboxComponent, IgxAccordionComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxDropDirective, IgxExpansionPanelTitleDirective, IgxChipComponent, IgxExpansionPanelBodyComponent, IgxDragDirective, IgxDropDownItemNavigationDirective, IgxDragHandleDirective, IgxDropDownComponent, IgxDropDownItemComponent, IgxFilterPivotItemsPipe] }) export class IgxPivotDataSelectorComponent { diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.html b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.html index f027ce2452c..f1cb6f73e0e 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.html +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.html @@ -23,12 +23,14 @@ (dragStop)="selectionService.dragMode = $event" (scroll)="preventContainerScroll($event)" (dragScroll)="dragScroll($event)" [igxGridDragSelect]="selectionService.dragMode" [style.height.px]="totalHeight" [style.width.px]="pivotContentCalcWidth || null" #tbody [attr.aria-activedescendant]="activeDescendant"> - - 0) { + + } - + @if (shouldOverlayLoading) { + + + }
- + }
@@ -113,7 +119,9 @@
- +@if (colResizingService.showResizer) { + +}
@@ -130,51 +138,57 @@ -
- - - - -
+ @for (dim of rowDimensions; track dim.memberName; let dimIndex = $index) { +
+ + + + +
+ }
- + @if (dataView | pivotGridHorizontalRowGrouping:pivotConfiguration:pipeTrigger:regroupTrigger; as groupedData) { - + }
-
- - -
+ @if (columnDimensions.length > 0 || values.length > 0) { +
+ + +
+ }
diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.ts index 1b91da92ff7..042519ef0c8 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.component.ts @@ -29,7 +29,7 @@ import { OnChanges, SimpleChanges } from '@angular/core'; -import { DOCUMENT, NgTemplateOutlet, NgIf, NgClass, NgStyle, NgFor } from '@angular/common'; +import { DOCUMENT, NgTemplateOutlet, NgClass, NgStyle } from '@angular/common'; import { first, take, takeUntil} from 'rxjs/operators'; import { IgxGridBaseDirective } from '../grid-base.directive'; @@ -159,8 +159,6 @@ const MINIMUM_COLUMN_WIDTH_SUPER_COMPACT = 104; IgxForOfScrollSyncService ], imports: [ - NgIf, - NgFor, NgClass, NgStyle, NgTemplateOutlet, diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.interface.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.interface.ts index 5a4065ac5be..80adca67018 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.interface.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.interface.ts @@ -112,7 +112,7 @@ export interface IPivotConfiguration { export interface IPivotDimension { /** Allows defining a hierarchy when multiple sub groups need to be extracted from single member. */ childLevel?: IPivotDimension; - /** Field name to use in order to extract value. */ + /** Unique member to extract related data field value or the result of the memberFunction. */ memberName: string; /* csTreatAsEvent: MemberFunctionHandler */ @@ -151,7 +151,7 @@ export interface IPivotDimension { * Configuration of a pivot value aggregation. */ export interface IPivotValue { - /** Field name to use in order to extract value. */ + /** Unique member to extract related data field value for aggregations. */ member: string; /** Display name to show instead of member for the column header of this value. **/ displayName?: string; diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.spec.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.spec.ts index cc919d121ba..21b047ebe44 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-grid.spec.ts @@ -228,6 +228,7 @@ describe('IgxPivotGrid #pivotGrid', () => { filteringExpressionTree.filteringOperands = [ { condition: IgxStringFilteringOperand.instance().condition('equals'), + conditionName: 'equals', fieldName: 'SellerName', searchVal: 'Stanley' } @@ -2832,6 +2833,7 @@ describe('IgxPivotGrid #pivotGrid', () => { filterColumnExpTree.filteringOperands = [ { condition: IgxStringFilteringOperand.instance().condition('in'), + conditionName: 'in', fieldName: 'City', searchVal: new Set(['Ciudad de la Costa']) } @@ -2840,6 +2842,7 @@ describe('IgxPivotGrid #pivotGrid', () => { filterRowExpTree.filteringOperands = [ { condition: IgxStringFilteringOperand.instance().condition('in'), + conditionName: 'in', fieldName: 'ProductCategory', searchVal: new Set(['Bikes']) } diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-header-row.component.html b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-header-row.component.html index 637e952d7fe..8d72f72940e 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-header-row.component.html +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-header-row.component.html @@ -2,62 +2,69 @@
-
- - - {{grid.resourceStrings.igx_grid_pivot_empty_filter_drop_area}} - - - + + + @if (grid.filterDimensions.length === 0) { + {{grid.resourceStrings.igx_grid_pivot_empty_filter_drop_area}} + } + @for (filter of this.filterAreaDimensions; track filter; let last = $last) { + + + + + {{filter.displayName || filter.memberName}} + + @if (last) { + + } + } + + {{grid.resourceStrings.igx_grid_pivot_filter_drop_chip}} + + + @if (isFiltersButton && grid.filterDimensions.length !== 0) { +
+ (click)='onFiltersAreaDropdownClick($event)'> - {{filter.displayName || filter.memberName}} - - - - - - - {{grid.resourceStrings.igx_grid_pivot_filter_drop_chip}} - - -
- - - + +
+ }
-
+ }
-
- - {{grid.resourceStrings.igx_grid_pivot_empty_row_drop_area}} - - + + @if (grid.rowDimensions.length === 0) { + {{grid.resourceStrings.igx_grid_pivot_empty_row_drop_area}} + } + @for (row of grid.rowDimensions; track row.memberName; let last = $last) { + {{ row.displayName || row.memberName}} - - + @if (row.sortDirection) { + + + } - - - - - - {{grid.resourceStrings.igx_grid_pivot_row_drop_chip}} - - -
+ @if (last) { + + } + } + + {{grid.resourceStrings.igx_grid_pivot_row_drop_chip}} + + +
+ }
-
- - - - {{grid.resourceStrings.igx_grid_pivot_empty_column_drop_area}} - - - + + + @if (grid.columnDimensions.length === 0) { + + {{grid.resourceStrings.igx_grid_pivot_empty_column_drop_area}} + } + @for (col of grid.columnDimensions; track col.memberName; let last = $last) { + + - - - - - {{col.displayName || col.memberName}} - - + + + + + {{col.displayName || col.memberName}} + @if (col.sortDirection) { + + + } + + @if (last) { + + } + } + + {{grid.resourceStrings.igx_grid_pivot_column_drop_chip}} - - - - - - {{grid.resourceStrings.igx_grid_pivot_column_drop_chip}} - - -
+ +
+ } -
- - - {{grid.resourceStrings.igx_grid_pivot_empty_value_drop_area}} - - - + + + @if (grid.values.length === 0) { + {{grid.resourceStrings.igx_grid_pivot_empty_value_drop_area}} + } + @for (value of grid.values; track value.member; let last = $last) { + + -
- - -
- +
+ + +
+ +
+ @if (last) { + + } + } + + {{grid.resourceStrings.igx_grid_pivot_value_drop_chip}} - - - -
- - {{grid.resourceStrings.igx_grid_pivot_value_drop_chip}} - -
-
+ +
+ }
@@ -180,111 +198,117 @@
- + @if (!grid.pivotUI.showRowHeaders || grid.rowDimensions.length === 0) {
- - {{grid.resourceStrings.igx_grid_pivot_empty_row_drop_area}} - + } + @for (row of grid.rowDimensions; track row.memberName; let last = $last) { - - - - - {{ row.displayName || row.memberName}} + + + + + {{ row.displayName || row.memberName}} + @if (row.sortDirection) { - - - - - + } + + @if (last) { + + } + } {{grid.resourceStrings.igx_grid_pivot_row_drop_chip}} - + }
-
+ } - + @if (grid.pivotUI.showRowHeaders && grid.visibleRowDimensions.length > 0) {
- - - - + @for (dim of grid.visibleRowDimensions; track dim; let colIndex = $index; let isLast = $last) { + @if (getRowDimensionColumn(dim); as dimCol) { + + + } + }
-
+ } - - + @if (pinnedColumnCollection.length && grid.isPinningToStart) { + @for (column of pinnedColumnCollection | igxTopLevel; track column) { + [ngStyle]="column.headerGroupStyles | igxHeaderGroupStyle:column:grid.pipeTrigger" [column]="column" + [style.min-width]="column.resolvedWidth | igxHeaderGroupWidth:grid.defaultHeaderGroupMinWidth:hasMRL" + [style.flex-basis]="column.resolvedWidth | igxHeaderGroupWidth:grid.defaultHeaderGroupMinWidth:hasMRL" + (pointerdown)="grid.navigation.focusOutRowHeader($event)"> - - -
-
- - - - -
+ } + } +
+ @for (dimLevelColumns of columnDimensionsByLevel; track $index; let i = $index) { +
+ + + + +
+ }
- - + @if (pinnedColumnCollection.length && !grid.isPinningToStart) { + @for (column of pinnedColumnCollection | igxTopLevel; track column) { + [ngStyle]="column.headerGroupStyles |igxHeaderGroupStyle:column:grid.pipeTrigger" [column]="column" + [style.min-width]="column.resolvedWidth | igxHeaderGroupWidth:grid.defaultHeaderGroupMinWidth:hasMRL" + [style.flex-basis]="column.resolvedWidth | igxHeaderGroupWidth:grid.defaultHeaderGroupMinWidth:hasMRL" + [style.left]="column.rightPinnedOffset" (pointerdown)="grid.navigation.focusOutRowHeader($event)"> - - + } + }
@@ -293,21 +317,25 @@
- - {{ item.label }} - + @for (item of aggregateList; track item.key) { + + {{ item.label }} + + }
- - {{filter.displayName || filter.memberName}} - - + @for (filter of this.filterDropdownDimensions; track filter) { + + {{filter.displayName || filter.memberName}} + + } +
@@ -317,15 +345,16 @@
- - - {{filter.displayName || filter.memberName}} - + @for (filter of grid.filterDimensions; track filter) { + + + {{filter.displayName || filter.memberName}} + + }
diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-header-row.component.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-header-row.component.ts index 4c1cf49841b..8ef6713927b 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-header-row.component.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-header-row.component.ts @@ -35,7 +35,7 @@ import { IgxBadgeComponent } from '../../badge/badge.component'; import { IgxPrefixDirective } from '../../directives/prefix/prefix.directive'; import { IgxIconComponent } from '../../icon/icon.component'; import { IgxDropDirective } from '../../directives/drag-drop/drag-drop.directive'; -import { NgIf, NgFor, NgTemplateOutlet, NgClass, NgStyle } from '@angular/common'; +import { NgTemplateOutlet, NgClass, NgStyle } from '@angular/common'; import { IgxPivotRowHeaderGroupComponent } from './pivot-row-header-group.component'; import { IgxPivotRowDimensionHeaderGroupComponent } from './pivot-row-dimension-header-group.component'; @@ -51,7 +51,7 @@ import { IgxPivotRowDimensionHeaderGroupComponent } from './pivot-row-dimension- changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-pivot-header-row', templateUrl: './pivot-header-row.component.html', - imports: [NgIf, IgxDropDirective, IgxChipsAreaComponent, NgFor, IgxChipComponent, IgxIconComponent, + imports: [IgxDropDirective, IgxChipsAreaComponent, IgxChipComponent, IgxIconComponent, IgxPrefixDirective, IgxBadgeComponent, IgxSuffixDirective, IgxDropDownItemNavigationDirective, NgTemplateOutlet, IgxGridHeaderGroupComponent, NgClass, NgStyle, IgxGridForOfDirective, IgxDropDownComponent, IgxDropDownItemComponent, IgxGridExcelStyleFilteringComponent, diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-header-group.component.html b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-header-group.component.html index 0ce641f9d02..e3c40924119 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-header-group.component.html +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-header-group.component.html @@ -9,8 +9,10 @@ - - +@if (!column.columnGroup) { + @if (grid.hasMovableColumns) { + + } - - - - + @if (!column.columnGroup && column.resizable) { + + + } + @if (grid.hasMovableColumns) { + + } +} diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-header-group.component.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-header-group.component.ts index d6c31e60447..1687303b5dd 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-header-group.component.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-header-group.component.ts @@ -11,7 +11,7 @@ import { IgxHeaderGroupStylePipe } from '../headers/pipes'; import { IgxPivotResizeHandleDirective } from '../resizing/pivot-grid/pivot-resize-handle.directive'; import { IgxColumnMovingDropDirective } from '../moving/moving.drop.directive'; import { IgxColumnMovingDragDirective } from '../moving/moving.drag.directive'; -import { NgIf, NgClass, NgStyle } from '@angular/common'; +import { NgClass, NgStyle } from '@angular/common'; import { IgxIconComponent } from '../../icon/icon.component'; import { IMultiRowLayoutNode } from '../common/types'; @@ -22,7 +22,7 @@ import { IMultiRowLayoutNode } from '../common/types'; changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-pivot-row-dimension-header-group', templateUrl: './pivot-row-dimension-header-group.component.html', - imports: [IgxIconComponent, NgIf, IgxPivotRowDimensionHeaderComponent, NgClass, NgStyle, IgxColumnMovingDragDirective, IgxColumnMovingDropDirective, IgxPivotResizeHandleDirective, IgxHeaderGroupStylePipe] + imports: [IgxIconComponent, IgxPivotRowDimensionHeaderComponent, NgClass, NgStyle, IgxColumnMovingDragDirective, IgxColumnMovingDropDirective, IgxPivotResizeHandleDirective, IgxHeaderGroupStylePipe] }) export class IgxPivotRowDimensionHeaderGroupComponent extends IgxGridHeaderGroupComponent implements PivotRowHeaderGroupType { diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-header.component.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-header.component.ts index 0b376ca5f87..afd14656238 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-header.component.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-header.component.ts @@ -5,7 +5,7 @@ import { GridType, IGX_GRID_BASE, PivotGridType } from '../common/grid.interface import { IgxGridHeaderComponent } from '../headers/grid-header.component'; import { IgxPivotColumnResizingService } from '../resizing/pivot-grid/pivot-resizing.service'; import { SortingIndexPipe } from '../headers/pipes'; -import { NgTemplateOutlet, NgIf, NgClass } from '@angular/common'; +import { NgTemplateOutlet, NgClass } from '@angular/common'; import { IgxIconComponent } from '../../icon/icon.component'; import { ISortingExpression, SortingDirection } from '../../data-operations/sorting-strategy'; import { takeUntil } from 'rxjs/operators'; @@ -19,7 +19,7 @@ import { PivotUtil } from './pivot-util'; changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-pivot-row-dimension-header', templateUrl: '../headers/grid-header.component.html', - imports: [IgxIconComponent, NgTemplateOutlet, NgIf, NgClass, SortingIndexPipe] + imports: [IgxIconComponent, NgTemplateOutlet, NgClass, SortingIndexPipe] }) export class IgxPivotRowDimensionHeaderComponent extends IgxGridHeaderComponent implements AfterViewInit { private pivotGrid: PivotGridType; diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-mrl-row.component.html b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-mrl-row.component.html index 8cd685921b7..7e917a0eeaf 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-mrl-row.component.html +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-mrl-row.component.html @@ -1,5 +1,7 @@ - +@for ( + cell of rowGroup | pivotGridHorizontalRowCellMerging:grid.pivotConfiguration:grid.pipeTrigger; + track getGroupKey(cell); let cellIndex = $index +) { - +} diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-mrl-row.component.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-mrl-row.component.ts index 9e8c61468b2..335008b8de8 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-mrl-row.component.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-dimension-mrl-row.component.ts @@ -14,10 +14,10 @@ import { } from '@angular/core'; import { IGX_GRID_BASE, PivotGridType } from '../common/grid.interface'; import { IgxGridHeaderRowComponent } from '../headers/grid-header-row.component'; -import { IPivotDimension, IPivotDimensionData, IPivotGridRecord } from './pivot-grid.interface'; -import { NgFor } from '@angular/common'; +import { IPivotDimension, IPivotDimensionData, IPivotGridHorizontalGroup, IPivotGridRecord } from './pivot-grid.interface'; import { IgxPivotRowDimensionContentComponent } from './pivot-row-dimension-content.component'; import { IgxPivotGridHorizontalRowCellMerging } from './pivot-grid.pipes'; +import { PivotUtil } from './pivot-util'; /** * @@ -31,7 +31,7 @@ import { IgxPivotGridHorizontalRowCellMerging } from './pivot-grid.pipes'; changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-pivot-row-dimension-mrl-row', templateUrl: './pivot-row-dimension-mrl-row.component.html', - imports: [NgFor, IgxPivotRowDimensionContentComponent, IgxPivotGridHorizontalRowCellMerging] + imports: [IgxPivotRowDimensionContentComponent, IgxPivotGridHorizontalRowCellMerging] }) export class IgxPivotRowDimensionMrlRowComponent extends IgxGridHeaderRowComponent { @@ -115,4 +115,10 @@ export class IgxPivotRowDimensionMrlRowComponent extends IgxGridHeaderRowCompone } return resWidth; } + + protected getGroupKey(group: IPivotGridHorizontalGroup) { + const rec = group.records[0]; + const key = PivotUtil.getRecordKey(rec, group.rootDimension); + return key; + } } diff --git a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-header-group.component.ts b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-header-group.component.ts index e804570aed4..4af9f47c472 100644 --- a/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-header-group.component.ts +++ b/projects/igniteui-angular/src/lib/grids/pivot-grid/pivot-row-header-group.component.ts @@ -10,7 +10,7 @@ import { IgxHeaderGroupStylePipe } from '../headers/pipes'; import { IgxPivotResizeHandleDirective } from '../resizing/pivot-grid/pivot-resize-handle.directive'; import { IgxColumnMovingDropDirective } from '../moving/moving.drop.directive'; import { IgxColumnMovingDragDirective } from '../moving/moving.drag.directive'; -import { NgIf, NgClass, NgStyle } from '@angular/common'; +import { NgClass, NgStyle } from '@angular/common'; import { IgxIconComponent } from '../../icon/icon.component'; import { SortingDirection } from '../../data-operations/sorting-strategy'; @@ -21,7 +21,7 @@ import { SortingDirection } from '../../data-operations/sorting-strategy'; changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-pivot-row-header-group', templateUrl: './pivot-row-dimension-header-group.component.html', - imports: [IgxIconComponent, NgIf, IgxPivotRowDimensionHeaderComponent, NgClass, NgStyle, IgxColumnMovingDragDirective, IgxColumnMovingDropDirective, IgxPivotResizeHandleDirective, IgxHeaderGroupStylePipe] + imports: [IgxIconComponent, IgxPivotRowDimensionHeaderComponent, NgClass, NgStyle, IgxColumnMovingDragDirective, IgxColumnMovingDropDirective, IgxPivotResizeHandleDirective, IgxHeaderGroupStylePipe] }) export class IgxPivotRowHeaderGroupComponent extends IgxGridHeaderGroupComponent implements PivotRowHeaderGroupType { diff --git a/projects/igniteui-angular/src/lib/grids/row.directive.ts b/projects/igniteui-angular/src/lib/grids/row.directive.ts index b3b44e1f763..9b9b71b8d1b 100644 --- a/projects/igniteui-angular/src/lib/grids/row.directive.ts +++ b/projects/igniteui-angular/src/lib/grids/row.directive.ts @@ -26,6 +26,7 @@ import { CellType, ColumnType, GridType, IGX_GRID_BASE } from './common/grid.int import { mergeWith } from 'lodash-es'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; +import { trackByIdentity } from '../core/utils'; @Directive({ selector: '[igxRowBaseComponent]', @@ -599,4 +600,10 @@ export class IgxRowDirective implements DoCheck, AfterViewInit, OnDestroy { const dragIndicatorOff = this.grid.rowDragging && !this.dragging ? 'igx-grid__drag-indicator--off' : ''; return `${defaultDragIndicatorCssClass} ${dragIndicatorOff}`; } + + /** + * - state persistence switching all pinned columns resets collection + * - MRL unpinnedColumns igxFor modes entire child loop on unpin + */ + protected trackPinnedColumn = trackByIdentity; } diff --git a/projects/igniteui-angular/src/lib/grids/state-base.directive.ts b/projects/igniteui-angular/src/lib/grids/state-base.directive.ts index 8aeda2630a1..2dfb9669d6b 100644 --- a/projects/igniteui-angular/src/lib/grids/state-base.directive.ts +++ b/projects/igniteui-angular/src/lib/grids/state-base.directive.ts @@ -1,28 +1,24 @@ import { Directive, Optional, Input, Host, ViewContainerRef, Inject, createComponent, EnvironmentInjector, Injector } from '@angular/core'; -import { FilteringExpressionsTree, IFilteringExpressionsTree } from '../data-operations/filtering-expressions-tree'; -import { IFilteringExpression } from '../data-operations/filtering-expression.interface'; +import { IExpressionTree, IFilteringExpressionsTree } from '../data-operations/filtering-expressions-tree'; import { IgxColumnComponent } from './columns/column.component'; import { IgxColumnGroupComponent } from './columns/column-group.component'; import { IGroupingExpression } from '../data-operations/grouping-expression.interface'; import { IPagingState } from '../data-operations/paging-state.interface'; import { GridColumnDataType } from '../data-operations/data-util'; -import { - IgxBooleanFilteringOperand, IgxNumberFilteringOperand, IgxDateFilteringOperand, - IgxStringFilteringOperand, IFilteringOperation, IgxDateTimeFilteringOperand -} from '../data-operations/filtering-condition'; import { IGroupByExpandState } from '../data-operations/groupby-expand-state.interface'; import { IGroupingState } from '../data-operations/groupby-state.interface'; import { IgxGridComponent } from './grid/grid.component'; import { IgxHierarchicalGridComponent } from './hierarchical-grid/hierarchical-grid.component'; import { GridSelectionRange } from './common/types'; import { ISortingExpression } from '../data-operations/sorting-strategy'; -import { ColumnType, GridType, IGX_GRID_BASE, IPinningConfig } from './common/grid.interface'; +import { ColumnType, FieldType, GridType, IGX_GRID_BASE, IPinningConfig } from './common/grid.interface'; import { IgxPivotGridComponent } from './pivot-grid/pivot-grid.component'; import { IPivotConfiguration, IPivotDimension } from './pivot-grid/pivot-grid.interface' import { PivotUtil } from './pivot-grid/pivot-util'; import { IgxPivotDateDimension } from './pivot-grid/pivot-grid-dimensions'; import { cloneArray, cloneValue } from '../core/utils'; import { IgxColumnLayoutComponent } from './columns/column-layout.component'; +import { recreateTreeFromFields } from '../data-operations/expressions-tree-util'; export interface IGridState { columns?: IColumnState[]; @@ -170,9 +166,9 @@ export class IgxGridStateBaseDirective { } return { filtering: filteringState }; }, - restoreFeatureState: (context: IgxGridStateBaseDirective, state: FilteringExpressionsTree): void => { + restoreFeatureState: (context: IgxGridStateBaseDirective, state: IFilteringExpressionsTree): void => { const filterTree = context.createExpressionsTreeFromObject(state); - context.currGrid.filteringExpressionsTree = filterTree as FilteringExpressionsTree; + context.currGrid.filteringExpressionsTree = filterTree as IFilteringExpressionsTree; } }, advancedFiltering: { @@ -190,9 +186,9 @@ export class IgxGridStateBaseDirective { } return { advancedFiltering }; }, - restoreFeatureState: (context: IgxGridStateBaseDirective, state: FilteringExpressionsTree): void => { + restoreFeatureState: (context: IgxGridStateBaseDirective, state: IFilteringExpressionsTree): void => { const filterTree = context.createExpressionsTreeFromObject(state); - context.currGrid.advancedFilteringExpressionsTree = filterTree as FilteringExpressionsTree; + context.currGrid.advancedFilteringExpressionsTree = filterTree as IFilteringExpressionsTree; } }, columns: { @@ -625,7 +621,7 @@ export class IgxGridStateBaseDirective { } // restore complex filters if (dim.filter) { - dim.filter = this.createExpressionsTreeFromObject(dim.filter as FilteringExpressionsTree); + dim.filter = this.createExpressionsTreeFromObject(dim.filter) as IFilteringExpressionsTree; } } } @@ -676,78 +672,18 @@ export class IgxGridStateBaseDirective { } /** - * This method builds a FilteringExpressionsTree from a provided object. + * This method builds a rehydrated IExpressionTree from a provided object. */ - private createExpressionsTreeFromObject(exprTreeObject: FilteringExpressionsTree): FilteringExpressionsTree { + private createExpressionsTreeFromObject(exprTreeObject: IExpressionTree): IExpressionTree { if (!exprTreeObject || !exprTreeObject.filteringOperands) { return null; } - const expressionsTree = new FilteringExpressionsTree(exprTreeObject.operator, exprTreeObject.fieldName); - - for (const item of exprTreeObject.filteringOperands) { - // Check if item is an expressions tree or a single expression. - if ((item as FilteringExpressionsTree).filteringOperands) { - const subTree = this.createExpressionsTreeFromObject((item as FilteringExpressionsTree)); - expressionsTree.filteringOperands.push(subTree); - } else { - const expr = item as IFilteringExpression; - let dataType: string; - if (this.currGrid instanceof IgxPivotGridComponent) { - dataType = this.currGrid.allDimensions.find(x => x.memberName === expr.fieldName).dataType; - } else if (this.currGrid.columns.length > 0) { - dataType = this.currGrid.columns.find(c => c.field === expr.fieldName).dataType; - } else if (this.state.columns) { - dataType = this.state.columns.find(c => c.field === expr.fieldName).dataType; - } else { - return null; - } - // when ESF, values are stored in Set. - // First those values are converted to an array before returning string in the stringifyCallback - // now we need to convert those back to Set - if (Array.isArray(expr.searchVal)) { - expr.searchVal = new Set(expr.searchVal); - } else { - expr.searchVal = expr.searchVal && (dataType === 'date' || dataType === 'dateTime') ? new Date(Date.parse(expr.searchVal)) : expr.searchVal; - } - - const condition = this.generateFilteringCondition(dataType, expr.condition.name) || - this.currGrid.columns.find(c => c.field === expr.fieldName).filters.condition(expr.condition.name); - - if (condition) { - expr.condition = condition; - expressionsTree.filteringOperands.push(expr); - } - } + if (this.currGrid instanceof IgxPivotGridComponent) { + return recreateTreeFromFields(exprTreeObject, this.currGrid.allDimensions.map(d => ({ dataType: d.dataType, field: d.memberName })) as FieldType[]) as IExpressionTree; } - return expressionsTree; - } - - /** - * Returns the filtering logic function for a given dataType and condition (contains, greaterThan, etc.) - */ - private generateFilteringCondition(dataType: string, name: string): IFilteringOperation { - let filters; - switch (dataType) { - case GridColumnDataType.Boolean: - filters = IgxBooleanFilteringOperand.instance(); - break; - case GridColumnDataType.Number: - filters = IgxNumberFilteringOperand.instance(); - break; - case GridColumnDataType.Date: - filters = IgxDateFilteringOperand.instance(); - break; - case GridColumnDataType.DateTime: - filters = IgxDateTimeFilteringOperand.instance(); - break; - case GridColumnDataType.String: - default: - filters = IgxStringFilteringOperand.instance(); - break; - } - return filters.condition(name); + return recreateTreeFromFields(exprTreeObject, this.currGrid.columns) as IExpressionTree; } protected stringifyCallback(key: string, val: any) { diff --git a/projects/igniteui-angular/src/lib/grids/state.directive.spec.ts b/projects/igniteui-angular/src/lib/grids/state.directive.spec.ts index e1c18b3ae16..2084025bb84 100644 --- a/projects/igniteui-angular/src/lib/grids/state.directive.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/state.directive.spec.ts @@ -17,7 +17,6 @@ import { DefaultSortingStrategy, ISortingExpression, SortingDirection } from '.. import { GridSelectionRange } from './common/types'; import { CustomFilter } from '../test-utils/grid-samples.spec'; import { IgxPaginatorComponent } from '../paginator/paginator.component'; -import { NgFor } from '@angular/common'; import { IgxColumnComponent, IgxColumnGroupComponent, IgxColumnLayoutComponent, IgxGridDetailTemplateDirective } from './public_api'; import { IColumnState, IGridState } from './state-base.directive'; @@ -92,7 +91,7 @@ describe('IgxGridState - input properties #grid', () => { expect(gridState).toBe(initialGridState, 'JSON string representation of the initial grid state is not correct'); }); - it('getState should return corect IGridState object when using default options', () => { + it('getState should return correct IGridState object when using default options', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); const grid = fix.componentInstance.grid; @@ -102,6 +101,7 @@ describe('IgxGridState - input properties #grid', () => { const productFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); const productExpression = { condition: IgxBooleanFilteringOperand.instance().condition('true'), + conditionName: 'true', fieldName: 'InStock', ignoreCase: true }; @@ -173,9 +173,10 @@ describe('IgxGridState - input properties #grid', () => { fix.detectChanges(); const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; - const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"true","isUnary":true,"iconName":"filter_true"},"fieldName":"InStock","ignoreCase":true}],"operator":0,"fieldName":"InStock"}],"operator":0,"type":0}}'; + const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"true","isUnary":true,"iconName":"filter_true"},"fieldName":"InStock","ignoreCase":true,"conditionName":"true"}],"operator":0,"fieldName":"InStock"}],"operator":0,"type":0}}'; const initialState = '{"filtering":{"filteringOperands":[],"operator":0}}'; + let gridState = state.getState(true, 'filtering'); expect(gridState).toBe(initialState); @@ -197,7 +198,7 @@ describe('IgxGridState - input properties #grid', () => { fix.detectChanges(); const state = fix.componentInstance.state; - const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"equals","isUnary":false,"iconName":"filter_equal"},"fieldName":"LastDate","ignoreCase":true,"searchVal":"2021-06-05T20:59:00.000Z"}],"operator":1,"fieldName":"LastDate"}],"operator":0,"type":0}}'; + const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"equals","isUnary":false,"iconName":"filter_equal"},"fieldName":"LastDate","ignoreCase":true,"conditionName":"equals","searchVal":"2021-06-05T20:59:00.000Z"}],"operator":1,"fieldName":"LastDate"}],"operator":0,"type":0}}'; const initialState = '{"filtering":{"filteringOperands":[],"operator":0}}'; let gridState = state.getState(true, 'filtering'); @@ -218,7 +219,7 @@ describe('IgxGridState - input properties #grid', () => { fix.detectChanges(); const state = fix.componentInstance.state; - const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"empty","isUnary":true,"iconName":"filter_empty"},"fieldName":"OrderDate","ignoreCase":true,"searchVal":null}],"operator":1,"fieldName":"OrderDate"}],"operator":0,"type":0}}'; + const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"empty","isUnary":true,"iconName":"filter_empty"},"fieldName":"OrderDate","ignoreCase":true,"searchVal":null,"conditionName":"empty"}],"operator":1,"fieldName":"OrderDate"}],"operator":0,"type":0}}'; const initialState = '{"filtering":{"filteringOperands":[],"operator":0}}'; let gridState = state.getState(true, 'filtering'); @@ -236,7 +237,7 @@ describe('IgxGridState - input properties #grid', () => { fix.detectChanges(); const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; - const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"true","isUnary":true,"iconName":"filter_true"},"fieldName":"InStock","ignoreCase":true}],"operator":0,"fieldName":"InStock"}],"operator":0,"type":0}}'; + const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"true","isUnary":true,"iconName":"filter_true"},"fieldName":"InStock","ignoreCase":true,"conditionName":"true"}],"operator":0,"fieldName":"InStock"}],"operator":0,"type":0}}'; const filteringStateObject = JSON.parse(filteringState) as IGridState; const initialState = '{"filtering":{"filteringOperands":[],"operator":0}}'; @@ -262,7 +263,7 @@ describe('IgxGridState - input properties #grid', () => { const initialState = '{"filtering":{"filteringOperands":[],"operator":0}}'; const filteringState = - '{"filtering":{"filteringOperands":[{"filteringOperands":[{"fieldName":"ProductID","condition":{"name":"custom","isUnary":false,"iconName":"custom"},"searchVal":"custom","ignoreCase":true}],"operator":1,"fieldName":"FirstName"}],"operator":0,"type":0}}'; + '{"filtering":{"filteringOperands":[{"filteringOperands":[{"fieldName":"ProductID","condition":{"name":"custom","isUnary":false,"iconName":"custom"},"searchVal":"custom","ignoreCase":true,"conditionName":"custom"}],"operator":1,"fieldName":"FirstName"}],"operator":0,"type":0}}'; const filteringStateObject = JSON.parse(filteringState) as IGridState; let gridState = state.getState(true, "filtering"); @@ -690,7 +691,7 @@ describe('IgxGridState - input properties #grid', () => { fix.detectChanges(); const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; - const advFilteringState = '{"advancedFiltering":{"filteringOperands":[{"fieldName":"InStock","condition":{"name":"true","isUnary":true,"iconName":"filter_true"},"searchVal":null,"ignoreCase":true},{"fieldName":"ProductID","condition":{"name":"greaterThan","isUnary":false,"iconName":"filter_greater_than"},"searchVal":"3","ignoreCase":true}],"operator":0,"type":1}}'; + const advFilteringState = '{"advancedFiltering":{"filteringOperands":[{"fieldName":"InStock","condition":{"name":"true","isUnary":true,"iconName":"filter_true"},"searchVal":null,"ignoreCase":true,"conditionName":"true"},{"fieldName":"ProductID","condition":{"name":"greaterThan","isUnary":false,"iconName":"filter_greater_than"},"searchVal":"3","ignoreCase":true,"conditionName":"greaterThan"}],"operator":0,"type":1}}'; const initialState = '{"advancedFiltering":{}}'; let gridState = state.getState(true, 'advancedFiltering'); @@ -708,7 +709,7 @@ describe('IgxGridState - input properties #grid', () => { fix.detectChanges(); const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; - const advFilteringState = '{"advancedFiltering":{"filteringOperands":[{"fieldName":"InStock","condition":{"name":"true","isUnary":true,"iconName":"filter_true"},"searchVal":null,"ignoreCase":true},{"fieldName":"ProductID","condition":{"name":"greaterThan","isUnary":false,"iconName":"filter_greater_than"},"searchVal":"3","ignoreCase":true}],"operator":0,"type":1}}'; + const advFilteringState = '{"advancedFiltering":{"filteringOperands":[{"fieldName":"InStock","condition":{"name":"true","isUnary":true,"iconName":"filter_true"},"searchVal":null,"ignoreCase":true,"conditionName":"true"},{"fieldName":"ProductID","condition":{"name":"greaterThan","isUnary":false,"iconName":"filter_greater_than"},"searchVal":"3","ignoreCase":true,"conditionName":"greaterThan"}],"operator":0,"type":1}}'; const initialState = '{"advancedFiltering":{}}'; const advFilteringStateObject = JSON.parse(advFilteringState); @@ -730,7 +731,7 @@ describe('IgxGridState - input properties #grid', () => { fix.detectChanges(); const state = fix.componentInstance.state; - const advFilteringState = '{"advancedFiltering":{"filteringOperands":[{"fieldName":"ProductID","condition":{"name":"custom","isUnary":false,"iconName":"custom"},"ignoreCase":true,"searchVal":"custom"}],"operator":0,"type":1}}'; + const advFilteringState = '{"advancedFiltering":{"filteringOperands":[{"fieldName":"ProductID","condition":{"name":"custom","isUnary":false,"iconName":"custom"},"ignoreCase":true,"searchVal":"custom","conditionName":"custom"}],"operator":0,"type":1}}'; const initialState = '{"advancedFiltering":{}}'; let gridState = state.getState(true, 'advancedFiltering'); @@ -878,35 +879,37 @@ class HelperFunctions { template: ` - - + @for (c of columns; track c) { + + + } Custom Content: {{cell.value}} `, - imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent, IgxGridStateDirective, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent, IgxGridStateDirective] }) export class IgxGridStateComponent { @ViewChild('grid', { read: IgxGridComponent, static: true }) @@ -985,7 +988,7 @@ export class IgxGridStateWithDetailsComponent { `, - imports: [IgxGridComponent, IgxColumnComponent, IgxColumnGroupComponent, IgxGridStateDirective, NgFor] + imports: [IgxGridComponent, IgxColumnComponent, IgxColumnGroupComponent, IgxGridStateDirective] }) export class CollapsibleColumnGroupTestComponent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) diff --git a/projects/igniteui-angular/src/lib/grids/state.hierarchicalgrid.spec.ts b/projects/igniteui-angular/src/lib/grids/state.hierarchicalgrid.spec.ts index e7b09a7d41c..a6ec23656c4 100644 --- a/projects/igniteui-angular/src/lib/grids/state.hierarchicalgrid.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/state.hierarchicalgrid.spec.ts @@ -15,7 +15,6 @@ import { ISortingExpression, SortingDirection } from '../data-operations/sorting import { GridSelectionRange } from './common/types'; import { IgxColumnComponent } from './public_api'; import { IgxPaginatorComponent } from '../paginator/paginator.component'; -import { NgFor } from '@angular/common'; import { IColumnState, IGridState } from './state-base.directive'; describe('IgxHierarchicalGridState - input properties #hGrid', () => { @@ -108,6 +107,7 @@ describe('IgxHierarchicalGridState - input properties #hGrid', () => { const productFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); const productExpression = { condition: IgxStringFilteringOperand.instance().condition('contains'), + conditionName: 'contains', fieldName: 'ProductName', ignoreCase: true, searchVal: 'A0' @@ -213,7 +213,7 @@ describe('IgxHierarchicalGridState - input properties #hGrid', () => { const emptyFiltering = '{"filteringOperands":[],"operator":0}'; const initialState = HelperFunctions.buildStateString(grid, 'filtering', emptyFiltering, emptyFiltering); - const filtering = '{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"contains","isUnary":false,"iconName":"filter_contains"},"fieldName":"ProductName","ignoreCase":true,"searchVal":"A0"}],"operator":0,"fieldName":"ProductName"}],"operator":0,"type":0}'; + const filtering = '{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"contains","isUnary":false,"iconName":"filter_contains"},"fieldName":"ProductName","ignoreCase":true,"searchVal":"A0","conditionName":"contains"}],"operator":0,"fieldName":"ProductName"}],"operator":0,"type":0}'; const filteringState = HelperFunctions.buildStateString(grid, 'filtering', filtering, filtering); const filteringStateObject = JSON.parse(filteringState) as IGridState; @@ -241,7 +241,7 @@ describe('IgxHierarchicalGridState - input properties #hGrid', () => { const emptyFiltering = '{"filteringOperands":[],"operator":0}'; const initialState = HelperFunctions.buildStateString(grid, 'filtering', emptyFiltering, emptyFiltering); - const filtering = '{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"contains","isUnary":false,"iconName":"filter_contains"},"fieldName":"ProductName","ignoreCase":true,"searchVal":"A0"}],"operator":0,"fieldName":"ProductName"}],"operator":0,"type":0}'; + const filtering = '{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"contains","isUnary":false,"iconName":"filter_contains"},"fieldName":"ProductName","ignoreCase":true,"searchVal":"A0","conditionName":"contains"}],"operator":0,"fieldName":"ProductName"}],"operator":0,"type":0}'; const filteringState = HelperFunctions.buildStateString(grid, 'filtering', filtering, filtering); const filteringStateObject = JSON.parse(filteringState) as IGridState; @@ -349,7 +349,7 @@ describe('IgxHierarchicalGridState - input properties #hGrid', () => { const emptyFiltering = '{}'; const initialState = HelperFunctions.buildStateString(grid, 'advancedFiltering', emptyFiltering, emptyFiltering); - const filtering = '{"filteringOperands":[{"fieldName":"ProductName","condition":{"name":"contains","isUnary":false,"iconName":"filter_contains"},"searchVal":"A0","ignoreCase":true},{"fieldName":"ID","condition":{"name":"lessThan","isUnary":false,"iconName":"filter_less_than"},"searchVal":3,"ignoreCase":true}],"operator":0,"type":1}'; + const filtering = '{"filteringOperands":[{"fieldName":"ProductName","condition":{"name":"contains","isUnary":false,"iconName":"filter_contains"},"searchVal":"A0","ignoreCase":true,"conditionName":"contains"},{"fieldName":"ID","condition":{"name":"lessThan","isUnary":false,"iconName":"filter_less_than"},"searchVal":3,"ignoreCase":true,"conditionName":"lessThan"}],"operator":0,"type":1}'; const filteringState = HelperFunctions.buildStateString(grid, 'advancedFiltering', filtering, filtering); let gridState = state.getState(true, ['advancedFiltering', 'rowIslands']); @@ -372,7 +372,7 @@ describe('IgxHierarchicalGridState - input properties #hGrid', () => { const emptyFiltering = '{}'; const initialState = HelperFunctions.buildStateString(grid, 'advancedFiltering', emptyFiltering, emptyFiltering); - const filtering = '{"filteringOperands":[{"fieldName":"ProductName","condition":{"name":"contains","isUnary":false,"iconName":"filter_contains"},"searchVal":"A0","ignoreCase":true},{"fieldName":"ID","condition":{"name":"lessThan","isUnary":false,"iconName":"filter_less_than"},"searchVal":3,"ignoreCase":true}],"operator":0,"type":1}'; + const filtering = '{"filteringOperands":[{"fieldName":"ProductName","condition":{"name":"contains","isUnary":false,"iconName":"filter_contains"},"searchVal":"A0","ignoreCase":true,"conditionName":"contains"},{"fieldName":"ID","condition":{"name":"lessThan","isUnary":false,"iconName":"filter_less_than"},"searchVal":3,"ignoreCase":true,"conditionName":"lessThan"}],"operator":0,"type":1}'; const filteringState = HelperFunctions.buildStateString(grid, 'advancedFiltering', filtering, filtering); const filteringStateObject = JSON.parse(filteringState) as IGridState; @@ -636,30 +636,9 @@ class HelperFunctions { @Component({ template: ` - - - - - + @for (c of columns; track c) { + + } + + + @for (c of childColumns; track c) { + + + } `, - imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxPaginatorComponent, IgxRowIslandComponent, IgxGridStateDirective, NgFor] + imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxPaginatorComponent, IgxRowIslandComponent, IgxGridStateDirective] }) export class IgxHierarchicalGridTestExpandedBaseComponent { @ViewChild('hGrid', { read: IgxHierarchicalGridComponent, static: true }) public hgrid: IgxHierarchicalGridComponent; diff --git a/projects/igniteui-angular/src/lib/grids/state.treegrid.spec.ts b/projects/igniteui-angular/src/lib/grids/state.treegrid.spec.ts index cb260e38cbd..c3e853fb7e9 100644 --- a/projects/igniteui-angular/src/lib/grids/state.treegrid.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/state.treegrid.spec.ts @@ -16,7 +16,6 @@ import { IgxTreeGridComponent } from './tree-grid/public_api'; import { ISortingExpression } from '../data-operations/sorting-strategy'; import { GridSelectionRange } from './common/types'; import { IgxPaginatorComponent } from '../paginator/paginator.component'; -import { NgFor } from '@angular/common'; import { IgxColumnComponent } from './public_api'; import { IColumnState, IGridState } from './state-base.directive'; @@ -100,6 +99,7 @@ describe('IgxTreeGridState - input properties #tGrid', () => { const productFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And, 'Age'); const productExpression = { condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), + conditionName: 'greaterThan', fieldName: 'Age', ignoreCase: true, searchVal: 35 @@ -134,7 +134,7 @@ describe('IgxTreeGridState - input properties #tGrid', () => { it('setState should correctly restore grid filtering state from string', () => { fix.detectChanges(); const state = fix.componentInstance.state; - const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"greaterThan","isUnary":false,"iconName":"filter_greater_than"},"searchVal":35,"fieldName":"Age","ignoreCase":true}],"operator":0,"fieldName":"Age"}],"operator":0,"type":0}}'; + const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"greaterThan","isUnary":false,"iconName":"filter_greater_than"},"searchVal":35,"fieldName":"Age","ignoreCase":true,"conditionName":"greaterThan"}],"operator":0,"fieldName":"Age"}],"operator":0,"type":0}}'; const initialState = '{"filtering":{"filteringOperands":[],"operator":0}}'; let gridState = state.getState(true, 'filtering'); @@ -260,7 +260,7 @@ describe('IgxTreeGridState - input properties #tGrid', () => { it('setState should correctly restore grid advanced filtering state from string', () => { fix.detectChanges(); const state = fix.componentInstance.state; - const advFilteringState = '{"advancedFiltering":{"filteringOperands":[{"fieldName":"Age","condition":{"name":"greaterThan","isUnary":false,"iconName":"filter_greater_than"},"searchVal":25,"ignoreCase":true},{"fieldName":"ID","condition":{"name":"greaterThan","isUnary":false,"iconName":"filter_greater_than"},"searchVal":"3","ignoreCase":true}],"operator":0,"type":1}}'; + const advFilteringState = '{"advancedFiltering":{"filteringOperands":[{"fieldName":"Age","condition":{"name":"greaterThan","isUnary":false,"iconName":"filter_greater_than"},"searchVal":25,"ignoreCase":true,"conditionName":"greaterThan"},{"fieldName":"ID","condition":{"name":"greaterThan","isUnary":false,"iconName":"filter_greater_than"},"searchVal":"3","ignoreCase":true,"conditionName":"greaterThan"}],"operator":0,"type":1}}'; const initialState = '{"advancedFiltering":{}}'; let gridState = state.getState(true, 'advancedFiltering'); @@ -345,30 +345,32 @@ class HelperFunctions { - - + @for (c of columns; track c) { + + + } `, - imports: [IgxTreeGridComponent, IgxColumnComponent, IgxPaginatorComponent, IgxGridStateDirective, NgFor] + imports: [IgxTreeGridComponent, IgxColumnComponent, IgxPaginatorComponent, IgxGridStateDirective] }) export class IgxTreeGridTreeDataTestComponent { @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; diff --git a/projects/igniteui-angular/src/lib/grids/summaries/summary-cell.component.html b/projects/igniteui-angular/src/lib/grids/summaries/summary-cell.component.html index c6dadcaa324..f8f6c00aa31 100644 --- a/projects/igniteui-angular/src/lib/grids/summaries/summary-cell.component.html +++ b/projects/igniteui-angular/src/lib/grids/summaries/summary-cell.component.html @@ -1,17 +1,14 @@ - +@if (hasSummary) { - - - -
- - {{ translateSummary(summary) }} - - {{ - formatSummaryResult(summary) - }} - -
-
-
+} + + @for (summary of summaryResults; track trackSummaryResult(summary)) { +
+ {{ translateSummary(summary) }} + + {{ formatSummaryResult(summary) }} + +
+ } +
diff --git a/projects/igniteui-angular/src/lib/grids/summaries/summary-cell.component.ts b/projects/igniteui-angular/src/lib/grids/summaries/summary-cell.component.ts index 9ca2d072e5f..8f4da37f72e 100644 --- a/projects/igniteui-angular/src/lib/grids/summaries/summary-cell.component.ts +++ b/projects/igniteui-angular/src/lib/grids/summaries/summary-cell.component.ts @@ -4,15 +4,16 @@ import { IgxSummaryResult } from './grid-summary'; import { GridColumnDataType } from '../../data-operations/data-util'; -import { formatCurrency, formatDate, formatNumber, formatPercent, getLocaleCurrencyCode, getLocaleCurrencySymbol, NgIf, NgTemplateOutlet, NgFor } from '@angular/common'; +import { formatCurrency, formatDate, formatNumber, formatPercent, getLocaleCurrencyCode, getLocaleCurrencySymbol, NgTemplateOutlet } from '@angular/common'; import { ISelectionNode } from '../common/types'; import { ColumnType } from '../common/grid.interface'; +import { trackByIdentity } from '../../core/utils'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-grid-summary-cell', templateUrl: './summary-cell.component.html', - imports: [NgIf, NgTemplateOutlet, NgFor] + imports: [NgTemplateOutlet] }) export class IgxSummaryCellComponent { @@ -114,6 +115,9 @@ export class IgxSummaryCellComponent { this.column.pipeArgs.display : getLocaleCurrencySymbol(this.grid.locale); } + /** cached single summary res after filter resets collection */ + protected trackSummaryResult = trackByIdentity; + public translateSummary(summary: IgxSummaryResult): string { return this.grid.resourceStrings[`igx_grid_summary_${summary.key}`] || summary.label; } diff --git a/projects/igniteui-angular/src/lib/grids/summaries/summary-row.component.html b/projects/igniteui-angular/src/lib/grids/summaries/summary-row.component.html index 6a07570631a..9bcc77428bb 100644 --- a/projects/igniteui-angular/src/lib/grids/summaries/summary-row.component.html +++ b/projects/igniteui-angular/src/lib/grids/summaries/summary-row.component.html @@ -1,15 +1,15 @@ - - +@if (summaries.size) { + @if (grid.summariesMargin) {
-
- + } + @if (pinnedColumns.length > 0 && grid.isPinningToStart) { - + } - + @if (pinnedColumns.length > 0 && !grid.isPinningToStart) { - -
+ } +} - + } diff --git a/projects/igniteui-angular/src/lib/grids/summaries/summary-row.component.ts b/projects/igniteui-angular/src/lib/grids/summaries/summary-row.component.ts index dfe6211477b..6628188091d 100644 --- a/projects/igniteui-angular/src/lib/grids/summaries/summary-row.component.ts +++ b/projects/igniteui-angular/src/lib/grids/summaries/summary-row.component.ts @@ -17,7 +17,8 @@ import { IgxGridForOfDirective } from '../../directives/for-of/for_of.directive' import { IgxForOfSyncService } from '../../directives/for-of/for_of.sync.service'; import { ColumnType, GridType, IGX_GRID_BASE } from '../common/grid.interface'; import { IgxGridNotGroupedPipe } from '../common/pipes'; -import { NgIf, NgTemplateOutlet, NgFor } from '@angular/common'; +import { NgTemplateOutlet } from '@angular/common'; +import { trackByIdentity } from '../../core/utils'; @Component({ @@ -25,7 +26,7 @@ import { NgIf, NgTemplateOutlet, NgFor } from '@angular/common'; selector: 'igx-grid-summary-row', templateUrl: './summary-row.component.html', providers: [IgxForOfSyncService], - imports: [NgIf, NgTemplateOutlet, IgxGridForOfDirective, IgxSummaryCellComponent, NgFor, IgxGridNotGroupedPipe] + imports: [NgTemplateOutlet, IgxGridForOfDirective, IgxSummaryCellComponent, IgxGridNotGroupedPipe] }) export class IgxSummaryRowComponent implements DoCheck { @@ -118,4 +119,7 @@ export class IgxSummaryRowComponent implements DoCheck { $implicit: row }; } + + /** state persistence switching all pinned columns resets collection */ + protected trackPinnedColumn = trackByIdentity; } diff --git a/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-advanced-filtering.component.html b/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-advanced-filtering.component.html index 57869977324..6a517c59ef4 100644 --- a/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-advanced-filtering.component.html +++ b/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-advanced-filtering.component.html @@ -8,6 +8,10 @@ - {{ grid?.resourceStrings.igx_grid_toolbar_advanced_filtering_button_label }} - ({{ numberOfColumns }}) + @if (!ref.textContent.trim()) { + {{ grid?.resourceStrings.igx_grid_toolbar_advanced_filtering_button_label }} + } + @if (grid?.advancedFilteringExpressionsTree) { + ({{ numberOfColumns }}) + } diff --git a/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-advanced-filtering.component.ts b/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-advanced-filtering.component.ts index 99af7c94396..ea831db5d7d 100644 --- a/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-advanced-filtering.component.ts +++ b/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-advanced-filtering.component.ts @@ -2,11 +2,10 @@ import { AfterViewInit, Component, Inject, Input, OnInit } from '@angular/core'; import { IgxToolbarToken } from './token'; import { OverlaySettings } from '../../services/overlay/utilities'; import { IgxIconComponent } from '../../icon/icon.component'; -import { NgIf } from '@angular/common'; import { IgxRippleDirective } from '../../directives/ripple/ripple.directive'; import { IgxButtonDirective } from '../../directives/button/button.directive'; -import { FilteringExpressionsTree, IFilteringExpressionsTree } from '../../data-operations/filtering-expressions-tree'; -import { IFilteringExpression } from '../../data-operations/filtering-expression.interface'; +import { IFilteringExpressionsTree } from '../../data-operations/filtering-expressions-tree'; +import { isTree } from '../../data-operations/expressions-tree-util'; /* blazorElement */ /* wcElementTag: igc-grid-toolbar-advanced-filtering */ @@ -30,7 +29,7 @@ import { IFilteringExpression } from '../../data-operations/filtering-expression @Component({ selector: 'igx-grid-toolbar-advanced-filtering', templateUrl: './grid-toolbar-advanced-filtering.component.html', - imports: [IgxButtonDirective, IgxRippleDirective, IgxIconComponent, NgIf] + imports: [IgxButtonDirective, IgxRippleDirective, IgxIconComponent] }) export class IgxGridToolbarAdvancedFilteringComponent implements OnInit { protected numberOfColumns: number; @@ -64,10 +63,10 @@ export class IgxGridToolbarAdvancedFilteringComponent implements OnInit { const columnNames = []; if (!filteringTree) return columnNames; filteringTree.filteringOperands.forEach((expr) => { - if (expr instanceof FilteringExpressionsTree) { + if (isTree(expr)) { columnNames.push(...this.extractUniqueFieldNamesFromFilterTree(expr)); } else { - columnNames.push((expr as IFilteringExpression).fieldName); + columnNames.push(expr.fieldName); } }); return [...new Set(columnNames)]; diff --git a/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-exporter.component.html b/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-exporter.component.html index d74fb7a1a14..adbc7c8cf71 100644 --- a/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-exporter.component.html +++ b/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-exporter.component.html @@ -5,31 +5,42 @@ - - {{ grid?.resourceStrings.igx_grid_toolbar_exporter_button_label }} - + @if (!ref.textContent.trim()) { + + {{ grid?.resourceStrings.igx_grid_toolbar_exporter_button_label }} + + }
    -
  • - - - - - {{ grid?.resourceStrings.igx_grid_toolbar_exporter_excel_entry_text}} - -
  • + @if (exportExcel) { +
  • + + + + @if (!excel.childNodes.length) { + + {{ grid?.resourceStrings.igx_grid_toolbar_exporter_excel_entry_text}} + + } +
  • + } -
  • - - - - - {{ grid?.resourceStrings.igx_grid_toolbar_exporter_csv_entry_text }} -
  • + @if (exportCSV) { +
  • + + + + @if (!csv.childNodes.length) { + + {{ grid?.resourceStrings.igx_grid_toolbar_exporter_csv_entry_text }} + + } +
  • + }
diff --git a/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-exporter.component.ts b/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-exporter.component.ts index fd6255e398e..a26a42dca40 100644 --- a/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-exporter.component.ts +++ b/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-exporter.component.ts @@ -13,7 +13,6 @@ import { import { IgxToggleDirective } from '../../directives/toggle/toggle.directive'; import { GridType } from '../common/grid.interface'; import { IgxToolbarToken } from './token'; -import { NgIf } from '@angular/common'; import { IgxIconComponent } from '../../icon/icon.component'; import { IgxRippleDirective } from '../../directives/ripple/ripple.directive'; import { IgxButtonDirective } from '../../directives/button/button.directive'; @@ -51,7 +50,7 @@ export interface IgxExporterEvent { @Component({ selector: 'igx-grid-toolbar-exporter', templateUrl: './grid-toolbar-exporter.component.html', - imports: [IgxButtonDirective, IgxRippleDirective, IgxIconComponent, NgIf, IgxToggleDirective, IgxExcelTextDirective, IgxCSVTextDirective] + imports: [IgxButtonDirective, IgxRippleDirective, IgxIconComponent, IgxToggleDirective, IgxExcelTextDirective, IgxCSVTextDirective] }) export class IgxGridToolbarExporterComponent extends BaseToolbarDirective { diff --git a/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-hiding.component.html b/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-hiding.component.html index 5f330d56e6b..9794e20a475 100644 --- a/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-hiding.component.html +++ b/projects/igniteui-angular/src/lib/grids/toolbar/grid-toolbar-hiding.component.html @@ -1,4 +1,4 @@ - +@if (grid.rendered$ | async) {
-
+} @@ -252,25 +273,39 @@ -
- {{grid.resourceStrings.igx_grid_required_validation_error}} -
-
- {{grid.resourceStrings.igx_grid_min_length_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.minlength.requiredLength }} -
-
- {{grid.resourceStrings.igx_grid_max_length_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.maxlength.requiredLength }} -
-
- {{grid.resourceStrings.igx_grid_min_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.min.min }} -
-
- {{grid.resourceStrings.igx_grid_max_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.max.max }} -
-
- {{grid.resourceStrings.igx_grid_email_validation_error }} -
-
- {{grid.resourceStrings.igx_grid_pattern_validation_error}} -
+ @if (formGroup?.get(column?.field).errors?.['required']) { +
+ {{grid.resourceStrings.igx_grid_required_validation_error}} +
+ } + @if (formGroup?.get(column?.field).errors?.['minlength']) { +
+ {{grid.resourceStrings.igx_grid_min_length_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.minlength.requiredLength }} +
+ } + @if (formGroup?.get(column?.field).errors?.['maxlength']) { +
+ {{grid.resourceStrings.igx_grid_max_length_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.maxlength.requiredLength }} +
+ } + @if (formGroup?.get(column?.field).errors?.['min']) { +
+ {{grid.resourceStrings.igx_grid_min_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.min.min }} +
+ } + @if (formGroup?.get(column?.field).errors?.['max']) { +
+ {{grid.resourceStrings.igx_grid_max_validation_error | igxStringReplace:'{0}':formGroup.get(column.field).errors.max.max }} +
+ } + @if (formGroup?.get(column?.field).errors?.['email']) { +
+ {{grid.resourceStrings.igx_grid_email_validation_error }} +
+ } + @if (formGroup?.get(column?.field).errors?.['pattern']) { +
+ {{grid.resourceStrings.igx_grid_pattern_validation_error}} +
+ }
diff --git a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-cell.component.ts b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-cell.component.ts index 062dc011059..e27d68065ba 100644 --- a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-cell.component.ts +++ b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-cell.component.ts @@ -3,7 +3,7 @@ import { Component, Input } from '@angular/core'; -import { NgIf, NgClass, NgStyle, NgTemplateOutlet, DecimalPipe, PercentPipe, CurrencyPipe, DatePipe } from '@angular/common'; +import { NgClass, NgStyle, NgTemplateOutlet, DecimalPipe, PercentPipe, CurrencyPipe, DatePipe } from '@angular/common'; import { HammerGesturesManager } from '../../core/touch'; import { IgxGridExpandableCellComponent } from '../grid/expandable-cell.component'; @@ -34,7 +34,6 @@ import { IgxTextSelectionDirective } from '../../directives/text-selection/text- templateUrl: 'tree-cell.component.html', providers: [HammerGesturesManager], imports: [ - NgIf, NgClass, NgStyle, NgTemplateOutlet, diff --git a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-row.component.html b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-row.component.html index 0c253b596be..05bbb9e49c4 100644 --- a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-row.component.html +++ b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-row.component.html @@ -6,87 +6,89 @@
- -
- -
-
- -
- + @if (rowDraggable) { +
+ +
+ } + @if (showRowSelectors) { +
+ + +
+ } + @if (pinnedColumns.length > 0 && grid.isPinningToStart) { + + } + + + + -
-
- - - - - - - - - - - + + + + + - + @if (pinnedColumns.length > 0 && !grid.isPinningToStart) { + + } - - - +
- + @for (col of pinnedColumns | igxNotGrouped; track trackPinnedColumn(col)) { - + - + } 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 7c3be816245..e84fa6ae9a5 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 @@ -7,14 +7,14 @@ import { IgxTreeGridCellComponent } from './tree-cell.component'; import { IgxGridCellComponent } from '../cell.component'; import { IgxGridForOfDirective } from '../../directives/for-of/for_of.directive'; import { IgxRowDragDirective } from '../row-drag.directive'; -import { NgTemplateOutlet, NgIf, NgClass, NgStyle, NgFor } from '@angular/common'; +import { NgTemplateOutlet, NgClass, NgStyle } from '@angular/common'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'igx-tree-grid-row', templateUrl: 'tree-grid-row.component.html', providers: [{ provide: IgxRowDirective, useExisting: forwardRef(() => IgxTreeGridRowComponent) }], - imports: [NgTemplateOutlet, NgIf, IgxRowDragDirective, IgxGridForOfDirective, IgxGridCellComponent, NgClass, NgStyle, IgxTreeGridCellComponent, IgxCheckboxComponent, NgFor, IgxGridNotGroupedPipe, IgxGridCellStylesPipe, IgxGridCellStyleClassesPipe, IgxGridDataMapperPipe, IgxGridTransactionStatePipe] + imports: [NgTemplateOutlet, IgxRowDragDirective, IgxGridForOfDirective, IgxGridCellComponent, NgClass, NgStyle, IgxTreeGridCellComponent, IgxCheckboxComponent, IgxGridNotGroupedPipe, IgxGridCellStylesPipe, IgxGridCellStyleClassesPipe, IgxGridDataMapperPipe, IgxGridTransactionStatePipe] }) export class IgxTreeGridRowComponent extends IgxRowDirective implements DoCheck { @ViewChildren('treeCell') diff --git a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-selection.spec.ts b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-selection.spec.ts index a4b764972c2..f6d5bc3ccd3 100644 --- a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-selection.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-selection.spec.ts @@ -1398,16 +1398,19 @@ describe('IgxTreeGrid - Selection #tGrid', () => { expressionTree.filteringOperands = [ { condition: IgxNumberFilteringOperand.instance().condition('doesNotEqual'), + conditionName: 'doesNotEqual', fieldName: 'ID', searchVal: 711 }, { condition: IgxNumberFilteringOperand.instance().condition('doesNotEqual'), + conditionName: 'doesNotEqual', fieldName: 'ID', searchVal: 998 }, { condition: IgxNumberFilteringOperand.instance().condition('doesNotEqual'), + conditionName: 'doesNotEqual', fieldName: 'ID', searchVal: 299 } @@ -1448,16 +1451,19 @@ describe('IgxTreeGrid - Selection #tGrid', () => { expressionTree.filteringOperands = [ { condition: IgxNumberFilteringOperand.instance().condition('doesNotEqual'), + conditionName: 'doesNotEqual', fieldName: 'ID', searchVal: 711 }, { condition: IgxNumberFilteringOperand.instance().condition('doesNotEqual'), + conditionName: 'doesNotEqual', fieldName: 'ID', searchVal: 998 }, { condition: IgxNumberFilteringOperand.instance().condition('doesNotEqual'), + conditionName: 'doesNotEqual', fieldName: 'ID', searchVal: 299 } @@ -1500,6 +1506,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { expressionTree.filteringOperands = [ { condition: IgxNumberFilteringOperand.instance().condition('doesNotEqual'), + conditionName: 'doesNotEqual', fieldName: 'ID', searchVal: 957 }, @@ -1544,16 +1551,19 @@ describe('IgxTreeGrid - Selection #tGrid', () => { expressionTree.filteringOperands = [ { condition: IgxNumberFilteringOperand.instance().condition('doesNotEqual'), + conditionName: 'doesNotEqual', fieldName: 'ID', searchVal: 711 }, { condition: IgxNumberFilteringOperand.instance().condition('doesNotEqual'), + conditionName: 'doesNotEqual', fieldName: 'ID', searchVal: 998 }, { condition: IgxNumberFilteringOperand.instance().condition('doesNotEqual'), + conditionName: 'doesNotEqual', fieldName: 'ID', searchVal: 299 } @@ -1615,11 +1625,13 @@ describe('IgxTreeGrid - Selection #tGrid', () => { expressionTree.filteringOperands = [ { condition: IgxNumberFilteringOperand.instance().condition('doesNotEqual'), + conditionName: 'doesNotEqual', fieldName: 'ID', searchVal: 711 }, { condition: IgxNumberFilteringOperand.instance().condition('doesNotEqual'), + conditionName: 'doesNotEqual', fieldName: 'ID', searchVal: 998 } diff --git a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.html b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.html index 23b405b715d..5983eb81ffa 100644 --- a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.html +++ b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.html @@ -20,33 +20,40 @@ (dragStop)="selectionService.dragMode = $event" [attr.aria-activedescendant]="activeDescendant" [attr.role]="dataView.length ? null : 'row'" (dragScroll)="dragScroll($event)" [igxGridDragSelect]="selectionService.dragMode" [style.height.px]='totalHeight' [style.width.px]='calcWidth' #tbody (scroll)='preventContainerScroll($event)'> - - + @if (moving && columnInDrag && pinnedColumns.length <= 0) { + + } + @if (moving && columnInDrag && pinnedColumns.length > 0) { + + } - -
- - - - -
-
+ @if (data + | treeGridTransaction:pipeTrigger + | visibleColumns:hasVisibleColumns + | treeGridNormalizeRecord:pipeTrigger + | treeGridAddRow:true:pipeTrigger + | gridRowPinning:id:true:pipeTrigger + | treeGridFiltering:filteringExpressionsTree:filterStrategy:advancedFilteringExpressionsTree:pipeTrigger:filteringPipeTrigger:true + | treeGridSorting:sortingExpressions:treeGroupArea?.expressions:sortStrategy:pipeTrigger:true; as pinnedData + ) { + @if (pinnedData.length > 0) { +
+ @for (rowData of pinnedData; track trackPinnedRowData(rowData); let rowIndex = $index) { + + + } +
+ } + }
- + @if (shouldOverlayLoading) { + + + }
- -
+ @if (moving && columnInDrag) { + + } +
@@ -114,12 +125,14 @@
- - + (keydown)="navigation.summaryNav($event)" [attr.aria-activedescendant]="activeDescendant"> + @if (hasSummarizedColumns && rootSummariesEnabled) { + + + }
@@ -142,18 +155,22 @@ {{emptyFilteredGridMessage}} - - - + @if (showAddButton) { + + + + } {{emptyGridMessage}} - - - + @if (showAddButton) { + + + + } @@ -170,13 +187,15 @@
-
-
- - +@if (rowEditable) { +
+
+ + +
-
+} {{ this.resourceStrings.igx_grid_row_edit_text | igxStringReplace:'{0}':rowChangesCount.toString() | igxStringReplace:'{1}':hiddenColumnsCount.toString() }} @@ -209,7 +228,9 @@ - +@if (colResizingService.showResizer) { + +}
@if (platform.isElements) { 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 9aa620cb3fd..a36bdc1af15 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 @@ -23,7 +23,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, booleanAttribute } from '@angular/core'; -import { DOCUMENT, NgIf, NgClass, NgFor, NgTemplateOutlet, NgStyle } from '@angular/common'; +import { DOCUMENT, NgClass, NgTemplateOutlet, NgStyle } from '@angular/common'; import { IgxTreeGridAPIService } from './tree-grid-api.service'; import { IgxGridBaseDirective } from '../grid-base.directive'; @@ -133,8 +133,6 @@ let NEXT_ID = 0; IgxForOfScrollSyncService ], imports: [ - NgIf, - NgFor, NgClass, NgStyle, NgTemplateOutlet, @@ -1076,6 +1074,13 @@ export class IgxTreeGridComponent extends IgxGridBaseDirective implements GridTy return this.treeGroupArea ? this.getComputedHeight(this.treeGroupArea.nativeElement) : 0; } + /** {@link triggerPipes} will re-create pinnedData on CRUD operations */ + protected trackPinnedRowData(record: ITreeGridRecord) { + // TODO FIX: pipeline data doesn't match end interface (¬_¬ ) + // return record.key || (record as any).rowID; + return record; + } + /** * @description A recursive way to deselect all selected children of a given record * @param recordID ID of the record whose children to deselect diff --git a/projects/igniteui-angular/src/lib/icon/icon.component.ts b/projects/igniteui-angular/src/lib/icon/icon.component.ts index 8186a6d85eb..dbd531ce68a 100644 --- a/projects/igniteui-angular/src/lib/icon/icon.component.ts +++ b/projects/igniteui-angular/src/lib/icon/icon.component.ts @@ -14,7 +14,6 @@ import type { IconReference } from "./types"; import { filter, takeUntil } from "rxjs/operators"; import { Subject } from "rxjs"; import { SafeHtml } from "@angular/platform-browser"; -import { NgIf, NgTemplateOutlet } from "@angular/common"; /** * Icon provides a way to include material icons to markup diff --git a/projects/igniteui-angular/src/lib/icon/icon.service.ts b/projects/igniteui-angular/src/lib/icon/icon.service.ts index 4bc94e2e006..e6b1600fc27 100644 --- a/projects/igniteui-angular/src/lib/icon/icon.service.ts +++ b/projects/igniteui-angular/src/lib/icon/icon.service.ts @@ -64,7 +64,7 @@ export class IgxIconService { @Optional() private _sanitizer: DomSanitizer, @Optional() private _httpClient: HttpClient, @Optional() private _platformUtil: PlatformUtil, - @Optional() @Inject(THEME_TOKEN) private _themeToken: ThemeToken, + @Optional() @Inject(THEME_TOKEN) private _themeToken: ThemeToken | undefined, @Optional() @Inject(DestroyRef) private _destroyRef: DestroyRef, @Optional() @Inject(DOCUMENT) protected document: Document, ) { @@ -72,11 +72,11 @@ export class IgxIconService { this.iconLoaded = this._iconLoaded.asObservable(); this.setFamily(this._defaultFamily.name, this._defaultFamily.meta); - const { unsubscribe } = this._themeToken?.onChange((theme) => { + const themeChange = this._themeToken?.onChange((theme) => { this.setRefsByTheme(theme); }); - this._destroyRef.onDestroy(() => unsubscribe); + this._destroyRef.onDestroy(() => themeChange?.unsubscribe()); if (this._platformUtil?.isBrowser) { this._domParser = new DOMParser(); diff --git a/projects/igniteui-angular/src/lib/input-group/input-group.component.html b/projects/igniteui-angular/src/lib/input-group/input-group.component.html index 64bd7ae925d..8b5a258edfa 100644 --- a/projects/igniteui-angular/src/lib/input-group/input-group.component.html +++ b/projects/igniteui-angular/src/lib/input-group/input-group.component.html @@ -1,6 +1,10 @@ -
+@if (isTypeBox) { +
+ +
+} @else { -
+}
@@ -19,40 +23,44 @@ - - - + @if (isFileType) { + + + + } -
- {{ fileNames }} -
+ @if (isFileType) { +
+ {{ fileNames }} +
+ }
- - - + @if (isFileType && isFilled) { + + + + } @@ -84,7 +92,9 @@
-
+ @if (hasBorder) { +
+ }
@@ -108,7 +118,9 @@
-
+ @if (hasBorder) { +
+ }
@@ -132,21 +144,18 @@ - - + @switch (theme) { + @case ('bootstrap') { - - - + } + @case ('fluent') { - - - + } + @case ('indigo') { - - - + } + @default { - - + } + } diff --git a/projects/igniteui-angular/src/lib/input-group/input-group.component.ts b/projects/igniteui-angular/src/lib/input-group/input-group.component.ts index 3c1fbcd3a2d..4e07fcc07dc 100644 --- a/projects/igniteui-angular/src/lib/input-group/input-group.component.ts +++ b/projects/igniteui-angular/src/lib/input-group/input-group.component.ts @@ -1,4 +1,4 @@ -import { DOCUMENT, NgIf, NgTemplateOutlet, NgClass, NgSwitch, NgSwitchCase, NgSwitchDefault } from '@angular/common'; +import { DOCUMENT, NgTemplateOutlet, NgClass } from '@angular/common'; import { ChangeDetectorRef, Component, @@ -32,7 +32,7 @@ import { IgxTheme, THEME_TOKEN, ThemeToken } from '../services/theme/theme.token selector: 'igx-input-group', templateUrl: 'input-group.component.html', providers: [{ provide: IgxInputGroupBase, useExisting: IgxInputGroupComponent }], - imports: [NgIf, NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, NgClass, IgxSuffixDirective, IgxIconComponent, NgSwitch, NgSwitchCase, NgSwitchDefault] + imports: [NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, NgClass, IgxSuffixDirective, IgxIconComponent] }) export class IgxInputGroupComponent implements IgxInputGroupBase { /** diff --git a/projects/igniteui-angular/src/lib/list/list-item.component.html b/projects/igniteui-angular/src/lib/list/list-item.component.html index a4f8f728522..ef538fa89f4 100644 --- a/projects/igniteui-angular/src/lib/list/list-item.component.html +++ b/projects/igniteui-angular/src/lib/list/list-item.component.html @@ -1,15 +1,19 @@ -
- - -
- -
- - -
+@if (!isHeader && list.listItemLeftPanningTemplate) { +
+ + +
+} + +@if (!isHeader && list.listItemRightPanningTemplate) { +
+ + +
+} @@ -33,15 +37,15 @@
- +@if (isHeader) { - +} - +@if (!isHeader) {
-
+} diff --git a/projects/igniteui-angular/src/lib/list/list-item.component.ts b/projects/igniteui-angular/src/lib/list/list-item.component.ts index 6af120b0db6..6d4eb22a51d 100644 --- a/projects/igniteui-angular/src/lib/list/list-item.component.ts +++ b/projects/igniteui-angular/src/lib/list/list-item.component.ts @@ -18,7 +18,7 @@ import { import { HammerGesturesManager } from '../core/touch'; import { rem } from '../core/utils'; -import { NgIf, NgTemplateOutlet } from '@angular/common'; +import { NgTemplateOutlet } from '@angular/common'; /** * The Ignite UI List Item component is a container intended for row items in the Ignite UI for Angular List component. @@ -39,7 +39,7 @@ import { NgIf, NgTemplateOutlet } from '@angular/common'; selector: 'igx-list-item', templateUrl: 'list-item.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - imports: [NgIf, NgTemplateOutlet] + imports: [NgTemplateOutlet] }) export class IgxListItemComponent implements IListChild { /** diff --git a/projects/igniteui-angular/src/lib/list/list.component.html b/projects/igniteui-angular/src/lib/list/list.component.html index 7b2c0a438d6..46bafca512b 100644 --- a/projects/igniteui-angular/src/lib/list/list.component.html +++ b/projects/igniteui-angular/src/lib/list/list.component.html @@ -12,7 +12,7 @@
- +@if (!children || children.length === 0 || isLoading) { - +} diff --git a/projects/igniteui-angular/src/lib/list/list.component.ts b/projects/igniteui-angular/src/lib/list/list.component.ts index 492b5e1e2a5..32b4d00b75d 100644 --- a/projects/igniteui-angular/src/lib/list/list.component.ts +++ b/projects/igniteui-angular/src/lib/list/list.component.ts @@ -1,4 +1,4 @@ -import { NgIf, NgTemplateOutlet } from '@angular/common'; +import { NgTemplateOutlet } from '@angular/common'; import { Component, ContentChild, @@ -146,7 +146,7 @@ export class IgxListLineSubTitleDirective { selector: 'igx-list', templateUrl: 'list.component.html', providers: [{ provide: IgxListBaseDirective, useExisting: IgxListComponent }], - imports: [NgIf, NgTemplateOutlet] + imports: [NgTemplateOutlet] }) export class IgxListComponent extends IgxListBaseDirective { /** diff --git a/projects/igniteui-angular/src/lib/navbar/navbar.component.html b/projects/igniteui-angular/src/lib/navbar/navbar.component.html index 67191d51d76..772a0a5e3f7 100644 --- a/projects/igniteui-angular/src/lib/navbar/navbar.component.html +++ b/projects/igniteui-angular/src/lib/navbar/navbar.component.html @@ -1,19 +1,20 @@

[alignment]="properties.alignment" [disabled]="properties.disabled" > - @for(city of cities; track city){ + @for (city of cities; track city){ { this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } private selectionMap = new Map( diff --git a/src/app/calendar/calendar.sample.html b/src/app/calendar/calendar.sample.html index 57ef6796957..eb41b90a0d9 100644 --- a/src/app/calendar/calendar.sample.html +++ b/src/app/calendar/calendar.sample.html @@ -53,7 +53,7 @@ - @for(option of ['narrow', 'short', 'long']; track option) { + @for (option of ['narrow', 'short', 'long']; track option) {
@@ -81,8 +91,12 @@
{{cell.value | currency:'USD':'symbol':'1.4-4'}} - trending_up - trending_down + @if (trends.positive(cell.row.data)) { + trending_up + } + @if (trends.negative(cell.row.data)) { + trending_down + }
@@ -92,10 +106,12 @@ - - + @for (c of columns; track c) { + + + }
@@ -113,8 +129,12 @@
{{cell.value | currency:'USD':'symbol':'1.4-4'}} - trending_up - trending_down + @if (trends.positive(cell.row.data)) { + trending_up + } + @if (trends.negative(cell.row.data)) { + trending_down + }
@@ -124,10 +144,12 @@ - - + @for (c of columns; track c) { + + + }
@@ -146,8 +168,12 @@
{{cell.value | currency:'USD':'symbol':'1.4-4'}} - trending_up - trending_down + @if (trends.positive(cell.row.data)) { + trending_up + } + @if (trends.negative(cell.row.data)) { + trending_down + }
@@ -157,10 +183,12 @@ - - + @for (c of columns; track c) { + + + }
diff --git a/src/app/dockmanager-grid/dockmanager-grid.sample.ts b/src/app/dockmanager-grid/dockmanager-grid.sample.ts index a69d35d6db6..d43818f503a 100644 --- a/src/app/dockmanager-grid/dockmanager-grid.sample.ts +++ b/src/app/dockmanager-grid/dockmanager-grid.sample.ts @@ -5,7 +5,7 @@ import { defineCustomElements } from 'igniteui-dockmanager/loader'; import { Subject } from 'rxjs'; import { first, takeUntil } from 'rxjs/operators'; -import { CommonModule, NgFor } from '@angular/common'; +import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { SignalRService } from './signal-r.service'; @@ -48,7 +48,6 @@ export class DockSlotComponent implements AfterViewInit, OnDestroy { styleUrls: ['dockmanager-grid.sample.scss'], templateUrl: 'dockmanager-grid.sample.html', imports: [ - NgFor, CommonModule, FormsModule, IGX_GRID_DIRECTIVES, diff --git a/src/app/drag-drop/drag-drop.sample.html b/src/app/drag-drop/drag-drop.sample.html index 1fcf609e085..7166d42a69b 100644 --- a/src/app/drag-drop/drag-drop.sample.html +++ b/src/app/drag-drop/drag-drop.sample.html @@ -5,8 +5,12 @@

No ghost dragging:

- Drag me - Weeeee + @if (!draggedElem) { + Drag me + } + @if (draggedElem) { + Weeeee + } edit
@@ -14,8 +18,12 @@

No ghost dragging:

- Drag me - Weeeee + @if (!draggedElem) { + Drag me + } + @if (draggedElem) { + Weeeee + } edit
@@ -28,12 +36,20 @@

Ghost and base templating:

- Drag me + @if (!customDragged) { + Drag me + }
- Weeeee - It's ok here - Pls no + @if (!ghostInDropArea) { + Weeeee + } + @if (ghostInDropArea && friendlyArea) { + It's ok here + } + @if (ghostInDropArea && !friendlyArea) { + Pls no + }
@@ -43,12 +59,20 @@

Ghost and base templating:

- Drag me + @if (!customDraggedScroll) { + Drag me + }
- Weeeee - It's ok here - Pls no + @if (!ghostInDropArea) { + Weeeee + } + @if (ghostInDropArea && friendlyArea) { + It's ok here + } + @if (ghostInDropArea && !friendlyArea) { + Pls no + }
@@ -94,18 +118,22 @@

Nested Drag Handle:

drag_indicator Movies list
-
-
- drag_indicator - {{category.text}} -
-
+ @for (category of categoriesNotes; track category) { +
drag_indicator - {{note.text}} + {{category.text}}
+ @for (note of getCategoryMovies(category.text); track note) { +
+
+ drag_indicator + {{note.text}} +
+
+ }
-
+ }
@@ -140,8 +168,12 @@

Playground:

No ghost dragging:

- Drag me - Weeeee + @if (!draggedElem) { + Drag me + } + @if (draggedElem) { + Weeeee + }
@@ -151,9 +183,15 @@

Playground:

- Weeeee - It's ok here - Pls no + @if (!ghostInDropArea) { + Weeeee + } + @if (ghostInDropArea && friendlyArea) { + It's ok here + } + @if (ghostInDropArea && !friendlyArea) { + Pls no + }
@@ -161,20 +199,24 @@

Playground:

-
- Drag me + @if (!customDraggedAnim) { + Drag me + }
-
- Drag me + @if (!customDraggedAnimScroll) { + Drag me + }
@@ -186,7 +228,9 @@

Playground:

- Drag me + @if (!customDraggedAnimXY) { + Drag me + }
@@ -199,7 +243,9 @@

Playground:

- Drag me + @if (!customDraggedAnimHostXY) { + Drag me + }
@@ -216,12 +262,14 @@

Playground:

Wishlist reorder with transitions:

-
- {{item.text}} -
+ @for (item of listNotes; track item; let itemIndex = $index) { +
+ {{item.text}} +
+ }
@@ -231,32 +279,37 @@

Wishlist reorder with transitions:

Multi selection row drag with custom ghost:

From
-
+ @for (item of sourceRows; track item) { +
{{ item.name }} -
+
+ }
To
-
- {{ item.name }} -
+ @for (item of targetRows; track item) { +
+ {{ item.name }} +
+ }
- - {{ row.name }} - + @for (row of selectedRows; track row) { + + {{ row.name }} + + }
@@ -267,14 +320,16 @@

Multi selection row drag with custom ghost:

Drag a suspect inside or outside the cage:

-
- {{elem.value}} -
+ @for (elem of draggableElems; track elem) { +
+ {{elem.value}} +
+ }
{ this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } public ngOnInit() { diff --git a/src/app/expansion-panel/expansion-panel-sample.ts b/src/app/expansion-panel/expansion-panel-sample.ts index 8729020f671..ba8721e2a48 100644 --- a/src/app/expansion-panel/expansion-panel-sample.ts +++ b/src/app/expansion-panel/expansion-panel-sample.ts @@ -51,14 +51,14 @@ export class ExpansionPanelSampleComponent { ) { this.propertyChangeService.setPanelConfig(this.panelConfig); - const { unsubscribe } = + const propertyChange = this.propertyChangeService.propertyChanges.subscribe( (properties) => { this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } private iconPositionMap = new Map([ 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 39d1d01b725..a3505b0ba6d 100644 --- a/src/app/gird-cell-styling/grid-cell-styling.sample.html +++ b/src/app/gird-cell-styling/grid-cell-styling.sample.html @@ -19,17 +19,19 @@ width="80%" height="600px" > - - + @for (c of columns; track c) { + + + }

Grid sample with rowClasses property applied based on row ID

Grid sample with rowClasses property applied based on r [pinning]='pinningConfig' (cellClick)="selectedRowId = $event.cell.row.key" > - - + @for (c of columns; track c) { + + + } @@ -71,16 +75,18 @@

Grid sample with rowClasses property applied based on r width="80%" height="600px" > - - + @for (c of columns; track c) { + + + }

diff --git a/src/app/gird-cell-styling/grid-cell-styling.sample.ts b/src/app/gird-cell-styling/grid-cell-styling.sample.ts index 0cae74c0fc4..07c2a00de5b 100644 --- a/src/app/gird-cell-styling/grid-cell-styling.sample.ts +++ b/src/app/gird-cell-styling/grid-cell-styling.sample.ts @@ -1,5 +1,5 @@ import { Component, ViewChild, OnInit } from '@angular/core'; -import { NgFor, JsonPipe } from '@angular/common'; +import { JsonPipe } from '@angular/common'; import { SAMPLE_DATA, HIERARCHICAL_SAMPLE_DATA } from '../shared/sample-data'; import { IgxActionStripComponent, IgxButtonDirective, IgxColumnComponent, IgxGridComponent, IgxGridEditingActionsComponent, IgxGridPinningActionsComponent, IgxHintDirective, IgxInputDirective, IgxInputGroupComponent, IgxTreeGridComponent, IPinningConfig, RowPinningPosition, RowType } from 'igniteui-angular'; @@ -9,7 +9,7 @@ import { IgxActionStripComponent, IgxButtonDirective, IgxColumnComponent, IgxGri selector: 'app-grid-cell-styling.sample', styleUrls: ['grid-cell-styling.sample.scss'], templateUrl: 'grid-cell-styling.sample.html', - imports: [IgxButtonDirective, IgxInputGroupComponent, IgxInputDirective, IgxHintDirective, IgxGridComponent, NgFor, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent, IgxGridEditingActionsComponent, IgxTreeGridComponent, JsonPipe] + imports: [IgxButtonDirective, IgxInputGroupComponent, IgxInputDirective, IgxHintDirective, IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent, IgxGridEditingActionsComponent, IgxTreeGridComponent, JsonPipe] }) export class GridCellStylingSampleComponent implements OnInit { @ViewChild('grid1', { static: true }) 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 1e340da6cec..abd3b0fe7b3 100644 --- a/src/app/grid-add-row/grid-add-row.sample.html +++ b/src/app/grid-add-row/grid-add-row.sample.html @@ -15,27 +15,28 @@ (rowDelete)="log($event)" (rowDeleted)="log($event)" > - - + @for (c of columns; track c) { + + + } - - + @if (paging) { + + + } @@ -46,7 +47,9 @@

Settings

- {{value}} + @for (value of selectOptions; track value) { + {{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 cfd84d38061..f436435263c 100644 --- a/src/app/grid-add-row/grid-add-row.sample.ts +++ b/src/app/grid-add-row/grid-add-row.sample.ts @@ -1,5 +1,4 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { NgFor, NgIf } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { IRowDataCancelableEventArgs, IRowDataEventArgs, IgxActionStripComponent, IgxButtonDirective, IgxCardComponent, IgxCardContentDirective, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxColumnComponent, IgxGridComponent, IgxGridEditingActionsComponent, IgxGridPinningActionsComponent, IgxInputDirective, IgxInputGroupComponent, IgxLabelDirective, IgxPaginatorComponent, IgxSelectComponent, IgxSelectItemComponent } from 'igniteui-angular'; @@ -7,7 +6,7 @@ import { IRowDataCancelableEventArgs, IRowDataEventArgs, IgxActionStripComponent selector: 'app-grid-add-row', styleUrls: ['grid-add-row.sample.scss'], templateUrl: `grid-add-row.sample.html`, - imports: [IgxGridComponent, NgFor, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent, IgxGridEditingActionsComponent, NgIf, IgxPaginatorComponent, IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, IgxButtonDirective, IgxSelectComponent, FormsModule, IgxSelectItemComponent, IgxInputGroupComponent, IgxInputDirective, IgxLabelDirective] + imports: [IgxGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent, IgxGridEditingActionsComponent, IgxPaginatorComponent, IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, IgxButtonDirective, IgxSelectComponent, FormsModule, IgxSelectItemComponent, IgxInputGroupComponent, IgxInputDirective, IgxLabelDirective] }) export class GridAddRowSampleComponent implements OnInit { diff --git a/src/app/grid-auto-size/grid-auto-size.sample.html b/src/app/grid-auto-size/grid-auto-size.sample.html index ed67cb38e4d..b3a51451e9c 100644 --- a/src/app/grid-auto-size/grid-auto-size.sample.html +++ b/src/app/grid-auto-size/grid-auto-size.sample.html @@ -22,35 +22,37 @@
- - - - - - - - - - -
+ + + + + + + + @for (c of columns; track c) { + + + } + + diff --git a/src/app/grid-auto-size/grid-auto-size.sample.ts b/src/app/grid-auto-size/grid-auto-size.sample.ts index 42bce4c11db..07d8b95883d 100644 --- a/src/app/grid-auto-size/grid-auto-size.sample.ts +++ b/src/app/grid-auto-size/grid-auto-size.sample.ts @@ -1,5 +1,4 @@ import { Component, ViewChild, OnInit, HostBinding } from '@angular/core'; -import { NgFor } from '@angular/common'; import { SAMPLE_DATA } from '../shared/sample-data'; import { GridSelectionMode, IgxGridComponent, IGX_BUTTON_GROUP_DIRECTIVES, IGX_GRID_DIRECTIVES } from 'igniteui-angular'; @@ -9,7 +8,7 @@ import { GridSelectionMode, IgxGridComponent, IGX_BUTTON_GROUP_DIRECTIVES, IGX_G selector: 'app-grid-column-moving-sample', styleUrls: ['grid-auto-size.sample.scss'], templateUrl: 'grid-auto-size.sample.html', - imports: [NgFor, IGX_GRID_DIRECTIVES, IGX_BUTTON_GROUP_DIRECTIVES] + imports: [IGX_GRID_DIRECTIVES, IGX_BUTTON_GROUP_DIRECTIVES] }) export class GridAutoSizeSampleComponent implements OnInit { diff --git a/src/app/grid-cell-api/grid-cell-api.sample.html b/src/app/grid-cell-api/grid-cell-api.sample.html index f0edb3cc1f2..e95e8a5e920 100644 --- a/src/app/grid-cell-api/grid-cell-api.sample.html +++ b/src/app/grid-cell-api/grid-cell-api.sample.html @@ -39,8 +39,10 @@

igxGrid

Address: {{dataItem.Address}}
- - + @for (c of columns; track c) { + + + } diff --git a/src/app/grid-groupby/grid-groupby.sample.ts b/src/app/grid-groupby/grid-groupby.sample.ts index 322bd46415d..f6943665d38 100644 --- a/src/app/grid-groupby/grid-groupby.sample.ts +++ b/src/app/grid-groupby/grid-groupby.sample.ts @@ -1,5 +1,4 @@ import { Component, ViewChild, OnInit, HostBinding } from '@angular/core'; -import { NgFor } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { DefaultSortingStrategy, GridSummaryCalculationMode, GridSummaryPosition, GroupMemberCountSortingStrategy, IRowSelectionEventArgs, ISortingExpression, ISortingOptions, IgxButtonDirective, IgxButtonGroupComponent, IgxColumnComponent, IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective, IgxGridComponent, IgxSwitchComponent, IgxToggleActionDirective, SortingDirection } from 'igniteui-angular'; @@ -7,7 +6,7 @@ import { DefaultSortingStrategy, GridSummaryCalculationMode, GridSummaryPosition selector: 'app-grid-sample', styleUrls: ['grid-groupby.sample.scss'], templateUrl: 'grid-groupby.sample.html', - imports: [IgxSwitchComponent, FormsModule, IgxButtonDirective, IgxToggleActionDirective, IgxDropDownItemNavigationDirective, IgxDropDownComponent, NgFor, IgxDropDownItemComponent, IgxButtonGroupComponent, IgxGridComponent, IgxColumnComponent] + imports: [IgxSwitchComponent, FormsModule, IgxButtonDirective, IgxToggleActionDirective, IgxDropDownItemNavigationDirective, IgxDropDownComponent, IgxDropDownItemComponent, IgxButtonGroupComponent, IgxGridComponent, IgxColumnComponent] }) export class GridGroupBySampleComponent implements OnInit { @HostBinding('style.--ig-size') diff --git a/src/app/grid-localization/grid-localization.sample.html b/src/app/grid-localization/grid-localization.sample.html index 0e506adebd5..28cff2ae551 100644 --- a/src/app/grid-localization/grid-localization.sample.html +++ b/src/app/grid-localization/grid-localization.sample.html @@ -5,9 +5,11 @@ Grid with Localization - - {{ locale }} - + @for (locale of selectLocales; track locale) { + + {{ locale }} + + } diff --git a/src/app/grid-localization/grid-localization.sample.ts b/src/app/grid-localization/grid-localization.sample.ts index d1872d9e190..d760416129b 100644 --- a/src/app/grid-localization/grid-localization.sample.ts +++ b/src/app/grid-localization/grid-localization.sample.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { registerLocaleData, NgFor } from '@angular/common'; +import { registerLocaleData } from '@angular/common'; import { FormsModule } from '@angular/forms'; import localeBG from '@angular/common/locales/bg'; @@ -25,7 +25,7 @@ import { IResourceStrings, GridResourceStringsEN, IgxColumnComponent, IgxGridCom selector: 'app-grid-localization', styleUrls: ['./grid-localization.sample.scss'], templateUrl: 'grid-localization.sample.html', - imports: [IgxGridComponent, IgxColumnComponent, IgxGridToolbarComponent, IgxGridToolbarTitleComponent, IgxSelectComponent, FormsModule, NgFor, IgxSelectItemComponent] + imports: [IgxGridComponent, IgxColumnComponent, IgxGridToolbarComponent, IgxGridToolbarTitleComponent, IgxSelectComponent, FormsModule, IgxSelectItemComponent] }) export class GridLocalizationSampleComponent implements OnInit { diff --git a/src/app/grid-master-detail/grid-master-detail.sample.html b/src/app/grid-master-detail/grid-master-detail.sample.html index dcd69f4e14b..12f4ce35d5c 100644 --- a/src/app/grid-master-detail/grid-master-detail.sample.html +++ b/src/app/grid-master-detail/grid-master-detail.sample.html @@ -2,13 +2,16 @@ - - + @for (c of columns; track c) { + + + } -
{{ cell.value}}
- + @if (cell.value > 1000) { +
{{ cell.value}}
+ }
-
+ @if (renderGrid) { + + + @for (col of gridCollection; track col) { + + } + + + + } - diff --git a/src/app/grid-multi-row-layout-config/grid-mrl-config.sample.ts b/src/app/grid-multi-row-layout-config/grid-mrl-config.sample.ts index e3cc675a156..0cfa14f46de 100644 --- a/src/app/grid-multi-row-layout-config/grid-mrl-config.sample.ts +++ b/src/app/grid-multi-row-layout-config/grid-mrl-config.sample.ts @@ -1,5 +1,5 @@ import { Component, ViewChild, ElementRef, ChangeDetectorRef, ViewChildren, QueryList } from '@angular/core'; -import { NgFor, NgStyle, NgIf } from '@angular/common'; +import { NgStyle } from '@angular/common'; import { SAMPLE_DATA } from '../shared/sample-data'; import { GridSelectionMode, IDropBaseEventArgs, IDropDroppedEventArgs, IgxButtonDirective, IgxColumnComponent, IgxColumnLayoutComponent, IgxDialogComponent, IgxDragDirective, IgxDropDirective, IgxGridComponent } from 'igniteui-angular'; @@ -19,7 +19,7 @@ interface ColumnConfig { selector: 'app-grid-mrl-config-sample', templateUrl: 'grid-mrl-config.sample.html', styleUrls: ['grid-mrl-config.sample.scss'], - imports: [NgFor, IgxDragDirective, NgStyle, IgxDropDirective, NgIf, IgxButtonDirective, IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, IgxDialogComponent] + imports: [IgxDragDirective, NgStyle, IgxDropDirective, IgxButtonDirective, IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, IgxDialogComponent] }) export class GridMRLConfigSampleComponent { diff --git a/src/app/grid-nested-props/grid-nested-props.sample.html b/src/app/grid-nested-props/grid-nested-props.sample.html index 0b6f2dd4f55..9cb4a5e118c 100644 --- a/src/app/grid-nested-props/grid-nested-props.sample.html +++ b/src/app/grid-nested-props/grid-nested-props.sample.html @@ -18,16 +18,18 @@ - - + @for (each of config; track each) { + + + } diff --git a/src/app/grid-nested-props/grid-nested-props.sample.ts b/src/app/grid-nested-props/grid-nested-props.sample.ts index 79383ffcee4..1575e658483 100644 --- a/src/app/grid-nested-props/grid-nested-props.sample.ts +++ b/src/app/grid-nested-props/grid-nested-props.sample.ts @@ -1,5 +1,4 @@ import { Component } from '@angular/core'; -import { NgFor } from '@angular/common'; import { GridColumnDataType, IGX_GRID_DIRECTIVES, IgxTreeGridComponent } from 'igniteui-angular'; interface GridConfig { @@ -11,7 +10,7 @@ interface GridConfig { @Component({ selector: 'app-grid-nested-props', templateUrl: 'grid-nested-props.sample.html', - imports: [NgFor, IGX_GRID_DIRECTIVES, IgxTreeGridComponent] + imports: [IGX_GRID_DIRECTIVES, IgxTreeGridComponent] }) export class GridNestedPropsSampleComponent { public data = []; diff --git a/src/app/grid-percentage-columns/grid-percantge-widths.sample.html b/src/app/grid-percentage-columns/grid-percantge-widths.sample.html index fa048118be8..569372a8c9f 100644 --- a/src/app/grid-percentage-columns/grid-percantge-widths.sample.html +++ b/src/app/grid-percentage-columns/grid-percantge-widths.sample.html @@ -39,11 +39,15 @@

Pipe and locale settings

- {{cur}} + @for (cur of currencies; track cur) { + {{cur}} + } - {{cur}} + @for (cur of locales; track cur) { + {{cur}} + } @@ -66,8 +70,12 @@

Pipe and locale settings

- Continued - Discontinued + @if (val) { + Continued + } + @if (!val) { + Discontinued + } diff --git a/src/app/grid-percentage-columns/grid-percantge-widths.sample.ts b/src/app/grid-percentage-columns/grid-percantge-widths.sample.ts index ba7ad778ffe..4f6c0632681 100644 --- a/src/app/grid-percentage-columns/grid-percantge-widths.sample.ts +++ b/src/app/grid-percentage-columns/grid-percantge-widths.sample.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { NgFor, NgIf, CurrencyPipe, DatePipe } from '@angular/common'; +import { CurrencyPipe, DatePipe } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { data, dataWithoutPK } from '../shared/data'; @@ -9,7 +9,7 @@ import { IColumnPipeArgs, IgxButtonDirective, IgxCardComponent, IgxCardContentDi providers: [], selector: 'app-grid-percantge-widths.sample', templateUrl: 'grid-percantge-widths.sample.html', - imports: [IgxGridComponent, IgxColumnComponent, IgxCellTemplateDirective, IgxPaginatorComponent, IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, IgxInputGroupComponent, IgxLabelDirective, FormsModule, IgxInputDirective, IgxSelectComponent, NgFor, IgxSelectItemComponent, IgxButtonDirective, NgIf, CurrencyPipe, DatePipe] + imports: [IgxGridComponent, IgxColumnComponent, IgxCellTemplateDirective, IgxPaginatorComponent, IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, IgxInputGroupComponent, IgxLabelDirective, FormsModule, IgxInputDirective, IgxSelectComponent, IgxSelectItemComponent, IgxButtonDirective, CurrencyPipe, DatePipe] }) export class GridColumnPercentageWidthsSampleComponent implements OnInit { @ViewChild('grid1', { read: IgxGridComponent, static: true }) diff --git a/src/app/grid-performance/grid-performance.sample.html b/src/app/grid-performance/grid-performance.sample.html index b4bf59772ad..7e702eaa343 100644 --- a/src/app/grid-performance/grid-performance.sample.html +++ b/src/app/grid-performance/grid-performance.sample.html @@ -7,8 +7,10 @@

Fixed Size Rows

- - + @for (c of columns; track c) { + + + }
diff --git a/src/app/grid-performance/grid-performance.sample.ts b/src/app/grid-performance/grid-performance.sample.ts index a51dbb3e4c8..734539ae64d 100644 --- a/src/app/grid-performance/grid-performance.sample.ts +++ b/src/app/grid-performance/grid-performance.sample.ts @@ -1,5 +1,4 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { NgFor } from '@angular/common'; import { GridSelectionMode, IgxColumnComponent, IgxGridComponent, IgxGridToolbarActionsComponent, IgxGridToolbarComponent, IgxGridToolbarHidingComponent, IgxGridToolbarPinningComponent } from 'igniteui-angular'; @@ -7,7 +6,7 @@ import { GridSelectionMode, IgxColumnComponent, IgxGridComponent, IgxGridToolbar selector: 'app-grid-performance-sample', templateUrl: 'grid-performance.sample.html', styleUrls: ['grid-performance.sample.scss'], - imports: [IgxGridComponent, IgxGridToolbarComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, NgFor, IgxColumnComponent] + imports: [IgxGridComponent, IgxGridToolbarComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxColumnComponent] }) export class GridPerformanceSampleComponent implements OnInit { diff --git a/src/app/grid-re-create/grid-re-create.sample.html b/src/app/grid-re-create/grid-re-create.sample.html index d8eb968a9ae..69220ebb819 100644 --- a/src/app/grid-re-create/grid-re-create.sample.html +++ b/src/app/grid-re-create/grid-re-create.sample.html @@ -1,8 +1,10 @@ -
- - - - -
+@if (create) { +
+ + + + +
+} diff --git a/src/app/grid-re-create/grid-re-create.sample.ts b/src/app/grid-re-create/grid-re-create.sample.ts index e8a1990a8be..3a06e4a6fda 100644 --- a/src/app/grid-re-create/grid-re-create.sample.ts +++ b/src/app/grid-re-create/grid-re-create.sample.ts @@ -1,4 +1,3 @@ -import { NgIf } from '@angular/common'; import { Component, OnInit } from '@angular/core'; import { IgxColumnComponent, IgxGridComponent } from 'igniteui-angular'; @@ -10,7 +9,7 @@ import { IgxColumnComponent, IgxGridComponent } from 'igniteui-angular'; standalone: true, providers: [ ], - imports: [NgIf, IgxGridComponent, IgxColumnComponent] + imports: [IgxGridComponent, IgxColumnComponent] }) export class GridRecreateSampleComponent implements OnInit { public data = [] as any[]; diff --git a/src/app/grid-remote-paging/grid-remote-paging.sample.html b/src/app/grid-remote-paging/grid-remote-paging.sample.html index be4223a43a0..724b93a9d9f 100644 --- a/src/app/grid-remote-paging/grid-remote-paging.sample.html +++ b/src/app/grid-remote-paging/grid-remote-paging.sample.html @@ -7,9 +7,11 @@ - - + @if (paging) { + + + } @@ -19,7 +21,9 @@

Paging settings

- {{value}} + @for (value of selectOptions; track value) { + {{value}} + }
diff --git a/src/app/grid-remote-paging/grid-remote-paging.sample.ts b/src/app/grid-remote-paging/grid-remote-paging.sample.ts index 91ee22a4936..8a2da80baa0 100644 --- a/src/app/grid-remote-paging/grid-remote-paging.sample.ts +++ b/src/app/grid-remote-paging/grid-remote-paging.sample.ts @@ -1,5 +1,5 @@ import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; -import { NgIf, NgFor, AsyncPipe } from '@angular/common'; +import { AsyncPipe } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { Observable } from 'rxjs'; @@ -10,7 +10,7 @@ import { GridPagingMode, IgxButtonDirective, IgxCardComponent, IgxCardContentDir selector: 'app-grid-remote-paging-sample', templateUrl: 'grid-remote-paging.sample.html', providers: [RemoteService], - imports: [IgxGridComponent, IgxColumnComponent, NgIf, IgxPaginatorComponent, IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, IgxButtonDirective, IgxSelectComponent, FormsModule, NgFor, IgxSelectItemComponent, AsyncPipe] + imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent, IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, IgxButtonDirective, IgxSelectComponent, FormsModule, IgxSelectItemComponent, AsyncPipe] }) export class GridRemotePagingSampleComponent implements OnInit, AfterViewInit, OnDestroy { @ViewChild('grid1', { static: true }) public grid1: IgxGridComponent; diff --git a/src/app/grid-row-api/grid-row-api.sample.html b/src/app/grid-row-api/grid-row-api.sample.html index c2d908af1bf..8d727f2a4d7 100644 --- a/src/app/grid-row-api/grid-row-api.sample.html +++ b/src/app/grid-row-api/grid-row-api.sample.html @@ -28,10 +28,12 @@

igxGrid

Address: {{dataItem.Address}}
- - + @for (c of columns; track c) { + + + }
{{dragIcon}}{{countIcon}} @@ -84,11 +86,13 @@

IgxTreeGrid Hierarchical Data

- - + @for (c of treeGridHierColumns; track c) { + + + } @@ -135,11 +139,13 @@

IgxTreeGrid Flat Data

- - + @for (c of treeColumns; track c) { + + + } @@ -183,9 +189,11 @@

igxHierarchicalGrid

- - + @for (c of hColumns; track c) { + + + } Grid with rowEditing and with transactions Row
@@ -50,8 +52,10 @@

Grid with rowEditing and with transactions

Column
@@ -114,24 +118,26 @@

Cancel Grid Edit Events

- -
-
- - - - This is a custom editing template -
-
-
- - - + @if (customTemplate) { + +
+
+ + + + This is a custom editing template +
+
+
+ + + +
-
- + + } Changes: {{rowChangesCount}} @@ -205,16 +211,20 @@

Grid without row editing and with transactions

Performance grid with transactions and row edit

- - + @for (c of columns; track c) { + + + }
Submit the following transactions?
-

- {{ transaction }} -

+ @for (transaction of currentActiveGrid.transactions; track transaction) { +

+ {{ transaction }} +

+ }
diff --git a/src/app/grid-row-edit/grid-row-edit-sample.component.ts b/src/app/grid-row-edit/grid-row-edit-sample.component.ts index 18f9aac150e..0860d0918cf 100644 --- a/src/app/grid-row-edit/grid-row-edit-sample.component.ts +++ b/src/app/grid-row-edit/grid-row-edit-sample.component.ts @@ -1,5 +1,4 @@ import { Component, ViewChild } from '@angular/core'; -import { NgFor, NgIf } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { data } from '../shared/data'; @@ -20,7 +19,7 @@ import { IgxColumnGroupComponent } from '../../../projects/igniteui-angular/src/ selector: 'app-grid-row-edit', styleUrls: [`grid-row-edit-sample.component.scss`], templateUrl: 'grid-row-edit-sample.component.html', - imports: [IgxGridComponent, IgxColumnComponent, IgxCellTemplateDirective, IgxColumnRequiredValidatorDirective, IgxCellEditorTemplateDirective, FormsModule, IgxFocusDirective, IgxCheckboxComponent, NgFor, IgxButtonDirective, IgxSwitchComponent, IgxColumnGroupComponent, NgIf, IgxRowEditTabStopDirective, IgxRowEditTextDirective, IgxRowEditActionsDirective, IgxPaginatorComponent, IgxToggleDirective] + imports: [IgxGridComponent, IgxColumnComponent, IgxCellTemplateDirective, IgxColumnRequiredValidatorDirective, IgxCellEditorTemplateDirective, FormsModule, IgxFocusDirective, IgxCheckboxComponent, IgxButtonDirective, IgxSwitchComponent, IgxColumnGroupComponent, IgxRowEditTabStopDirective, IgxRowEditTextDirective, IgxRowEditActionsDirective, IgxPaginatorComponent, IgxToggleDirective] }) export class GridRowEditSampleComponent { @ViewChild(IgxToggleDirective, { static: true }) diff --git a/src/app/grid-row-pinning/grid-row-pinning.sample.html b/src/app/grid-row-pinning/grid-row-pinning.sample.html index 5a9f1f02fca..b2ea6f8a3df 100644 --- a/src/app/grid-row-pinning/grid-row-pinning.sample.html +++ b/src/app/grid-row-pinning/grid-row-pinning.sample.html @@ -44,10 +44,12 @@

igxGrid

- - + @for (c of columns; track c) { + + + }
@@ -74,9 +76,11 @@

igxHierarchicalGrid

- - + @for (c of hColumns; track c) { + + + } @@ -109,11 +113,13 @@

igxTreeGrid

- - + @for (c of treeColumns; track c) { + + + } diff --git a/src/app/grid-row-pinning/grid-row-pinning.sample.ts b/src/app/grid-row-pinning/grid-row-pinning.sample.ts index 9926f71136e..12928cb8ecd 100644 --- a/src/app/grid-row-pinning/grid-row-pinning.sample.ts +++ b/src/app/grid-row-pinning/grid-row-pinning.sample.ts @@ -1,5 +1,4 @@ import { Component, OnInit, ViewChild, AfterViewInit, HostBinding } from '@angular/core'; -import { NgFor } from '@angular/common'; import { IgxGridComponent, @@ -28,7 +27,7 @@ import { GridSearchBoxComponent } from '../grid-search-box/grid-search-box.compo providers: [ IgxIconService ], - imports: [NgFor, IGX_HIERARCHICAL_GRID_DIRECTIVES, IgxGridComponent, IgxTreeGridComponent, IgxIconComponent, GridSearchBoxComponent, IgxSwitchComponent, IgxButtonDirective] + imports: [IGX_HIERARCHICAL_GRID_DIRECTIVES, IgxGridComponent, IgxTreeGridComponent, IgxIconComponent, GridSearchBoxComponent, IgxSwitchComponent, IgxButtonDirective] }) export class GridRowPinningSampleComponent implements OnInit, AfterViewInit { diff --git a/src/app/grid-search-box/grid-search-box.component.html b/src/app/grid-search-box/grid-search-box.component.html index b70068de6af..f4acb8f175c 100644 --- a/src/app/grid-search-box/grid-search-box.component.html +++ b/src/app/grid-search-box/grid-search-box.component.html @@ -1,35 +1,47 @@ - - clear + @if (searchText.length === 0) { + + } + @if (searchText.length > 0) { + clear + } - -
- - {{ grid.lastSearchInfo.activeMatchIndex + 1 }}/{{ grid.lastSearchInfo.matchCount }} - - - 0/0 - -
-
- - - Aa - - - Ab - - -
-
- navigate_before - navigate_next -
-
+ @if (searchText.length > 0) { + + @if (grid.lastSearchInfo) { +
+ @if (grid.lastSearchInfo.matchCount > 0) { + + {{ grid.lastSearchInfo.activeMatchIndex + 1 }}/{{ grid.lastSearchInfo.matchCount }} + + } + @if (grid.lastSearchInfo.matchCount === 0) { + + 0/0 + + } +
+ } +
+ + + Aa + + + Ab + + +
+
+ navigate_before + navigate_next +
+
+ }
diff --git a/src/app/grid-search-box/grid-search-box.component.ts b/src/app/grid-search-box/grid-search-box.component.ts index 77ba72711d3..557f3931a07 100644 --- a/src/app/grid-search-box/grid-search-box.component.ts +++ b/src/app/grid-search-box/grid-search-box.component.ts @@ -1,5 +1,4 @@ import { Component, Input } from '@angular/core'; -import { NgIf } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { IGX_CHIPS_DIRECTIVES, IGX_INPUT_GROUP_DIRECTIVES, IgxGridComponent, IgxHierarchicalGridComponent, IgxIconComponent, IgxRippleDirective, IgxTreeGridComponent } from 'igniteui-angular'; @@ -8,7 +7,7 @@ import { IGX_CHIPS_DIRECTIVES, IGX_INPUT_GROUP_DIRECTIVES, IgxGridComponent, Igx selector: 'app-grid-search-box', styleUrls: ['./grid-search-box.component.scss'], templateUrl: './grid-search-box.component.html', - imports: [NgIf, IgxIconComponent, FormsModule, IgxRippleDirective, IGX_INPUT_GROUP_DIRECTIVES, IGX_CHIPS_DIRECTIVES] + imports: [IgxIconComponent, FormsModule, IgxRippleDirective, IGX_INPUT_GROUP_DIRECTIVES, IGX_CHIPS_DIRECTIVES] }) export class GridSearchBoxComponent { @Input() diff --git a/src/app/grid-search/grid-search.sample.html b/src/app/grid-search/grid-search.sample.html index 5b8831b8702..29af39438db 100644 --- a/src/app/grid-search/grid-search.sample.html +++ b/src/app/grid-search/grid-search.sample.html @@ -19,10 +19,12 @@ - - + @for (c of columns; track c) { + + + }
diff --git a/src/app/grid-search/grid-search.sample.ts b/src/app/grid-search/grid-search.sample.ts index 42ee83222c8..cf46bc18adf 100644 --- a/src/app/grid-search/grid-search.sample.ts +++ b/src/app/grid-search/grid-search.sample.ts @@ -1,5 +1,4 @@ import { Component, ViewChild, OnInit, HostBinding } from '@angular/core'; -import { NgFor } from '@angular/common'; import { SAMPLE_DATA } from '../shared/sample-data'; @@ -11,7 +10,7 @@ import { GridSearchBoxComponent } from '../grid-search-box/grid-search-box.compo selector: 'app-grid-search-sample', styleUrls: ['grid-search.sample.scss'], templateUrl: 'grid-search.sample.html', - imports: [NgFor, IGX_GRID_DIRECTIVES, IGX_BUTTON_GROUP_DIRECTIVES, GridSearchBoxComponent] + imports: [IGX_GRID_DIRECTIVES, IGX_BUTTON_GROUP_DIRECTIVES, GridSearchBoxComponent] }) export class GridSearchComponent implements OnInit { diff --git a/src/app/grid-selection/grid-selection.sample.html b/src/app/grid-selection/grid-selection.sample.html index c426ef747da..0b8fad057a7 100644 --- a/src/app/grid-selection/grid-selection.sample.html +++ b/src/app/grid-selection/grid-selection.sample.html @@ -3,12 +3,16 @@ - {{ item }} + @for (item of selectionModes; track item) { + {{ item }} + } - {{ item }} + @for (item of selectionModes; track item) { + {{ item }} + }
diff --git a/src/app/grid-selection/grid-selection.sample.ts b/src/app/grid-selection/grid-selection.sample.ts index bf6cb631cc7..f2b4390b1b9 100644 --- a/src/app/grid-selection/grid-selection.sample.ts +++ b/src/app/grid-selection/grid-selection.sample.ts @@ -1,5 +1,4 @@ import { AfterViewInit, ChangeDetectorRef, Component, ViewChild } from '@angular/core'; -import { NgFor } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { Observable } from 'rxjs'; @@ -21,7 +20,6 @@ import { data } from '../shared/data'; IgxColumnComponent, IgxGridComponent, IgxSwitchComponent, - NgFor, ] }) export class GridSelectionComponent implements AfterViewInit { diff --git a/src/app/grid-state/grid-state.component.html b/src/app/grid-state/grid-state.component.html index ff9c226732e..f1f1217856c 100644 --- a/src/app/grid-state/grid-state.component.html +++ b/src/app/grid-state/grid-state.component.html @@ -3,9 +3,11 @@ Flat Grid - - {{collapsed() ? 'Expand':'Collapse'}} - + @if (templatedIcon) { + + {{collapsed() ? 'Expand':'Collapse'}} + + }
@@ -22,11 +24,13 @@ - - + @for (c of initialColumns; track c) { + + + } @@ -47,9 +51,11 @@ Multi-column Headers - - {{collapsed() ? 'Expand':'Collapse'}} - + @if (templatedIcon) { + + {{collapsed() ? 'Expand':'Collapse'}} + + } @@ -113,9 +119,11 @@ Multi-Row Layouts - - {{collapsed() ? 'Expand':'Collapse'}} - + @if (templatedIcon) { + + {{collapsed() ? 'Expand':'Collapse'}} + + } @@ -169,9 +177,11 @@ Hierarchical Grid - - {{collapsed() ? 'Expand':'Collapse'}} - + @if (templatedIcon) { + + {{collapsed() ? 'Expand':'Collapse'}} + + }
@@ -186,10 +196,12 @@ - - + @for (c of hierGridColumns; track c) { + + + } @@ -199,24 +211,30 @@ - - + @for (c of hierGridColumns; track c) { + + + } - - - - - + } + + + @for (c of hierGridColumns; track c) { + + + } @@ -232,9 +250,11 @@ Tree Grid Flat data using PK and FK - - {{collapsed() ? 'Expand':'Collapse'}} - + @if (templatedIcon) { + + {{collapsed() ? 'Expand':'Collapse'}} + + }
@@ -248,11 +268,13 @@ - - + @for (c of treeGridColumns; track c) { + + + }
@@ -264,9 +286,11 @@ Tree Grid Flat Child Collection - - {{collapsed() ? 'Expand':'Collapse'}} - + @if (templatedIcon) { + + {{collapsed() ? 'Expand':'Collapse'}} + + }
@@ -296,22 +320,24 @@
  • Navigate away to visit the ABOUT page to save grid - state into local storage.
  • + state into local storage.
  • Use the switch buttons to turn on/off saving state for the corresponding feature.
  • Use the - delete - and - refresh - buttons to clear the localStorage content and reload the page with clear state.
  • + [igxTooltipTarget]="clear"> + delete + and + refresh + buttons to clear the localStorage content and reload the page with clear state.
-
- {{ f.shortName }} - -
+ @for (f of features; track f) { +
+ {{ f.shortName }} + +
+ }
@@ -320,13 +346,15 @@
-
- -
+ @for (f of features; track f) { +
+ +
+ }
Hi I'm {{ cell.value }} - + diff --git a/src/app/grid-state/grid-state.component.ts b/src/app/grid-state/grid-state.component.ts index 3b2ba2651f9..35c9f3e83ca 100644 --- a/src/app/grid-state/grid-state.component.ts +++ b/src/app/grid-state/grid-state.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild, QueryList, ViewChildren, TemplateRef } from '@angular/core'; -import { NgIf, NgTemplateOutlet, NgFor } from '@angular/common'; +import { NgTemplateOutlet } from '@angular/common'; import { Router, RouterLink } from '@angular/router'; import { FormsModule } from '@angular/forms'; @@ -51,7 +51,7 @@ interface GridState { selector: 'app-grid', styleUrls: ['./grid-state.component.scss'], templateUrl: './grid-state.component.html', - imports: [IgxColumnLayoutComponent, IgxExpansionPanelComponent, IgxCellHeaderTemplateDirective, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective, NgIf, IgxExpansionPanelIconDirective, IgxExpansionPanelBodyComponent, NgTemplateOutlet, IgxGridComponent, IgxGridStateDirective, IgxGridToolbarComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, NgFor, IgxColumnComponent, IgxGridDetailTemplateDirective, IgxPaginatorComponent, IgxTooltipDirective, IgxColumnGroupComponent, IgxHierarchicalGridComponent, IgxRowIslandComponent, IgxTreeGridComponent, RouterLink, IgxTooltipTargetDirective, IgxIconComponent, IgxSwitchComponent, FormsModule, IgxButtonDirective, IgxCellTemplateDirective] + imports: [IgxColumnLayoutComponent, IgxExpansionPanelComponent, IgxCellHeaderTemplateDirective, IgxExpansionPanelHeaderComponent, IgxExpansionPanelTitleDirective, IgxExpansionPanelIconDirective, IgxExpansionPanelBodyComponent, NgTemplateOutlet, IgxGridComponent, IgxGridStateDirective, IgxGridToolbarComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxColumnComponent, IgxGridDetailTemplateDirective, IgxPaginatorComponent, IgxTooltipDirective, IgxColumnGroupComponent, IgxHierarchicalGridComponent, IgxRowIslandComponent, IgxTreeGridComponent, RouterLink, IgxTooltipTargetDirective, IgxIconComponent, IgxSwitchComponent, FormsModule, IgxButtonDirective, IgxCellTemplateDirective] }) export class GridSaveStateComponent implements OnInit { @ViewChild(IgxExpansionPanelComponent, { static: true }) @@ -148,7 +148,7 @@ export class GridSaveStateComponent implements OnInit { } try { window.localStorage.setItem(`${stateDirective.grid.id}-state`, state); - } catch (e) { + } catch (_e) { console.log('Storage is full, or the value that you try to se is too long to be written in single item, Please empty data'); } } else { @@ -159,7 +159,7 @@ export class GridSaveStateComponent implements OnInit { } try { window.localStorage.setItem(`${stateDir.grid.id}-state`, state); - } catch (e) { + } catch (_e) { console.log('Storage is full, or the value that you try to se is too long to be written in single item, Please empty data'); } }); diff --git a/src/app/grid-summaries/grid-summaries.sample.html b/src/app/grid-summaries/grid-summaries.sample.html index 015d0c17568..7263cdb8c50 100644 --- a/src/app/grid-summaries/grid-summaries.sample.html +++ b/src/app/grid-summaries/grid-summaries.sample.html @@ -4,18 +4,24 @@ - - Grid Toolbar - - - - - - Export to Excel 👌 - Export to CSV 👍 - - - + @if (showToolbar) { + + Grid Toolbar + + @if (columnPinning) { + + } + @if (columnHiding) { + + } + + + Export to Excel 👌 + Export to CSV 👍 + + + + } @@ -55,7 +61,9 @@ - + @if (paging) { + + }
diff --git a/src/app/grid-summaries/grid-summaries.sample.ts b/src/app/grid-summaries/grid-summaries.sample.ts index 03b91d4e4cf..ae40bca4f09 100644 --- a/src/app/grid-summaries/grid-summaries.sample.ts +++ b/src/app/grid-summaries/grid-summaries.sample.ts @@ -1,5 +1,4 @@ import { Component, HostBinding, OnInit, ViewChild } from '@angular/core'; -import { NgIf } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { IgxGridComponent, @@ -30,7 +29,7 @@ class MySummary extends IgxNumberSummaryOperand { super(); } - public override operate(data: any[], allData = [], fieldName?): IgxSummaryResult[] { + public override operate(_data: any[], allData = [], fieldName?): IgxSummaryResult[] { fieldName = fieldName === 'Sum' ? 'ReorderLevel' : fieldName; const result = super.operate(allData.map(r => r[fieldName])); result.push({ @@ -46,7 +45,7 @@ class MySummary extends IgxNumberSummaryOperand { selector: 'app-grid-summaries-sample', styleUrls: ['./grid-summaries.component.scss'], templateUrl: 'grid-summaries.sample.html', - imports: [IgxButtonGroupComponent, IgxGridComponent, NgIf, IgxGridToolbarComponent, IgxGridToolbarTitleComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarExporterComponent, IgxExcelTextDirective, IgxCSVTextDirective, IgxColumnComponent, IgxCellTemplateDirective, IgxSummaryTemplateDirective, IgxPaginatorComponent, FormsModule, IgxSwitchComponent] + imports: [IgxButtonGroupComponent, IgxGridComponent, IgxGridToolbarComponent, IgxGridToolbarTitleComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarExporterComponent, IgxExcelTextDirective, IgxCSVTextDirective, IgxColumnComponent, IgxCellTemplateDirective, IgxSummaryTemplateDirective, IgxPaginatorComponent, FormsModule, IgxSwitchComponent] }) export class GridSummaryComponent implements OnInit { @HostBinding('style.--ig-size') diff --git a/src/app/grid-toolbar/grid-toolbar-custom.sample.html b/src/app/grid-toolbar/grid-toolbar-custom.sample.html index c7905078199..751ee085459 100644 --- a/src/app/grid-toolbar/grid-toolbar-custom.sample.html +++ b/src/app/grid-toolbar/grid-toolbar-custom.sample.html @@ -4,26 +4,32 @@

Toolbar

- - - - - - - - - - Export to Excel 👌 - Export to CSV 👍 - - - + @if (showToolbar) { + + + + + + @if (columnPinning) { + + } + @if (columnHiding) { + + } + + + Export to Excel 👌 + Export to CSV 👍 + + + + } diff --git a/src/app/grid-toolbar/grid-toolbar-custom.sample.ts b/src/app/grid-toolbar/grid-toolbar-custom.sample.ts index 8df6f2c7111..fd68850afa3 100644 --- a/src/app/grid-toolbar/grid-toolbar-custom.sample.ts +++ b/src/app/grid-toolbar/grid-toolbar-custom.sample.ts @@ -1,6 +1,5 @@ import { Component } from '@angular/core'; -import { NgIf } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { IgxButtonDirective, IgxCSVTextDirective, IgxColumnComponent, IgxExcelTextDirective, IgxGridComponent, IgxGridToolbarActionsComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarComponent, IgxGridToolbarExporterComponent, IgxGridToolbarHidingComponent, IgxGridToolbarPinningComponent, IgxIconComponent, IgxRippleDirective, IgxSwitchComponent } from 'igniteui-angular'; @@ -9,7 +8,7 @@ import { IgxButtonDirective, IgxCSVTextDirective, IgxColumnComponent, IgxExcelTe selector: 'app-grid-toolbar-custom-sample', styleUrls: ['grid-toolbar-custom.sample.scss'], templateUrl: 'grid-toolbar-custom.sample.html', - imports: [IgxGridComponent, NgIf, IgxGridToolbarComponent, IgxButtonDirective, IgxRippleDirective, IgxIconComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarExporterComponent, IgxExcelTextDirective, IgxCSVTextDirective, IgxSwitchComponent, FormsModule] + imports: [IgxGridComponent, IgxGridToolbarComponent, IgxButtonDirective, IgxRippleDirective, IgxIconComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarExporterComponent, IgxExcelTextDirective, IgxCSVTextDirective, IgxSwitchComponent, FormsModule] }) export class GridToolbarCustomSampleComponent { public showToolbar = true; diff --git a/src/app/grid-toolbar/grid-toolbar.sample.html b/src/app/grid-toolbar/grid-toolbar.sample.html index 62ab7c10141..1354af76fdd 100644 --- a/src/app/grid-toolbar/grid-toolbar.sample.html +++ b/src/app/grid-toolbar/grid-toolbar.sample.html @@ -3,19 +3,27 @@

Toolbar

- - - {{ title }} - - - - Really advanced filtering - - Transform to Excel 👌 - Transform to CSV 👍 - - - + @if (showToolbar) { + + @if (customContent) { + + } + {{ title }} + + @if (pinningEnabled) { + + } + @if (hidingEnabled) { + + } + Really advanced filtering + + Transform to Excel 👌 + Transform to CSV 👍 + + + + }
Toolbar diff --git a/src/app/grid-toolbar/grid-toolbar.sample.ts b/src/app/grid-toolbar/grid-toolbar.sample.ts index b279c638877..ecdf804e20e 100644 --- a/src/app/grid-toolbar/grid-toolbar.sample.ts +++ b/src/app/grid-toolbar/grid-toolbar.sample.ts @@ -1,5 +1,4 @@ import { Component } from '@angular/core'; -import { NgIf } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { IgxCSVTextDirective, IgxColumnComponent, IgxCsvExporterService, IgxExcelExporterService, IgxExcelTextDirective, IgxGridComponent, IgxGridToolbarActionsComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarComponent, IgxGridToolbarExporterComponent, IgxGridToolbarHidingComponent, IgxGridToolbarPinningComponent, IgxGridToolbarTitleComponent, IgxSwitchComponent } from 'igniteui-angular'; @@ -7,7 +6,7 @@ import { IgxCSVTextDirective, IgxColumnComponent, IgxCsvExporterService, IgxExce selector: 'app-grid-toolbar-sample', styleUrls: ['grid-toolbar.sample.scss'], templateUrl: 'grid-toolbar.sample.html', - imports: [IgxGridComponent, NgIf, IgxGridToolbarComponent, IgxGridToolbarTitleComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarExporterComponent, IgxExcelTextDirective, IgxCSVTextDirective, IgxSwitchComponent, FormsModule] + imports: [IgxGridComponent, IgxGridToolbarComponent, IgxGridToolbarTitleComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarExporterComponent, IgxExcelTextDirective, IgxCSVTextDirective, IgxSwitchComponent, FormsModule] }) export class GridToolbarSampleComponent { public showToolbar = true; diff --git a/src/app/grid-updates-test/grid-updates.component.html b/src/app/grid-updates-test/grid-updates.component.html index 4a90adba310..0b1a462503c 100644 --- a/src/app/grid-updates-test/grid-updates.component.html +++ b/src/app/grid-updates-test/grid-updates.component.html @@ -10,12 +10,14 @@ (rowSelectionChanging)="handleRowSelectionChange($event)" rowSelection="single" #grid> - - + @for (each of nestedConfigColumns; track each) { + + + }

Selected Name: {{selectedItem?.name}}

diff --git a/src/app/grid-updates-test/grid-updates.component.ts b/src/app/grid-updates-test/grid-updates.component.ts index 10d37ed32ff..6e1e90bbc25 100644 --- a/src/app/grid-updates-test/grid-updates.component.ts +++ b/src/app/grid-updates-test/grid-updates.component.ts @@ -1,5 +1,4 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { NgFor } from '@angular/common'; import { IRowSelectionEventArgs, IgxColumnComponent, IgxGridComponent } from 'igniteui-angular'; import { AMINO_DATA } from './aminoData'; @@ -7,7 +6,7 @@ import { AMINO_DATA } from './aminoData'; selector: 'app-grid-updates', styleUrls: ['./grid-updates.component.scss'], templateUrl: './grid-updates.component.html', - imports: [IgxGridComponent, NgFor, IgxColumnComponent] + imports: [IgxGridComponent, IgxColumnComponent] }) export class GridUpdatesComponent implements OnInit { @ViewChild('grid') public grid: IgxGridComponent; diff --git a/src/app/grid-validation/grid-validation.sample.component.html b/src/app/grid-validation/grid-validation.sample.component.html index 45b89cc48b3..3ec23bda707 100644 --- a/src/app/grid-validation/grid-validation.sample.component.html +++ b/src/app/grid-validation/grid-validation.sample.component.html @@ -17,9 +17,11 @@

Grid without transactions

-
- This name is forbidden. -
+ @if (cell.validation.errors?.['forbiddenName']) { +
+ This name is forbidden. +
+ }
@@ -43,9 +45,11 @@

Grid with transactions

-
- This name is forbidden. -
+ @if (cell.validation.errors?.['forbiddenName']) { +
+ This name is forbidden. +
+ }
@@ -66,21 +70,23 @@

Grid with transactions

TreeGrid

- - - {{cell.row.validation.status}} - - - - - - - - - + foreignKey="PID" [width]="'900px'" [height]="'800px'" [rowEditable]="true" [moving]="true"> + + + {{cell.row.validation.status}} + + + @for (c of treeColumns; track c) { + + + } + + + + +
@@ -88,18 +94,24 @@

TreeGrid

Hierarchical Grid

- - - - - - - -
- This name is forbidden. -
-
+ @for (c of hColumns; track c) { + + } + + @for (c of hColumns2; track c) { + + + + + @if (cell.validation.errors?.['forbiddenName']) { +
+ This name is forbidden. +
+ } +
+
+ }
diff --git a/src/app/grid-validation/grid-validation.sample.component.ts b/src/app/grid-validation/grid-validation.sample.component.ts index 7f40f4a142a..9b45a74a557 100644 --- a/src/app/grid-validation/grid-validation.sample.component.ts +++ b/src/app/grid-validation/grid-validation.sample.component.ts @@ -1,5 +1,5 @@ import { Component, Directive, ViewChild, Input } from '@angular/core'; -import { NgTemplateOutlet, NgIf, NgFor } from '@angular/common'; +import { NgTemplateOutlet } from '@angular/common'; import { AbstractControl, NG_VALIDATORS, ValidationErrors, ValidatorFn, Validators, FormsModule } from '@angular/forms'; import { data } from '../shared/data'; @@ -35,8 +35,6 @@ export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn { styleUrls: [`grid-validation.sample.component.scss`], templateUrl: 'grid-validation.sample.component.html', imports: [ - NgFor, - NgIf, NgTemplateOutlet, FormsModule, ForbiddenValidatorDirective, diff --git a/src/app/grid/grid.sample.html b/src/app/grid/grid.sample.html index 9a9bcde16e0..2f67f33a48f 100644 --- a/src/app/grid/grid.sample.html +++ b/src/app/grid/grid.sample.html @@ -58,24 +58,26 @@
Revertable for the last deleted row
-
-

{{ col.field }}

-
- Filtering -
-
- Sorting -
-
- Editable -
-
- Hidden -
-
- Disable Hiding + @for (col of grid1.columns; track col) { +
+

{{ col.field }}

+
+ Filtering +
+
+ Sorting +
+
+ Editable +
+
+ Hidden +
+
+ Disable Hiding +
-
+ }
@@ -94,24 +96,26 @@

Grid with templated column cells and local observable d >

-
-

{{ col.field }}

-
- Filtering -
-
- Sorting -
-
- Editable + @for (col of grid2.columns; track col) { +
+

{{ col.field }}

+
+ Filtering +
+
+ Sorting +
+
+ Editable +
+
+ Hidden +
+
+ Disable Hiding +
-
- Hidden -
-
- Disable Hiding -
-
+ }
@@ -139,12 +143,15 @@

{{ col.field }}

+ --> @@ -154,7 +161,9 @@

{{ col.field }}

- + @if (gridPaging) { + + } diff --git a/src/app/grid/grid.sample.ts b/src/app/grid/grid.sample.ts index 49ecefe32b6..fc94203ef0a 100644 --- a/src/app/grid/grid.sample.ts +++ b/src/app/grid/grid.sample.ts @@ -1,6 +1,6 @@ import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core'; import { Observable } from 'rxjs'; -import { NgFor, AsyncPipe, NgIf } from '@angular/common'; +import { AsyncPipe } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { RemoteService } from '../shared/remote.service'; @@ -18,8 +18,6 @@ import { CsvFileTypes, DefaultSortingStrategy, GridSelectionMode, IgxBaseExporte ], imports: [ FormsModule, - NgFor, - NgIf, AsyncPipe, IGX_GRID_DIRECTIVES, IGX_CARD_DIRECTIVES, diff --git a/src/app/hierarchical-grid-remote-virtualization/hierarchical-grid-remote-virtualization.html b/src/app/hierarchical-grid-remote-virtualization/hierarchical-grid-remote-virtualization.html index 15d9aeda183..ae896940d26 100644 --- a/src/app/hierarchical-grid-remote-virtualization/hierarchical-grid-remote-virtualization.html +++ b/src/app/hierarchical-grid-remote-virtualization/hierarchical-grid-remote-virtualization.html @@ -1,11 +1,11 @@ - -
-
- -
- {{ val }} -
+ @if (!rowData.emptyRec) { +
+ {{ val }} +
+ } @else { +
+ }
diff --git a/src/app/hierarchical-grid-remote-virtualization/hierarchical-grid-remote-virtualization.ts b/src/app/hierarchical-grid-remote-virtualization/hierarchical-grid-remote-virtualization.ts index 4bff9369e6b..84ad3c5d662 100644 --- a/src/app/hierarchical-grid-remote-virtualization/hierarchical-grid-remote-virtualization.ts +++ b/src/app/hierarchical-grid-remote-virtualization/hierarchical-grid-remote-virtualization.ts @@ -1,5 +1,4 @@ import { Component, ViewChild, AfterViewInit, ChangeDetectorRef } from '@angular/core'; -import { NgIf } from '@angular/common'; import { IGX_HIERARCHICAL_GRID_DIRECTIVES, IgxHierarchicalGridComponent @@ -13,7 +12,7 @@ import { debounceTime } from 'rxjs/operators'; templateUrl: 'hierarchical-grid-remote-virtualization.html', styleUrls: ['hierarchical-grid-remote-virtualization.scss'], providers: [RemoteService], - imports: [NgIf, IGX_HIERARCHICAL_GRID_DIRECTIVES] + imports: [IGX_HIERARCHICAL_GRID_DIRECTIVES] }) export class HierarchicalGridRemoteVirtualizationComponent implements AfterViewInit { @ViewChild('hGrid', { static: true }) diff --git a/src/app/hierarchical-grid/hierarchical-grid.sample.html b/src/app/hierarchical-grid/hierarchical-grid.sample.html index d5daa1761ff..3c700c62688 100644 --- a/src/app/hierarchical-grid/hierarchical-grid.sample.html +++ b/src/app/hierarchical-grid/hierarchical-grid.sample.html @@ -115,8 +115,8 @@

Sample One

@@ -154,27 +154,37 @@

Sample three (batch editing)

- - - + [rowEditable]="true" [primaryKey]="'ID'" [data]="localData" [height]="'600px'" [width]="'100%'" #hGrid2> + @if (columnsReady) { - -
- -
-
+ } + @if (columnsReady) { + + } + @if (layoutsReady) { + + + + @if (riToggle) { +
+ +
+ } +
+ } -
- - - - -
+ @if (!riToggle) { +
+ + + + +
+ }

Sample 4

@@ -188,11 +198,15 @@

Sample 4

- + @for (c of columns; track c) { + + } - + @for (c of childColumns; track c) { + + }
diff --git a/src/app/hierarchical-grid/hierarchical-grid.sample.ts b/src/app/hierarchical-grid/hierarchical-grid.sample.ts index 6981abed203..af746d3344c 100644 --- a/src/app/hierarchical-grid/hierarchical-grid.sample.ts +++ b/src/app/hierarchical-grid/hierarchical-grid.sample.ts @@ -1,5 +1,4 @@ import { Component, ViewChild, ChangeDetectorRef, AfterViewInit, HostBinding } from '@angular/core'; -import { NgIf, NgFor } from '@angular/common'; import { GridSearchBoxComponent } from '../grid-search-box/grid-search-box.component'; import { IgxRowIslandComponent, @@ -17,7 +16,7 @@ import { selector: 'app-hierarchical-grid-sample', styleUrls: ['hierarchical-grid.sample.scss'], templateUrl: 'hierarchical-grid.sample.html', - imports: [NgIf, NgFor, GridSearchBoxComponent, IGX_HIERARCHICAL_GRID_DIRECTIVES, IgxIconComponent, IGX_BUTTON_GROUP_DIRECTIVES] + imports: [GridSearchBoxComponent, IGX_HIERARCHICAL_GRID_DIRECTIVES, IgxIconComponent, IGX_BUTTON_GROUP_DIRECTIVES] }) export class HierarchicalGridSampleComponent implements AfterViewInit { @HostBinding('style.--ig-size') diff --git a/src/app/hound/hound.component.html b/src/app/hound/hound.component.html index 8ef2412902d..e88cf5b9161 100644 --- a/src/app/hound/hound.component.html +++ b/src/app/hound/hound.component.html @@ -21,10 +21,14 @@
- - {{ item.field }} - {{item.icon}} - + @for (item of ddItems; track item) { + + {{ item.field }} + @if (item.icon) { + {{item.icon}} + } + + }
@@ -50,9 +54,11 @@ - - {{item}} - + @for (item of items; track item) { + + {{item}} + + } + placeholder="Location(s)"> diff --git a/src/app/hound/hound.component.ts b/src/app/hound/hound.component.ts index 405526479ea..8fff9069931 100644 --- a/src/app/hound/hound.component.ts +++ b/src/app/hound/hound.component.ts @@ -24,7 +24,6 @@ import { IgxToggleActionDirective, } from "igniteui-angular"; import {FormsModule} from "@angular/forms"; -import {NgForOf, NgIf} from "@angular/common"; @Component({ selector: 'app-hound', @@ -39,7 +38,6 @@ import {NgForOf, NgIf} from "@angular/common"; IgxPrefixDirective, IgxSuffixDirective, IgxSelectComponent, - NgForOf, IgxComboComponent, IgxCheckboxComponent, IgxDropDownComponent, @@ -47,7 +45,6 @@ import {NgForOf, NgIf} from "@angular/common"; IgxToggleActionDirective, IgxRadioComponent, IgxRadioGroupDirective, - NgIf, IgxSelectItemComponent, IgxTabsModule, IgxTabsComponent, diff --git a/src/app/icon-button/icon-button.sample.ts b/src/app/icon-button/icon-button.sample.ts index 8582a727887..523fdf16770 100644 --- a/src/app/icon-button/icon-button.sample.ts +++ b/src/app/icon-button/icon-button.sample.ts @@ -59,13 +59,13 @@ export class IconButtonSampleComponent { ) { this.propertyChangeService.setPanelConfig(this.panelConfig); - const { unsubscribe } = + const propertyChange = this.propertyChangeService.propertyChanges.subscribe( (properties) => { this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } } diff --git a/src/app/input-controls/input-controls.sample.ts b/src/app/input-controls/input-controls.sample.ts index a4f243da5f4..764a072ad23 100644 --- a/src/app/input-controls/input-controls.sample.ts +++ b/src/app/input-controls/input-controls.sample.ts @@ -107,14 +107,14 @@ export class InputControlsSampleComponent { ) { this.propertyChangeService.setPanelConfig(this.panelConfig); - const { unsubscribe } = + const propertyChange = this.propertyChangeService.propertyChanges.subscribe( (properties) => { this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } private alignmentMap = new Map([ diff --git a/src/app/input-group-showcase/input-group-showcase.sample.ts b/src/app/input-group-showcase/input-group-showcase.sample.ts index 256a888feeb..314b188dc88 100644 --- a/src/app/input-group-showcase/input-group-showcase.sample.ts +++ b/src/app/input-group-showcase/input-group-showcase.sample.ts @@ -154,7 +154,7 @@ export class InputGroupShowcaseSampleComponent { constructor(private destroyRef: DestroyRef) { this.pcs.setPanelConfig(this.panelConfig); - const { unsubscribe } = this.pcs.propertyChanges.subscribe((updatedProperties) => { + const propertyChange = this.pcs.propertyChanges.subscribe((updatedProperties) => { const mergedProperties = this.mergeProperties(updatedProperties); this.properties.set(mergedProperties); @@ -162,7 +162,7 @@ export class InputGroupShowcaseSampleComponent { this.getPlaceholder(); }); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } // Merge incoming property updates with the default configuration diff --git a/src/app/input/input.sample.html b/src/app/input/input.sample.html index 5d185b669dc..e7380a237b4 100644 --- a/src/app/input/input.sample.html +++ b/src/app/input/input.sample.html @@ -31,9 +31,13 @@

Personal Info

- {{item}} - {{item}} + } + @for (item of ['Male', 'Female']; track item) { + {{item}} + }
@@ -58,15 +62,17 @@

Airplane Mode

- - {{item.icon}} -

{{item.name}}

-
- - {{item.active ? 'ON': 'OFF'}} - -
-
+ @for (item of settings; track item) { + + {{item.icon}} +

{{item.name}}

+
+ + {{item.active ? 'ON': 'OFF'}} + +
+
+ }
@@ -82,8 +88,8 @@

Checkbox sample

Alicia Keys + [(ngModel)]="user.registered" + [disableTransitions]="true"> Value diff --git a/src/app/input/input.sample.ts b/src/app/input/input.sample.ts index aba60cc2faa..3a358e7da24 100644 --- a/src/app/input/input.sample.ts +++ b/src/app/input/input.sample.ts @@ -1,5 +1,4 @@ import { Component, ChangeDetectionStrategy } from '@angular/core'; -import { NgFor } from '@angular/common'; import { UntypedFormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { IChangeCheckboxEventArgs, IGX_INPUT_GROUP_DIRECTIVES, IGX_LIST_DIRECTIVES, IgxAvatarComponent, IgxButtonDirective, IgxCheckboxComponent, IgxIconComponent, IgxRadioComponent, IgxSwitchComponent } from 'igniteui-angular'; @@ -9,7 +8,7 @@ import { IChangeCheckboxEventArgs, IGX_INPUT_GROUP_DIRECTIVES, IGX_LIST_DIRECTIV selector: 'app-input-sample', styleUrls: ['input.sample.scss'], templateUrl: 'input.sample.html', - imports: [FormsModule, NgFor, ReactiveFormsModule, IGX_INPUT_GROUP_DIRECTIVES, IGX_LIST_DIRECTIVES, IgxSwitchComponent, IgxIconComponent, IgxCheckboxComponent, IgxAvatarComponent, IgxRadioComponent, IgxButtonDirective] + imports: [FormsModule, ReactiveFormsModule, IGX_INPUT_GROUP_DIRECTIVES, IGX_LIST_DIRECTIVES, IgxSwitchComponent, IgxIconComponent, IgxCheckboxComponent, IgxAvatarComponent, IgxRadioComponent, IgxButtonDirective] }) export class InputSampleComponent { public placeholder = 'Please enter a value'; diff --git a/src/app/linear-progress/linear-progress.sample.ts b/src/app/linear-progress/linear-progress.sample.ts index 3670074c463..674207b228f 100644 --- a/src/app/linear-progress/linear-progress.sample.ts +++ b/src/app/linear-progress/linear-progress.sample.ts @@ -112,14 +112,14 @@ export class LinearProgressSampleComponent { ) { this.propertyChangeService.setPanelConfig(this.panelConfig); - const { unsubscribe } = + const propertyChange = this.propertyChangeService.propertyChanges.subscribe( (properties) => { this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } protected get variantAngular() { diff --git a/src/app/list-panning/list-panning.sample.html b/src/app/list-panning/list-panning.sample.html index 1840cd8a5bc..d936463426a 100644 --- a/src/app/list-panning/list-panning.sample.html +++ b/src/app/list-panning/list-panning.sample.html @@ -11,12 +11,14 @@

Swipe left or right to perform action

Dial
Contacts - + @for (item of navItems; track item) { +

{{item.text}}

{{item.phone}} star -
+
+ }
@@ -33,12 +35,14 @@

Swipe left or right to perform action

Delete
Contacts - + @for (item of navItems2; track item) { + -

{{item.text}}

- {{item.phone}} +

{{item.text}}

+ {{item.phone}} star -
+
+ }
diff --git a/src/app/list-panning/list-panning.sample.ts b/src/app/list-panning/list-panning.sample.ts index 0fe2cf9f78f..23bf59db6f4 100644 --- a/src/app/list-panning/list-panning.sample.ts +++ b/src/app/list-panning/list-panning.sample.ts @@ -1,12 +1,11 @@ import { Component, ViewChild, ViewEncapsulation } from '@angular/core'; -import { NgFor } from '@angular/common'; import { IGX_LIST_DIRECTIVES, IgxAvatarComponent, IgxButtonDirective, IgxIconComponent, IgxRippleDirective, IgxToastComponent } from 'igniteui-angular'; @Component({ selector: 'app-list-panning-sample', styleUrls: ['list-panning.sample.scss'], templateUrl: 'list-panning.sample.html', encapsulation: ViewEncapsulation.None, - imports: [NgFor, IgxRippleDirective, IgxAvatarComponent, IgxIconComponent, IgxToastComponent, IgxButtonDirective, IGX_LIST_DIRECTIVES] + imports: [IgxRippleDirective, IgxAvatarComponent, IgxIconComponent, IgxToastComponent, IgxButtonDirective, IGX_LIST_DIRECTIVES] }) export class ListPanningSampleComponent { @ViewChild('toast', { static: true }) diff --git a/src/app/list-performance/list-performance.sample.html b/src/app/list-performance/list-performance.sample.html index 7ac4c69c6eb..b9c9abf50f8 100644 --- a/src/app/list-performance/list-performance.sample.html +++ b/src/app/list-performance/list-performance.sample.html @@ -6,22 +6,26 @@

Performance sample

- - clear - + @if (searchContacts.value.length > 0) { + + clear + + } - - Contacts -
- - - {{item.text}} - star - -
-
+ @if (showList) { + + Contacts +
+ + + {{item.text}} + star + +
+
+ }
diff --git a/src/app/list-performance/list-performance.sample.ts b/src/app/list-performance/list-performance.sample.ts index cfe6cc291a1..774f86ff013 100644 --- a/src/app/list-performance/list-performance.sample.ts +++ b/src/app/list-performance/list-performance.sample.ts @@ -1,5 +1,4 @@ import { Component } from '@angular/core'; -import { NgIf } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { IGX_INPUT_GROUP_DIRECTIVES, IGX_LIST_DIRECTIVES, IgxAvatarComponent, IgxButtonDirective, IgxCardComponent, IgxFilterOptions, IgxFilterPipe, IgxForOfDirective, IgxIconComponent, IgxRippleDirective } from 'igniteui-angular'; @@ -9,7 +8,7 @@ import { IGX_INPUT_GROUP_DIRECTIVES, IGX_LIST_DIRECTIVES, IgxAvatarComponent, Ig selector: 'app-list-performance-sample', styleUrls: ['list-performance.sample.scss'], templateUrl: 'list-performance.sample.html', - imports: [IgxIconComponent, FormsModule, NgIf, IgxButtonDirective, IgxCardComponent, IgxForOfDirective, IgxRippleDirective, IgxAvatarComponent, IgxFilterPipe, IGX_LIST_DIRECTIVES, IGX_INPUT_GROUP_DIRECTIVES] + imports: [IgxIconComponent, FormsModule, IgxButtonDirective, IgxCardComponent, IgxForOfDirective, IgxRippleDirective, IgxAvatarComponent, IgxFilterPipe, IGX_LIST_DIRECTIVES, IGX_INPUT_GROUP_DIRECTIVES] }) export class ListPerformanceSampleComponent { public search1: string; diff --git a/src/app/list/list.sample.ts b/src/app/list/list.sample.ts index 26e71e08ee3..5d7edc82ca0 100644 --- a/src/app/list/list.sample.ts +++ b/src/app/list/list.sample.ts @@ -155,14 +155,14 @@ export class ListSampleComponent { ) { this.propertyChangeService.setPanelConfig(this.panelConfig); - const { unsubscribe } = + const propertyChange = this.propertyChangeService.propertyChanges.subscribe( (properties) => { this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } public employeeItems: Employee[] = [ diff --git a/src/app/navdrawer/navdrawer.sample.html b/src/app/navdrawer/navdrawer.sample.html index a9ed1186619..06a8ad2343a 100644 --- a/src/app/navdrawer/navdrawer.sample.html +++ b/src/app/navdrawer/navdrawer.sample.html @@ -25,8 +25,10 @@
Modes
Position
- {{item}} + @for (item of ['left', 'right']; track item) { + {{item}} + }

Can be "left"(default) or "right". Only has effect when not pinned.

diff --git a/src/app/navdrawer/navdrawer.sample.ts b/src/app/navdrawer/navdrawer.sample.ts index 5e6cf814df3..c9cd134b9e2 100644 --- a/src/app/navdrawer/navdrawer.sample.ts +++ b/src/app/navdrawer/navdrawer.sample.ts @@ -1,5 +1,4 @@ import { Component } from '@angular/core'; -import { NgFor } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { IgxRadioComponent, IgxSwitchComponent } from 'igniteui-angular'; import { AppComponent } from '../app.component'; @@ -10,7 +9,7 @@ import { AppComponent } from '../app.component'; selector: 'app-navbar-sample', styleUrls: ['navdrawer.sample.scss'], templateUrl: 'navdrawer.sample.html', - imports: [IgxSwitchComponent, FormsModule, NgFor, IgxRadioComponent] + imports: [IgxSwitchComponent, FormsModule, IgxRadioComponent] }) export class NavdrawerSampleComponent { constructor(public app: AppComponent) {} diff --git a/src/app/overlay/overlay-presets.sample.html b/src/app/overlay/overlay-presets.sample.html index 50f472488b7..a115dd3af5f 100644 --- a/src/app/overlay/overlay-presets.sample.html +++ b/src/app/overlay/overlay-presets.sample.html @@ -5,29 +5,37 @@

Absolute Position Strategies

- {{item}} + @for (item of absStrategies; track item) { + {{item}} + }

Absolute Position Settings

- {{item}} + @for (item of absPositions; track item) { + {{item}} + }

Relative Position Strategies

- {{item}} + @for (item of relStrategies; track item) { + {{item}} + }
-
-

Relative Position Settings

- {{item}} -
+
+

Relative Position Settings

+ @for (item of relPositions; track item) { + {{item}} + } +
Outlet @@ -37,11 +45,13 @@ - -
- {{ item }} -
-
+ @for (item of items; track item) { + +
+ {{ item }} +
+
+ }
diff --git a/src/app/overlay/overlay-presets.sample.ts b/src/app/overlay/overlay-presets.sample.ts index 26da56991af..bbfb28d5bdc 100644 --- a/src/app/overlay/overlay-presets.sample.ts +++ b/src/app/overlay/overlay-presets.sample.ts @@ -1,5 +1,4 @@ import { Component, ViewChild, ElementRef, OnInit } from '@angular/core'; -import { NgFor } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { IgxDropDownComponent, @@ -19,7 +18,7 @@ import { selector: 'overlay-presets-sample', templateUrl: './overlay-presets.sample.html', styleUrls: ['overlay-presets.sample.scss'], - imports: [NgFor, IgxRadioComponent, FormsModule, IgxButtonDirective, IgxRippleDirective, IgxDragDirective, IgxDropDownComponent, IgxDropDownItemComponent] + imports: [IgxRadioComponent, FormsModule, IgxButtonDirective, IgxRippleDirective, IgxDragDirective, IgxDropDownComponent, IgxDropDownItemComponent] }) export class OverlayPresetsSampleComponent implements OnInit { @ViewChild(IgxDropDownComponent, { static: true }) diff --git a/src/app/overlay/overlay.sample.html b/src/app/overlay/overlay.sample.html index c44853e74fe..f57447e6fef 100644 --- a/src/app/overlay/overlay.sample.html +++ b/src/app/overlay/overlay.sample.html @@ -38,13 +38,17 @@

Strategies

Position Strategies

- {{item}} + }

Scroll Strategies

- {{item}} + }
@@ -86,11 +90,13 @@ - -
- {{ item }} -
-
+ @for (item of items; track item) { + +
+ {{ item }} +
+
+ }
diff --git a/src/app/overlay/overlay.sample.ts b/src/app/overlay/overlay.sample.ts index fc29c0b9120..f69ea23cfc7 100644 --- a/src/app/overlay/overlay.sample.ts +++ b/src/app/overlay/overlay.sample.ts @@ -1,6 +1,5 @@ import { Component, ViewChild, ElementRef, ChangeDetectorRef, OnInit } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { NgFor } from '@angular/common'; import { IgxDropDownComponent, OverlaySettings, @@ -30,7 +29,7 @@ import { IAnimationParams } from 'igniteui-angular/animations'; selector: 'overlay-sample', styleUrls: ['overlay.sample.css'], templateUrl: './overlay.sample.html', - imports: [NgFor, IgxRadioComponent, FormsModule, IgxSwitchComponent, IgxInputGroupComponent, IgxInputDirective, IgxLabelDirective, IgxButtonDirective, IgxRippleDirective, IgxDragDirective, IgxDropDownComponent, IgxDropDownItemComponent] + imports: [IgxRadioComponent, FormsModule, IgxSwitchComponent, IgxInputGroupComponent, IgxInputDirective, IgxLabelDirective, IgxButtonDirective, IgxRippleDirective, IgxDragDirective, IgxDropDownComponent, IgxDropDownItemComponent] }) export class OverlaySampleComponent implements OnInit { @ViewChild(IgxDropDownComponent, { static: true }) diff --git a/src/app/pivot-grid/pivot-grid.sample.ts b/src/app/pivot-grid/pivot-grid.sample.ts index 35637546c77..132e5d4752d 100644 --- a/src/app/pivot-grid/pivot-grid.sample.ts +++ b/src/app/pivot-grid/pivot-grid.sample.ts @@ -71,6 +71,7 @@ export class PivotGridSampleComponent { this.filterExpTree.filteringOperands = [ { condition: IgxStringFilteringOperand.instance().condition('equals'), + conditionName: IgxStringFilteringOperand.instance().condition('equals').name, fieldName: 'SellerName', searchVal: 'Stanley' } diff --git a/src/app/query-builder/query-builder.sample.html b/src/app/query-builder/query-builder.sample.html index d9781214eea..d7bbd7aa97c 100644 --- a/src/app/query-builder/query-builder.sample.html +++ b/src/app/query-builder/query-builder.sample.html @@ -1,17 +1,68 @@ -
-
- +
+
+ + + + + + + (expressionTreeChange)="handleExpressionTreeChange()" [entities]="this.entities" + [expressionTree]="this.expressionTree"> - Custom Title +   Custom Title + + + + @if (selectedField?.field === 'Id' && selectedCondition === 'equals'){ + + + + + } @else { + + } + + +
+ + + +
-
- + @if (this.queryResult) { +
+ {{ this.queryResult }} +
+ } + +
+
{{ printExpressionTree(queryBuilder.expressionTree) }}
+ +

NO HEADER

+ + + +

EMPTY HEADER

+ + + + +

ONLY HEADER CONTENT

+ + face   Custom header content + + +

HEADER WITH TITLE

+ + +
diff --git a/src/app/query-builder/query-builder.sample.scss b/src/app/query-builder/query-builder.sample.scss index 90582957ea8..ea771d01d88 100644 --- a/src/app/query-builder/query-builder.sample.scss +++ b/src/app/query-builder/query-builder.sample.scss @@ -1,10 +1,43 @@ -.density-chooser { - margin-bottom: 16px; - max-width: 900px; +:host { + display: block; + padding-block-end: 16px; } -.sample-buttons { - margin-top: 24px; +.qb-sample-column { display: flex; + flex: initial; + flex-direction: column; + gap: 16px; + + > button { + align-self: center; + } +} + +.qb-sample-row { + display: flex; + gap: 16px; + flex-wrap: wrap; + + > * { + flex: 1; + } +} + +.qb-sample-buttons { + display: flex; + gap: 8px; flex-wrap: wrap; } + +.qb-output-area{ + overflow-y: auto; + max-height: 600px; + border: 1px solid hsla(var(--ig-gray-300)); + border-radius: 4px; + padding: 16px; + + pre { + margin-block: 0; + } +} diff --git a/src/app/query-builder/query-builder.sample.ts b/src/app/query-builder/query-builder.sample.ts index c39a511ece2..4188a3a7a8b 100644 --- a/src/app/query-builder/query-builder.sample.ts +++ b/src/app/query-builder/query-builder.sample.ts @@ -1,77 +1,182 @@ import { Component, ViewChild, OnInit } from '@angular/core'; -import { FilteringExpressionsTree, IgxStringFilteringOperand, +import { + FilteringExpressionsTree, FilteringLogic, IgxQueryBuilderComponent, changei18n, IExpressionTree, IgxButtonDirective, IgxRippleDirective, - IgxQueryBuilderHeaderComponent} from 'igniteui-angular'; + IgxQueryBuilderHeaderComponent, + IgxNumberFilteringOperand, + IgxStringFilteringOperand, + IgxBooleanFilteringOperand, + IgxDateFilteringOperand, + IgxTimeFilteringOperand, + IgxDateTimeFilteringOperand, + IgxComboComponent, + IGX_DIALOG_DIRECTIVES, IgxIconComponent +} from 'igniteui-angular'; import { IgxResourceStringsFR } from 'igniteui-angular-i18n'; -import { SizeSelectorComponent } from '../size-selector/size-selector.component'; +import { CommonModule } from '@angular/common'; +import { IgxQueryBuilderSearchValueTemplateDirective } from 'igniteui-angular/src/lib/query-builder/query-builder.directives'; +import { FormsModule } from '@angular/forms'; @Component({ providers: [], selector: 'app-query-builder-sample', styleUrls: ['query-builder.sample.scss'], templateUrl: 'query-builder.sample.html', - imports: [IgxQueryBuilderComponent, IgxQueryBuilderHeaderComponent, IgxButtonDirective, IgxRippleDirective, SizeSelectorComponent] + imports: [FormsModule, IGX_DIALOG_DIRECTIVES, IgxComboComponent, IgxQueryBuilderComponent, IgxQueryBuilderHeaderComponent, IgxButtonDirective, IgxRippleDirective, CommonModule, IgxQueryBuilderSearchValueTemplateDirective, IgxIconComponent] }) export class QueryBuilderComponent implements OnInit { @ViewChild('queryBuilder', { static: true }) public queryBuilder: IgxQueryBuilderComponent; - public fields: Array; + @ViewChild('searchValueTemplate', { read: IgxQueryBuilderSearchValueTemplateDirective, static: true }) + public searchValueTemplate: IgxQueryBuilderSearchValueTemplateDirective; + public lData: any[]; + public entities: Array; + public fieldsEntityA: Array; + public fieldsEntityB: Array; public displayDensities; public expressionTree: IExpressionTree; + public queryResult: string; public ngOnInit(): void { - this.fields = [ - { field: 'ID', dataType: 'string' }, - { field: 'CompanyName', dataType: 'string'}, - { field: 'ContactName', dataType: 'string' }, - { field: 'Employees', dataType: 'number' }, - { field: 'ContactTitle', dataType: 'string' }, - { field: 'DateCreated', dataType: 'date' }, - { field: 'TimeCreated', dataType: 'time' }, - { field: 'Address', dataType: 'string' }, - { field: 'City', dataType: 'string' }, - { field: 'Region', dataType: 'string' }, - { field: 'PostalCode', dataType: 'string' }, - { field: 'Phone', dataType: 'string' }, - { field: 'Fax', dataType: 'string' }, - { field: 'Contract', dataType: 'boolean' } + this.fieldsEntityA = [ + { field: 'Id', dataType: 'number', formatter: (value: any, rowData: any) => rowData === 'equals' ? `${Array.from(value).map((v: { id: any; }) => v.id)}` : value }, + { field: 'Name', dataType: 'string' }, + { field: 'Validated', dataType: 'boolean' }, + { field: 'Date created', dataType: 'date' }, + { field: 'Time created', dataType: 'time' }, + { field: 'DateTime created', dataType: 'dateTime' } ]; + this.fieldsEntityB = [ + { field: 'Number', dataType: 'number' }, + { field: 'String', dataType: 'string' }, + { field: 'Boolean', dataType: 'boolean' }, + { field: 'Date', dataType: 'date' }, + { field: 'Time', dataType: 'time' }, + { field: 'DateTime', dataType: 'dateTime' } + ]; + this.entities = [ + { + name: 'Entity A', + fields: this.fieldsEntityA + }, + { + name: 'Entity B', + fields: this.fieldsEntityB + } + ]; + + + const innerTree = new FilteringExpressionsTree(FilteringLogic.And, undefined, 'Entity B', ['Number']); + innerTree.filteringOperands.push({ + fieldName: 'Number', + condition: IgxNumberFilteringOperand.instance().condition('equals'), + conditionName: IgxNumberFilteringOperand.instance().condition('equals').name, + searchVal: 123 + }); + innerTree.filteringOperands.push({ + fieldName: 'String', + condition: IgxStringFilteringOperand.instance().condition('equals'), + conditionName: IgxStringFilteringOperand.instance().condition('equals').name, + searchVal: 'abc' + }); + innerTree.filteringOperands.push({ + fieldName: 'Boolean', + condition: IgxBooleanFilteringOperand.instance().condition('true'), + conditionName: IgxBooleanFilteringOperand.instance().condition('true').name + }); + innerTree.filteringOperands.push({ + fieldName: 'Date', + condition: IgxDateFilteringOperand.instance().condition('before'), + conditionName: IgxDateFilteringOperand.instance().condition('before').name, + searchVal: new Date() + }); + innerTree.filteringOperands.push({ + fieldName: 'Time', + condition: IgxTimeFilteringOperand.instance().condition('before'), + conditionName: IgxTimeFilteringOperand.instance().condition('before').name, + searchVal: new Date() + }); + innerTree.filteringOperands.push({ + fieldName: 'DateTime', + condition: IgxDateTimeFilteringOperand.instance().condition('before'), + conditionName: IgxDateTimeFilteringOperand.instance().condition('before').name, + searchVal: new Date() + }); - const tree = new FilteringExpressionsTree(FilteringLogic.And); + const tree = new FilteringExpressionsTree(FilteringLogic.And, undefined, 'Entity A', ['*']); + tree.filteringOperands.push({ + fieldName: 'Id', + condition: IgxStringFilteringOperand.instance().condition('inQuery'), + conditionName: IgxStringFilteringOperand.instance().condition('inQuery').name, + searchTree: innerTree + }); tree.filteringOperands.push({ - fieldName: 'ID', - condition: IgxStringFilteringOperand.instance().condition('contains'), - searchVal: 'a', - ignoreCase: true + fieldName: 'Validated', + condition: IgxBooleanFilteringOperand.instance().condition('true'), + conditionName: IgxBooleanFilteringOperand.instance().condition('true').name }); - const orTree = new FilteringExpressionsTree(FilteringLogic.Or); - orTree.filteringOperands.push({ - fieldName: 'ID', - condition: IgxStringFilteringOperand.instance().condition('contains'), - searchVal: 'b', - ignoreCase: true + + const subGroup = new FilteringExpressionsTree(FilteringLogic.Or, undefined, 'Entity A', ['*']); + subGroup.filteringOperands.push({ + fieldName: 'Name', + condition: IgxStringFilteringOperand.instance().condition('endsWith'), + conditionName: IgxStringFilteringOperand.instance().condition('endsWith').name, + searchVal: 'a' }); - orTree.filteringOperands.push({ - fieldName: 'CompanyName', - condition: IgxStringFilteringOperand.instance().condition('contains'), - searchVal: 'c', - ignoreCase: true + subGroup.filteringOperands.push({ + fieldName: 'DateTime created', + condition: IgxDateFilteringOperand.instance().condition('today'), + conditionName: IgxDateFilteringOperand.instance().condition('today').name }); - tree.filteringOperands.push(orTree); + tree.filteringOperands.push(subGroup); + tree.filteringOperands.push({ - fieldName: 'CompanyName', - condition: IgxStringFilteringOperand.instance().condition('contains'), - searchVal: 'd', - ignoreCase: true + fieldName: 'Validated', + condition: IgxBooleanFilteringOperand.instance().condition('false'), + conditionName: IgxBooleanFilteringOperand.instance().condition('false').name }); + const subGroup2 = new FilteringExpressionsTree(FilteringLogic.Or, undefined, 'Entity A', ['*']); + subGroup2.filteringOperands.push({ + fieldName: 'Id', + condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), + conditionName: IgxNumberFilteringOperand.instance().condition('greaterThan').name, + searchVal: '3' + }); + subGroup2.filteringOperands.push({ + fieldName: 'Name', + condition: IgxStringFilteringOperand.instance().condition('notNull'), + conditionName: IgxStringFilteringOperand.instance().condition('notNull').name + }); + tree.filteringOperands.push(subGroup2); + this.expressionTree = tree; + this.lData = [{ id: 0, field: 'a' }, { id: 1, field: '1' }] + // this.onChange(); + } + + public handleExpressionTreeChange() { + console.log(this.queryBuilder.expressionTree); + } + + public async onChange() { + // const tree = JSON.stringify(this.expressionTree); + // const resp = await fetch(this.backendUrl, { + // method: 'POST', + // headers: { + // 'Content-Type': 'application/json', + // }, + // body: tree + // }) + // if (resp.status == 200) { + // this.queryResult = await resp.text(); + // } } public changeLocale(locale: string) { @@ -80,4 +185,31 @@ export class QueryBuilderComponent implements OnInit { } this.queryBuilder.locale = locale; } + + public printExpressionTree(tree: IExpressionTree) { + if (JSON.stringify(tree) !== JSON.stringify(this.expressionTree)) { + // this.expressionTree = tree; + // this.onChange(); + } + return tree ? JSON.stringify(tree, null, 2) : 'Please add an expression!'; + } + + public canCommitExpressionTree() { + console.log(this.queryBuilder.canCommit()); + } + + public commitExpressionTree() { + this.queryBuilder.commit(); + } + + public discardExpressionTree() { + this.queryBuilder.discard(); + } + + // public handleChange(ev, selectedField, searchVal) { + // if (selectedField.field === 'Id') { + // searchVal.value = ev.newValue[0]; + // selectedField.formatter = (value: any, rowData: any) => rowData === 'equals' ? value[0].id : value; + // } + // } } diff --git a/src/app/radio/radio.sample.html b/src/app/radio/radio.sample.html index 391cf5260a9..d0e509bcfb5 100644 --- a/src/app/radio/radio.sample.html +++ b/src/app/radio/radio.sample.html @@ -2,28 +2,30 @@
- - -
Reserve your dream vacation at {{ opt }}
-
- -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut - labore et dolore magna - aliqua. Elit pellentesque habitant morbi tristique senectus et netus et. Aliquet bibendum - enim facilisis gravida. Rutrum -

-
- - - Pick choice {{ opt }} - -
+ @for (opt of options; track opt) { + + +
Reserve your dream vacation at {{ opt }}
+
+ +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut + labore et dolore magna + aliqua. Elit pellentesque habitant morbi tristique senectus et netus et. Aliquet bibendum + enim facilisis gravida. Rutrum +

+
+ + + Pick choice {{ opt }} + +
+ }

Selected: {{ initial }}

@@ -33,9 +35,11 @@
Reserve your dream vacation at {{ opt }}

Radio group without data model (Vertical Alignment)

- - {{item}} - + @for (item of ['Foo', 'Bar', 'Baz']; track item) { + + {{item}} + + }
- - + + @for (item of seasons; track item) { + {{item.name}} - + } +
diff --git a/src/app/radio/radio.sample.ts b/src/app/radio/radio.sample.ts index 3ab5979d2ad..bc25a6e32fc 100644 --- a/src/app/radio/radio.sample.ts +++ b/src/app/radio/radio.sample.ts @@ -1,5 +1,5 @@ import { Component, ViewChild, AfterContentInit } from '@angular/core'; -import { NgFor, JsonPipe } from '@angular/common'; +import { JsonPipe } from '@angular/common'; import { UntypedFormGroup, UntypedFormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { IgxRadioGroupDirective, IgxLayoutDirective, IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, IgxCardActionsComponent, IgxRippleDirective, IgxButtonDirective, IgxRadioComponent, RadioGroupAlignment } from 'igniteui-angular'; @@ -18,7 +18,7 @@ class Person { selector: 'app-radio-sample', styleUrls: ['radio.sample.scss'], templateUrl: 'radio.sample.html', - imports: [IgxRadioGroupDirective, FormsModule, IgxLayoutDirective, NgFor, IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, IgxCardActionsComponent, IgxRippleDirective, IgxButtonDirective, IgxRadioComponent, ReactiveFormsModule, JsonPipe] + imports: [IgxRadioGroupDirective, FormsModule, IgxLayoutDirective, IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, IgxCardActionsComponent, IgxRippleDirective, IgxButtonDirective, IgxRadioComponent, ReactiveFormsModule, JsonPipe] }) export class RadioSampleComponent implements AfterContentInit { @ViewChild('radioGroupZZ', { read: IgxRadioGroupDirective, static: true }) diff --git a/src/app/rating/rating.sample.html b/src/app/rating/rating.sample.html index 5b501514e3b..518ad2fa666 100644 --- a/src/app/rating/rating.sample.html +++ b/src/app/rating/rating.sample.html @@ -1,23 +1,23 @@
- - - {{model.Name}} - {{ model.Name }}'s rating is: {{ model.Rating }} - - -
- - - - - - - - - - - -
-
-
+ @for (model of models; track model) { + + + {{model.Name}} + {{ model.Name }}'s rating is: {{ model.Rating }} + + +
+ + + + + + + + + +
+
+
+ }
diff --git a/src/app/rating/rating.sample.ts b/src/app/rating/rating.sample.ts index ac7cc07267b..14bfa4cba9d 100644 --- a/src/app/rating/rating.sample.ts +++ b/src/app/rating/rating.sample.ts @@ -1,6 +1,5 @@ import { Component } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { NgFor } from '@angular/common'; import { defineComponents, IgcRatingComponent } from 'igniteui-webcomponents'; import { IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, IgxInputGroupComponent, IgxInputDirective, IgxLabelDirective, IgcFormControlDirective } from 'igniteui-angular'; @@ -11,7 +10,7 @@ defineComponents(IgcRatingComponent); selector: 'app-rating-sample', styleUrls: ['rating.sample.scss'], templateUrl: 'rating.sample.html', - imports: [NgFor, IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, FormsModule, IgxInputGroupComponent, IgxInputDirective, IgxLabelDirective, IgcFormControlDirective] + imports: [IgxCardComponent, IgxCardHeaderComponent, IgxCardHeaderTitleDirective, IgxCardContentDirective, FormsModule, IgxInputGroupComponent, IgxInputDirective, IgxLabelDirective, IgcFormControlDirective] }) export class RatingSampleComponent { public models = [{ diff --git a/src/app/reactive-from/reactive-form-sample.component.html b/src/app/reactive-from/reactive-form-sample.component.html index c818ca5a1de..b2b14304773 100644 --- a/src/app/reactive-from/reactive-form-sample.component.html +++ b/src/app/reactive-from/reactive-form-sample.component.html @@ -4,11 +4,15 @@

Book your movie ticket

- - - {{ movie }} - - + @for (genre of genres; track genre) { + + @for (movie of genre.movies; track movie) { + + {{ movie }} + + } + + } local_movies diff --git a/src/app/reactive-from/reactive-form-sample.component.ts b/src/app/reactive-from/reactive-form-sample.component.ts index 9ee391dd838..c2088e10afb 100644 --- a/src/app/reactive-from/reactive-form-sample.component.ts +++ b/src/app/reactive-from/reactive-form-sample.component.ts @@ -1,5 +1,4 @@ import { Component } from '@angular/core'; -import { NgFor } from '@angular/common'; import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { IgxSelectComponent, IgxSelectGroupComponent, IgxSelectItemComponent, IgxLabelDirective, IgxSelectToggleIconDirective, IgxIconComponent, IgxInputGroupComponent, IgxInputDirective, IgxSuffixDirective, IgxPrefixDirective, IgxHintDirective, IgxComboComponent, IgxDatePickerComponent, IgxTimePickerComponent, IgxButtonDirective, IgxRippleDirective } from 'igniteui-angular'; @@ -7,7 +6,7 @@ import { IgxSelectComponent, IgxSelectGroupComponent, IgxSelectItemComponent, Ig selector: 'app-reactive-form', styleUrls: ['reactive-form-sample.component.scss'], templateUrl: 'reactive-form-sample.component.html', - imports: [FormsModule, ReactiveFormsModule, IgxSelectComponent, NgFor, IgxSelectGroupComponent, IgxSelectItemComponent, IgxLabelDirective, IgxSelectToggleIconDirective, IgxIconComponent, IgxInputGroupComponent, IgxInputDirective, IgxSuffixDirective, IgxPrefixDirective, IgxHintDirective, IgxComboComponent, IgxDatePickerComponent, IgxTimePickerComponent, IgxButtonDirective, IgxRippleDirective] + imports: [FormsModule, ReactiveFormsModule, IgxSelectComponent, IgxSelectGroupComponent, IgxSelectItemComponent, IgxLabelDirective, IgxSelectToggleIconDirective, IgxIconComponent, IgxInputGroupComponent, IgxInputDirective, IgxSuffixDirective, IgxPrefixDirective, IgxHintDirective, IgxComboComponent, IgxDatePickerComponent, IgxTimePickerComponent, IgxButtonDirective, IgxRippleDirective] }) export class ReactiveFormSampleComponent { public genres = []; diff --git a/src/app/select/select.sample.html b/src/app/select/select.sample.html index 639bbe97877..a1dcd55c199 100644 --- a/src/app/select/select.sample.html +++ b/src/app/select/select.sample.html @@ -31,11 +31,13 @@

Select with ngModel, set items OnInit

None - - alarm - {{ item.field }} - notifications_active - + @for (item of items; track item; let inx = $index) { + + alarm + {{ item.field }} + notifications_active + + }
Header content @@ -101,8 +103,8 @@

Select - disabled item

-

Select - using Groups

- Select - using Groups + Select - using Groups (closed)="testOnClosed()" (selectionChanging)="testOnSelection($event)" [disabled]="false"> - - - alarm - - OutsideGroup - - - alarm - InsideGroup1 - alarm - - - alarm - InsideGroup2 - alarm - - - alarm - InsideGroup3 - alarm - - - + + + alarm + + OutsideGroup + + + alarm + InsideGroup1 + alarm + + + alarm + InsideGroup2 + alarm + + + alarm + InsideGroup3 + alarm + + +
@@ -144,9 +146,11 @@

Select in a Form

alarm - - {{ city }} - + @for (city of cities; track city; let inx = $index) { + + {{ city }} + + } @@ -169,9 +173,11 @@

Select - dynamically change required

Fruit None - - {{fruit}} - + @for (fruit of fruits; track fruit) { + + {{fruit}} + + }
Selected: {{selected}}
Valid: {{model.valid}}
diff --git a/src/app/select/select.sample.ts b/src/app/select/select.sample.ts index f97e8349d9a..bf64a880d2b 100644 --- a/src/app/select/select.sample.ts +++ b/src/app/select/select.sample.ts @@ -1,6 +1,5 @@ import { Component, OnInit, ViewChildren, QueryList, ViewChild } from '@angular/core'; import { UntypedFormBuilder, UntypedFormGroup, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { NgFor } from '@angular/common'; import { IgxButtonDirective, IgxSelectComponent, IgxLabelDirective, IgxPrefixDirective, IgxIconComponent, IgxSelectItemComponent, IgxSelectHeaderDirective, IgxSelectFooterDirective, IgxSuffixDirective, IgxHintDirective, IgxSelectGroupComponent, IgxSwitchComponent, ISelectionEventArgs, CancelableEventArgs, HorizontalAlignment, VerticalAlignment, ConnectedPositioningStrategy, AbsoluteScrollStrategy } from 'igniteui-angular'; import { scaleInTop, scaleOutBottom } from 'igniteui-angular/animations'; import { SizeSelectorComponent } from '../size-selector/size-selector.component'; @@ -19,7 +18,6 @@ import { SizeSelectorComponent } from '../size-selector/size-selector.component' IgxPrefixDirective, IgxIconComponent, IgxSelectItemComponent, - NgFor, IgxSelectHeaderDirective, IgxSelectFooterDirective, IgxSuffixDirective, diff --git a/src/app/slider-showcase/slider-showcase.sample.ts b/src/app/slider-showcase/slider-showcase.sample.ts index 771e7eb63dc..862a693891d 100644 --- a/src/app/slider-showcase/slider-showcase.sample.ts +++ b/src/app/slider-showcase/slider-showcase.sample.ts @@ -127,14 +127,14 @@ export class SliderShowcaseSampleComponent { ) { this.propertyChangeService.setPanelConfig(this.panelConfig); - const { unsubscribe } = + const propertyChange = this.propertyChangeService.propertyChanges.subscribe( (properties) => { this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } private ticksOrientationMap = new Map( diff --git a/src/app/snackbar-showcase/snackbar-showcase.sample.ts b/src/app/snackbar-showcase/snackbar-showcase.sample.ts index e16074edfe2..f970c622166 100644 --- a/src/app/snackbar-showcase/snackbar-showcase.sample.ts +++ b/src/app/snackbar-showcase/snackbar-showcase.sample.ts @@ -57,13 +57,13 @@ export class SnackbarShowcaseSampleComponent { ) { this.propertyChangeService.setPanelConfig(this.panelConfig); - const { unsubscribe } = + const propertyChange = this.propertyChangeService.propertyChanges.subscribe( (properties) => { this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } } diff --git a/src/app/stepper/stepper.sample.ts b/src/app/stepper/stepper.sample.ts index 9cef9ee53a3..b9ac68ae705 100644 --- a/src/app/stepper/stepper.sample.ts +++ b/src/app/stepper/stepper.sample.ts @@ -212,13 +212,13 @@ export class IgxStepperSampleComponent { constructor(private destroyRef: DestroyRef) { this.pcs.setPanelConfig(this.panelConfig); - const { unsubscribe } = this.pcs.propertyChanges.subscribe( + const propertyChange = this.pcs.propertyChanges.subscribe( (properties) => { this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } // Reactive forms initialization diff --git a/src/app/styleguide/animations/animations.sample.html b/src/app/styleguide/animations/animations.sample.html index 24f62b2161d..b4b57ed1ba4 100644 --- a/src/app/styleguide/animations/animations.sample.html +++ b/src/app/styleguide/animations/animations.sample.html @@ -3,12 +3,11 @@

Animations categories

- -

{{ category }}

-
+ @for (category of animationsCategories; track category) { + +

{{ category }}

+
+ }
@@ -16,9 +15,11 @@

Animations categories

Animations

- -

{{ animation.name }}

-
+ @for (animation of animations; track animation) { + +

{{ animation.name }}

+
+ }
diff --git a/src/app/styleguide/animations/animations.sample.ts b/src/app/styleguide/animations/animations.sample.ts index 716f4e3a283..b161c21857e 100644 --- a/src/app/styleguide/animations/animations.sample.ts +++ b/src/app/styleguide/animations/animations.sample.ts @@ -1,5 +1,4 @@ import { AnimationReferenceMetadata } from '@angular/animations'; -import { NgFor } from '@angular/common'; import { Component, ViewChild } from '@angular/core'; import { AbsolutePosition, @@ -31,7 +30,7 @@ import { selector: 'app-animations-sample', styleUrls: ['animations.sample.scss'], templateUrl: 'animations.sample.html', - imports: [IgxListComponent, NgFor, IgxListItemComponent, IgxRippleDirective, IgxDialogComponent] + imports: [IgxListComponent, IgxListItemComponent, IgxRippleDirective, IgxDialogComponent] }) export class AnimationsSampleComponent { @ViewChild('dialog', { static: true, read: IgxDialogComponent }) diff --git a/src/app/styleguide/colors/color.sample.html b/src/app/styleguide/colors/color.sample.html index 53d880bef60..f68f875f295 100644 --- a/src/app/styleguide/colors/color.sample.html +++ b/src/app/styleguide/colors/color.sample.html @@ -2,14 +2,20 @@

Color Palettes

-
-
-

{{color.name}}

-
- {{variant}} -
+ @for (color of colors; track color) { +
+ @if (color.variants.length > 1) { +
+

{{color.name}}

+ @for (variant of color.variants; track variant) { +
+ {{variant}} +
+ } +
+ }
-
+ }
diff --git a/src/app/styleguide/colors/color.sample.ts b/src/app/styleguide/colors/color.sample.ts index a4905648057..dab6c1b0070 100644 --- a/src/app/styleguide/colors/color.sample.ts +++ b/src/app/styleguide/colors/color.sample.ts @@ -1,11 +1,10 @@ import { Component } from '@angular/core'; -import { NgFor, NgIf } from '@angular/common'; @Component({ selector: 'app-colors-sample', styleUrls: ['color.sample.scss'], templateUrl: 'color.sample.html', - imports: [NgFor, NgIf] + imports: [] }) export class ColorsSampleComponent { public colors = [ diff --git a/src/app/tabs-routing/tabs-routing-views.sample.ts b/src/app/tabs-routing/tabs-routing-views.sample.ts index 20c41786eee..207d07fd167 100644 --- a/src/app/tabs-routing/tabs-routing-views.sample.ts +++ b/src/app/tabs-routing/tabs-routing-views.sample.ts @@ -2,7 +2,6 @@ import { Component } from '@angular/core'; import { IgxIconComponent } from '../../../projects/igniteui-angular/src/lib/icon/icon.component'; import { IgxAvatarComponent } from '../../../projects/igniteui-angular/src/lib/avatar/avatar.component'; import { IgxRippleDirective } from '../../../projects/igniteui-angular/src/lib/directives/ripple/ripple.directive'; -import { NgFor } from '@angular/common'; import { IgxListItemComponent } from '../../../projects/igniteui-angular/src/lib/list/list-item.component'; import { IgxListComponent, IgxListThumbnailDirective, IgxListLineTitleDirective, IgxListLineSubTitleDirective, IgxListActionDirective } from '../../../projects/igniteui-angular/src/lib/list/list.component'; @@ -10,15 +9,17 @@ import { IgxListComponent, IgxListThumbnailDirective, IgxListLineTitleDirective, template: ` History - - -

{{contact.text}}

-

{{contact.phone}}

- phone -
+ @for (contact of contacts; track contact) { + + +

{{contact.text}}

+

{{contact.phone}}

+ phone +
+ }
`, - imports: [IgxListComponent, IgxListItemComponent, NgFor, IgxRippleDirective, IgxAvatarComponent, IgxListThumbnailDirective, IgxListLineTitleDirective, IgxListLineSubTitleDirective, IgxIconComponent, IgxListActionDirective] + imports: [IgxListComponent, IgxListItemComponent, IgxRippleDirective, IgxAvatarComponent, IgxListThumbnailDirective, IgxListLineTitleDirective, IgxListLineSubTitleDirective, IgxIconComponent, IgxListActionDirective] }) export class TabsRoutingView1Component { public contacts = [{ diff --git a/src/app/tabs-showcase/tabs-showcase.sample.ts b/src/app/tabs-showcase/tabs-showcase.sample.ts index 6f3506260c2..a3972df4333 100644 --- a/src/app/tabs-showcase/tabs-showcase.sample.ts +++ b/src/app/tabs-showcase/tabs-showcase.sample.ts @@ -93,13 +93,13 @@ export class TabsShowcaseSampleComponent implements OnInit { }, }); - const { unsubscribe } = this.pcs.propertyChanges.subscribe( + const propertyChange = this.pcs.propertyChanges.subscribe( (properties) => { this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } public ngOnInit() { diff --git a/src/app/time-picker/time-picker.sample.html b/src/app/time-picker/time-picker.sample.html index a7f2320550c..7da22ba5546 100644 --- a/src/app/time-picker/time-picker.sample.html +++ b/src/app/time-picker/time-picker.sample.html @@ -25,8 +25,10 @@

Time Picker with ngModel binding

- Value is outside the range. - + @if (model.errors?.minValue || model.errors?.maxValue) { + Value is outside the range. + + }
@@ -65,8 +67,8 @@

Time Picker with custom spin buttons

alarm - - + + delete expand_less diff --git a/src/app/time-picker/time-picker.sample.ts b/src/app/time-picker/time-picker.sample.ts index 7c8871b98ff..8f94c56d4f8 100644 --- a/src/app/time-picker/time-picker.sample.ts +++ b/src/app/time-picker/time-picker.sample.ts @@ -1,5 +1,4 @@ import { Component, ViewChild } from '@angular/core'; -import { NgIf } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { IgxTimePickerComponent, @@ -21,7 +20,7 @@ import { selector: 'app-time-picker-sample', styleUrls: ['time-picker.sample.scss'], templateUrl: 'time-picker.sample.html', - imports: [IgxTimePickerComponent, FormsModule, NgIf, IgxHintDirective, IgxButtonDirective, IgxPickerActionsDirective, IgxPickerToggleComponent, IgxPrefixDirective, IgxIconComponent, IgxPickerClearComponent, IgxSuffixDirective] + imports: [IgxTimePickerComponent, FormsModule, IgxHintDirective, IgxButtonDirective, IgxPickerActionsDirective, IgxPickerToggleComponent, IgxPrefixDirective, IgxIconComponent, IgxPickerClearComponent, IgxSuffixDirective] }) export class TimePickerSampleComponent { @ViewChild('tp', { read: IgxTimePickerComponent, static: true }) diff --git a/src/app/toast-showcase/toast-showcase.sample.ts b/src/app/toast-showcase/toast-showcase.sample.ts index 88230d968a8..fd0984fbf83 100644 --- a/src/app/toast-showcase/toast-showcase.sample.ts +++ b/src/app/toast-showcase/toast-showcase.sample.ts @@ -51,13 +51,13 @@ export class ToastShowcaseSampleComponent { ) { this.propertyChangeService.setPanelConfig(this.panelConfig); - const { unsubscribe } = + const propertyChange = this.propertyChangeService.propertyChanges.subscribe( (properties) => { this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } } 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 4542c3cf346..437a82fcaaf 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,11 +1,13 @@
- - + @for (c of columns; track c) { + + + } 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 f5a8e6e2aff..e920daa74fa 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,5 +1,4 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { NgFor } from '@angular/common'; import { ColumnPinningPosition, IgxActionStripComponent, IgxButtonDirective, IgxColumnComponent, IgxGridEditingActionsComponent, IgxGridPinningActionsComponent, IgxInputDirective, IgxInputGroupComponent, IgxLabelDirective, IgxTreeGridComponent, RowPinningPosition } from 'igniteui-angular'; @@ -7,7 +6,7 @@ import { ColumnPinningPosition, IgxActionStripComponent, IgxButtonDirective, Igx selector: 'app-tree-grid-add-row', styleUrls: ['tree-grid-add-row.sample.scss'], templateUrl: `tree-grid-add-row.sample.html`, - imports: [IgxTreeGridComponent, NgFor, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent, IgxGridEditingActionsComponent, IgxButtonDirective, IgxInputGroupComponent, IgxInputDirective, IgxLabelDirective] + imports: [IgxTreeGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent, IgxGridEditingActionsComponent, IgxButtonDirective, IgxInputGroupComponent, IgxInputDirective, IgxLabelDirective] }) export class TreeGridAddRowSampleComponent implements OnInit { @ViewChild(IgxTreeGridComponent) diff --git a/src/app/tree-grid-flat-data/tree-grid-flat-data.sample.html b/src/app/tree-grid-flat-data/tree-grid-flat-data.sample.html index bb531374a6d..e0355553bfc 100644 --- a/src/app/tree-grid-flat-data/tree-grid-flat-data.sample.html +++ b/src/app/tree-grid-flat-data/tree-grid-flat-data.sample.html @@ -9,11 +9,13 @@ - - + @for (c of columns; track c) { + + + } @@ -26,7 +28,9 @@ - + @if (paging) { + + }
diff --git a/src/app/tree-grid-flat-data/tree-grid-flat-data.sample.ts b/src/app/tree-grid-flat-data/tree-grid-flat-data.sample.ts index 7a2cdac729a..8d7fd37a3b5 100644 --- a/src/app/tree-grid-flat-data/tree-grid-flat-data.sample.ts +++ b/src/app/tree-grid-flat-data/tree-grid-flat-data.sample.ts @@ -1,5 +1,4 @@ import { Component, ViewChild, OnInit, HostBinding } from '@angular/core'; -import { NgFor, NgIf } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { GridSearchBoxComponent } from '../grid-search-box/grid-search-box.component'; @@ -23,7 +22,7 @@ export class MySummaryOperand extends IgxSummaryOperand { selector: 'app-tree-grid-flat-data-sample', styleUrls: ['tree-grid-flat-data.sample.scss'], templateUrl: 'tree-grid-flat-data.sample.html', - imports: [IgxButtonGroupComponent, IgxButtonDirective, IgxTreeGridComponent, NgFor, NgIf, IgxColumnComponent, IgxGridToolbarComponent, GridSearchBoxComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarExporterComponent, IgxExcelTextDirective, IgxCSVTextDirective, IgxPaginatorComponent, IgxSwitchComponent, FormsModule] + imports: [IgxButtonGroupComponent, IgxButtonDirective, IgxTreeGridComponent, IgxColumnComponent, IgxGridToolbarComponent, GridSearchBoxComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarExporterComponent, IgxExcelTextDirective, IgxCSVTextDirective, IgxPaginatorComponent, IgxSwitchComponent, FormsModule] }) export class TreeGridFlatDataSampleComponent implements OnInit { @HostBinding('style.--ig-size') diff --git a/src/app/tree-grid-groupby/tree-grid-groupby.sample.html b/src/app/tree-grid-groupby/tree-grid-groupby.sample.html index a2bb4a72099..c83a14652da 100644 --- a/src/app/tree-grid-groupby/tree-grid-groupby.sample.html +++ b/src/app/tree-grid-groupby/tree-grid-groupby.sample.html @@ -1,7 +1,9 @@
- Hide Grouped Columns + @if (groupArea) { + Hide Grouped Columns + }
@@ -35,10 +37,12 @@ - - + @for (c of columns; track c) { + + + }
diff --git a/src/app/tree-grid-groupby/tree-grid-groupby.sample.ts b/src/app/tree-grid-groupby/tree-grid-groupby.sample.ts index fa5a4700e92..466eb1ce7d5 100644 --- a/src/app/tree-grid-groupby/tree-grid-groupby.sample.ts +++ b/src/app/tree-grid-groupby/tree-grid-groupby.sample.ts @@ -1,5 +1,4 @@ import { Component, ViewChild, OnInit, HostBinding } from '@angular/core'; -import { NgIf, NgFor } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { SAMPLE_DATA } from '../shared/sample-data'; @@ -11,7 +10,7 @@ import { IgxButtonGroupComponent, IgxSwitchComponent, IgxTreeGridComponent, IgxT selector: 'app-tree-grid-groupby-sample', styleUrls: ['tree-grid-groupby.sample.scss'], templateUrl: 'tree-grid-groupby.sample.html', - imports: [IgxButtonGroupComponent, NgIf, IgxSwitchComponent, FormsModule, IgxTreeGridComponent, IgxTreeGridGroupByAreaComponent, IgxColumnComponent, NgFor, IgxTreeGridGroupingPipe] + imports: [IgxButtonGroupComponent, IgxSwitchComponent, FormsModule, IgxTreeGridComponent, IgxTreeGridGroupByAreaComponent, IgxColumnComponent, IgxTreeGridGroupingPipe] }) export class TreeGridGroupBySampleComponent implements OnInit { diff --git a/src/app/tree-grid-load-on-demand/tree-grid-load-on-demand.sample.html b/src/app/tree-grid-load-on-demand/tree-grid-load-on-demand.sample.html index a55cca09f08..c73be3efb74 100644 --- a/src/app/tree-grid-load-on-demand/tree-grid-load-on-demand.sample.html +++ b/src/app/tree-grid-load-on-demand/tree-grid-load-on-demand.sample.html @@ -23,15 +23,19 @@

Primary/Foreign key

- - + @for (c of columns; track c) { + + + } - + @if (paging) { + + }
@@ -77,10 +81,12 @@

ChildData key

- - + @for (c of columns; track c) { + + + }
diff --git a/src/app/tree-grid-load-on-demand/tree-grid-load-on-demand.sample.ts b/src/app/tree-grid-load-on-demand/tree-grid-load-on-demand.sample.ts index cb51f4f9bb5..0214c9e4209 100644 --- a/src/app/tree-grid-load-on-demand/tree-grid-load-on-demand.sample.ts +++ b/src/app/tree-grid-load-on-demand/tree-grid-load-on-demand.sample.ts @@ -1,5 +1,4 @@ import { Component, ViewChild, OnInit, HostBinding } from '@angular/core'; -import { NgFor, NgIf } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { TreeGridLoadOnDemandService } from './tree-grid-load-on-demand.service'; @@ -25,7 +24,7 @@ export class MySummaryOperand extends IgxSummaryOperand { selector: 'app-tree-grid-load-on-demand-sample', styleUrls: ['tree-grid-load-on-demand.sample.scss'], templateUrl: 'tree-grid-load-on-demand.sample.html', - imports: [IgxButtonGroupComponent, IgxTreeGridComponent, IgxGridToolbarComponent, GridSearchBoxComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarExporterComponent, IgxExcelTextDirective, IgxCSVTextDirective, NgFor, IgxColumnComponent, IgxSwitchComponent, FormsModule, NgIf, IgxPaginatorComponent, IgxButtonDirective] + imports: [IgxButtonGroupComponent, IgxTreeGridComponent, IgxGridToolbarComponent, GridSearchBoxComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarExporterComponent, IgxExcelTextDirective, IgxCSVTextDirective, IgxColumnComponent, IgxSwitchComponent, FormsModule, IgxPaginatorComponent, IgxButtonDirective] }) export class TreeGridLoadOnDemandSampleComponent implements OnInit { @HostBinding('style.--ig-size') diff --git a/src/app/tree-grid/tree-grid.sample.html b/src/app/tree-grid/tree-grid.sample.html index 105a2317341..364a0a14454 100644 --- a/src/app/tree-grid/tree-grid.sample.html +++ b/src/app/tree-grid/tree-grid.sample.html @@ -19,9 +19,12 @@ - - + + @if (paging) { + + }
@@ -30,9 +33,11 @@
- + @for (item of selectionModes; track item) { + {{ item }} - + + } diff --git a/src/app/tree-grid/tree-grid.sample.ts b/src/app/tree-grid/tree-grid.sample.ts index 06f50495e17..5fe222208f8 100644 --- a/src/app/tree-grid/tree-grid.sample.ts +++ b/src/app/tree-grid/tree-grid.sample.ts @@ -1,5 +1,4 @@ import { Component, ViewChild, OnInit, HostBinding } from '@angular/core'; -import { NgIf, NgFor } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { HIERARCHICAL_SAMPLE_DATA } from '../shared/sample-data'; @@ -12,7 +11,7 @@ import { IgxButtonGroupComponent, IgxTreeGridComponent, IgxGridToolbarComponent, selector: 'app-tree-grid-sample', styleUrls: ['tree-grid.sample.scss'], templateUrl: 'tree-grid.sample.html', - imports: [IgxButtonGroupComponent, IgxTreeGridComponent, IgxGridToolbarComponent, GridSearchBoxComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarExporterComponent, IgxExcelTextDirective, IgxCSVTextDirective, NgIf, IgxPaginatorComponent, IgxSwitchComponent, FormsModule, IgxButtonDirective, IgxToggleActionDirective, IgxDropDownItemNavigationDirective, IgxDropDownComponent, NgFor, IgxDropDownItemComponent] + imports: [IgxButtonGroupComponent, IgxTreeGridComponent, IgxGridToolbarComponent, GridSearchBoxComponent, IgxGridToolbarActionsComponent, IgxGridToolbarPinningComponent, IgxGridToolbarHidingComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarExporterComponent, IgxExcelTextDirective, IgxCSVTextDirective, IgxPaginatorComponent, IgxSwitchComponent, FormsModule, IgxButtonDirective, IgxToggleActionDirective, IgxDropDownItemNavigationDirective, IgxDropDownComponent, IgxDropDownItemComponent] }) export class TreeGridSampleComponent implements OnInit { diff --git a/src/app/tree-showcase/tree-showcase.sample.ts b/src/app/tree-showcase/tree-showcase.sample.ts index c47e10b19ce..1b43895b2b3 100644 --- a/src/app/tree-showcase/tree-showcase.sample.ts +++ b/src/app/tree-showcase/tree-showcase.sample.ts @@ -73,14 +73,14 @@ export class TreeShowcaseSampleComponent { this.data = structuredClone(HIERARCHICAL_SAMPLE_DATA); this.propertyChangeService.setPanelConfig(this.panelConfig); - const { unsubscribe } = + const propertyChange = this.propertyChangeService.propertyChanges.subscribe( (properties) => { this.properties = properties; } ); - this.destroyRef.onDestroy(() => unsubscribe); + this.destroyRef.onDestroy(() => propertyChange.unsubscribe()); } public angSelection = IgxTreeSelectionType.None; diff --git a/src/app/tree/tree.sample.html b/src/app/tree/tree.sample.html index 30c85956e74..7b08d641a9b 100644 --- a/src/app/tree/tree.sample.html +++ b/src/app/tree/tree.sample.html @@ -71,37 +71,51 @@ Disabled node Load on demand - - {{ item.CompanyName }} - + @for (item of (asyncItems | async) || [{ ID: 'dummy', CompanyName: ''}]; track item) { + + {{ item.CompanyName }} + + } Disabled Link Link children - - - - + @for (node of [].constructor(7); track $index; let i = $index) { + + + @for (node of [].constructor(2); track $index; let i = $index) { + + + + } - + } - -
- face - {{ node.ID }} -
- NA_FRANCO_DETETO - - {{ child.ID }} - - {{ leafchild.ID }} - + @for (node of data; track node) { + +
+ face + {{ node.ID }} +
+ @if (node.ID === 'FRANS') { + NA_FRANCO_DETETO + } + @for (child of node.ChildCompanies; track child) { + + {{ child.ID }} + @for (leafchild of child.ChildCompanies; track leafchild) { + + {{ leafchild.ID }} + + } + + }
-
+ } Link to Google @@ -114,15 +128,21 @@

IgxTree 2: The Branching

- - {{ node.CompanyName }} - - {{ child.CompanyName }} - - {{ leafchild.CompanyName }} - + @for (node of data; track node) { + + {{ node.CompanyName }} + @for (child of node.ChildCompanies; track child) { + + {{ child.CompanyName }} + @for (leafchild of child.ChildCompanies; track leafchild) { + + {{ leafchild.CompanyName }} + + } + + } - + }
diff --git a/src/app/tree/tree.sample.ts b/src/app/tree/tree.sample.ts index d4bd5e3ae9b..28ed9c02a11 100644 --- a/src/app/tree/tree.sample.ts +++ b/src/app/tree/tree.sample.ts @@ -1,5 +1,5 @@ import { useAnimation } from '@angular/animations'; -import { NgFor, NgTemplateOutlet, NgIf, AsyncPipe } from '@angular/common'; +import { NgTemplateOutlet, AsyncPipe } from '@angular/common'; import { AfterViewInit, ChangeDetectorRef, Component, ViewChild } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { @@ -16,7 +16,7 @@ import { IgxInputDirective, IgxInputGroupComponent, IgxLabelDirective, - IgxLayoutDirective, + IgxLayoutDirective, IgxSwitchComponent, IgxTreeNodeLinkDirective, IgxTreeExpandIndicatorDirective @@ -61,12 +61,10 @@ interface CompanyData { IgxButtonGroupComponent, IgxTreeComponent, IgxTreeNodeComponent, - NgFor, IgxTreeNodeLinkDirective, IgxTreeExpandIndicatorDirective, NgTemplateOutlet, IgxIconComponent, - NgIf, AsyncPipe, SizeSelectorComponent ] diff --git a/src/app/virtual-for-directive/virtual-for.sample.html b/src/app/virtual-for-directive/virtual-for.sample.html index 215a8e6ae79..c6b05e44e0d 100644 --- a/src/app/virtual-for-directive/virtual-for.sample.html +++ b/src/app/virtual-for-directive/virtual-for.sample.html @@ -91,7 +91,7 @@

Variable heights

Even Variable

-