diff --git a/projects/igniteui-angular/input-group/README.md b/projects/igniteui-angular/input-group/README.md index 0a3ac91ef35..6d35c287a93 100644 --- a/projects/igniteui-angular/input-group/README.md +++ b/projects/igniteui-angular/input-group/README.md @@ -47,7 +47,7 @@ Ignite UI for Angular Hint provides a helper text placed below the input. The hi | Name | Description | | :--- | :--- | -| type | How the input will be styled. The allowed values are line, box, border and search. The default is line.| +| type | How the input will be styled. The allowed values are line, box, border and search. The default is box.| | theme | Allows the user to change the theme of the input group. | | position | **`Hint` API**. Where the hint will be placed. The allowed values are start and end. The default value is start. | diff --git a/projects/igniteui-angular/input-group/src/input-group/input-group.component.spec.ts b/projects/igniteui-angular/input-group/src/input-group/input-group.component.spec.ts index 12ad887770e..b10d4829a94 100644 --- a/projects/igniteui-angular/input-group/src/input-group/input-group.component.spec.ts +++ b/projects/igniteui-angular/input-group/src/input-group/input-group.component.spec.ts @@ -37,8 +37,8 @@ describe('IgxInputGroup', () => { const igxInputGroup = fixture.componentInstance.igxInputGroup; tick(); fixture.detectChanges(); - // the default type should be line - testInputGroupType('line', igxInputGroup, inputGroupElement); + // the default type should be box + testInputGroupType('box', igxInputGroup, inputGroupElement); })); it('Initializes an input group with type box.', fakeAsync(() => { diff --git a/projects/igniteui-angular/input-group/src/input-group/input-group.component.ts b/projects/igniteui-angular/input-group/src/input-group/input-group.component.ts index 58eca803e1e..c1b43bf59da 100644 --- a/projects/igniteui-angular/input-group/src/input-group/input-group.component.ts +++ b/projects/igniteui-angular/input-group/src/input-group/input-group.component.ts @@ -187,7 +187,7 @@ export class IgxInputGroupComponent implements IgxInputGroupBase, AfterContentCh /** * Returns the type of the `IgxInputGroupComponent`. How the input is styled. - * The default is `line`. + * The default is `box`. * ```typescript * @ViewChild("MyInputGroup") * public inputGroup: IgxInputGroupComponent; @@ -197,7 +197,7 @@ export class IgxInputGroupComponent implements IgxInputGroupBase, AfterContentCh * ``` */ public get type() { - return this._type || this._inputGroupType || 'line'; + return this._type || this._inputGroupType || 'box'; } /** diff --git a/projects/igniteui-angular/migrations/migration-collection.json b/projects/igniteui-angular/migrations/migration-collection.json index 7fae5e49350..526b573700d 100644 --- a/projects/igniteui-angular/migrations/migration-collection.json +++ b/projects/igniteui-angular/migrations/migration-collection.json @@ -289,6 +289,11 @@ "version": "21.2.2", "description": "Updates Ignite UI for Angular from v21.2.0 to v21.2.2", "factory": "./update-21_2_2" + }, + "migration-57": { + "version": "22.0.0", + "description": "Updates Ignite UI for Angular from v21.2.x to v22.0.0", + "factory": "./update-22_0_0" } } } diff --git a/projects/igniteui-angular/migrations/update-22_0_0/index.spec.ts b/projects/igniteui-angular/migrations/update-22_0_0/index.spec.ts new file mode 100644 index 00000000000..43a98882041 --- /dev/null +++ b/projects/igniteui-angular/migrations/update-22_0_0/index.spec.ts @@ -0,0 +1,117 @@ +import * as path from 'path'; + +import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing/index.js'; +import { setupTestTree } from '../common/setup.spec'; + +const version = '22.0.0'; + +describe(`Update to ${version}`, () => { + let appTree: UnitTestTree; + const schematicRunner = new SchematicTestRunner('ig-migrate', path.join(__dirname, '../migration-collection.json')); + + beforeEach(() => { + appTree = setupTestTree(); + }); + + const migrationName = 'migration-57'; + + it('should add type="line" to igx-input-group without explicit type', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + `` + ); + + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(``); + }); + + it('should add type="line" to igx-select without explicit type', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + `Option` + ); + + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(`Option`); + }); + + it('should add type="line" to igx-date-picker without explicit type', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + `` + ); + + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(``); + }); + + it('should add type="line" to igx-date-range-picker without explicit type', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + `` + ); + + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(``); + }); + + it('should add type="line" to igx-time-picker without explicit type', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + `` + ); + + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(``); + }); + + it('should NOT modify igx-input-group that already has type attribute', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + `` + ); + + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(``); + }); + + it('should NOT modify igx-input-group that already has [type] binding', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + `` + ); + + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(``); + }); + + it('should handle multiple components in the same template', async () => { + appTree.create( + `/testSrc/appPrefix/component/test.component.html`, + ` + +` + ); + + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(` + +`); + }); +}); diff --git a/projects/igniteui-angular/migrations/update-22_0_0/index.ts b/projects/igniteui-angular/migrations/update-22_0_0/index.ts new file mode 100644 index 00000000000..c87176922b3 --- /dev/null +++ b/projects/igniteui-angular/migrations/update-22_0_0/index.ts @@ -0,0 +1,76 @@ +import type { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; +import { UpdateChanges } from '../common/UpdateChanges'; +import { + FileChange, + findElementNodes, + getSourceOffset, + hasAttribute, + parseFile +} from '../common/util'; + +const version = '22.0.0'; + +export default (): Rule => async (host: Tree, context: SchematicContext) => { + context.logger.info( + `Applying migration for Ignite UI for Angular to version ${version}` + ); + + const { HtmlParser, Element } = await import('@angular/compiler'); + + const update = new UpdateChanges(__dirname, host, context); + const changes = new Map(); + const parser = new HtmlParser(); + + const applyChanges = () => { + for (const [path, fileChanges] of changes.entries()) { + let content = host.read(path)!.toString(); + fileChanges + .sort((a, b) => b.position - a.position) + .forEach((c) => { + content = c.apply(content); + }); + host.overwrite(path, content); + } + }; + + const addChange = (path: string, change: FileChange) => { + if (!changes.has(path)) { + changes.set(path, []); + } + changes.get(path)!.push(change); + }; + + // All form components that default to 'line' prior to this version + const TAGS = [ + 'igx-input-group', + 'igx-select', + 'igx-date-picker', + 'igx-date-range-picker', + 'igx-time-picker' + ]; + + const TYPE_ATTRS = ['type', '[type]']; + + for (const path of update.templateFiles) { + const root = parseFile(parser, host, path); + const nodes = findElementNodes(root, TAGS); + + for (const node of nodes) { + if (!(node instanceof Element)) continue; + + // Skip if the element already has an explicit type binding + if (hasAttribute(node, TYPE_ATTRS)) continue; + + const offset = getSourceOffset(node); + const file = offset.file; + + // Insert type="line" right after the tag name in the start tag + // e.g., { expect(select.disabled).toBeFalsy(); expect(select.placeholder).toEqual('Choose a city'); expect(select.value).toBeNull(); - // Default type will be set - currently 'line' - expect(select.type).toEqual('line'); + // Default type will be set - currently 'box' + expect(select.type).toEqual('box'); expect(select.overlaySettings).toBeUndefined(); expect(select.items).toBeDefined(); // Reset input values @@ -461,16 +461,10 @@ describe('igxSelect', () => { it('should render input type properly', fakeAsync(() => { const inputGroup = fixture.debugElement.query(By.css('.' + CSS_CLASS_INPUT_GROUP)); - // Default type will be set - currently 'line' - expect(select.type).toEqual('line'); - expect(inputGroup.nativeElement.classList.contains(CSS_CLASS_INPUT_GROUP_BOX)).toBeFalsy(); - expect(inputGroup.nativeElement.classList.contains(CSS_CLASS_INPUT_GROUP_BORDER)).toBeFalsy(); - select.type = 'box'; - fixture.detectChanges(); - tick(); - fixture.detectChanges(); - + // Default type will be set - currently 'box' + expect(select.type).toEqual('box'); expect(inputGroup.nativeElement.classList.contains(CSS_CLASS_INPUT_GROUP_BOX)).toBeTruthy(); + expect(inputGroup.nativeElement.classList.contains(CSS_CLASS_INPUT_GROUP_BORDER)).toBeFalsy(); select.type = 'border'; fixture.detectChanges(); tick(); diff --git a/projects/igniteui-angular/select/src/select/select.component.ts b/projects/igniteui-angular/select/src/select/select.component.ts index 4a3a8031caa..63ae442d0f1 100644 --- a/projects/igniteui-angular/select/src/select/select.component.ts +++ b/projects/igniteui-angular/select/src/select/select.component.ts @@ -289,14 +289,14 @@ export class IgxSelectComponent extends IgxDropDownComponent implements IgxSelec /** * Sets how the select will be styled. - * The allowed values are `line`, `box` and `border`. The input-group default is `line`. + * The allowed values are `line`, `box` and `border`. Defaults to `box` if no input-group type is set. * ```html - * + * * ``` */ @Input() public get type(): IgxInputGroupType { - return this._type || this._inputGroupType || 'line'; + return this._type || this._inputGroupType || 'box'; } public set type(val: IgxInputGroupType) {