Skip to content

Commit b96c763

Browse files
feat(card): implement start & end directives (#12777)
* feat(card): implement start & end directives --------- Co-authored-by: Simeon Simeonoff <[email protected]>
1 parent b2f08b3 commit b96c763

File tree

11 files changed

+199
-87
lines changed

11 files changed

+199
-87
lines changed

CHANGELOG.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,32 @@ All notable changes for each version of this project will be documented in this
1212
- `IgxColumnComponent`
1313
- Added `currRec` and `groupRec` parameters to the `groupingComparer` function that give access to the all properties of the compared records.
1414
- `IgxOverlayService`
15-
-A new event `contentAppending` is introduced - the event is emitted before the content is appended to the overlay. The event is emitted with `OverlayEventArgs` arguments and is not cancellable.
15+
- A new event `contentAppending` is introduced - the event is emitted before the content is appended to the overlay. The event is emitted with `OverlayEventArgs` arguments and is not cancellable.
16+
- `IgxCard`
17+
- Buttons and icons slotted in the `igx-card-actions` can now be explicitly arranged to the start/end of the layout. To position components on either side users can take advantage of the newly added directives: `igxStart` - aligns items to the start and `igxEnd` - aligns items on the end of the card actions area.
18+
- The `reverse` property has been deprecated and will be removed in a future version.
19+
20+
- Code example:
21+
22+
```html
23+
<igx-card>
24+
<igx-card-header>
25+
<h3>Title</h3>
26+
</igx-card-header>
27+
<igx-card-content>
28+
Card Content
29+
</igx-card-content>
30+
31+
<!-- Rearrange items using igxStart and igxEnd directives -->
32+
<igx-card-actions>
33+
<igx-icon igxStart>drag_indicator</igx-icon>
34+
<button igxButton="icon" igxStart>
35+
<igx-icon>favorite</igx-icon>
36+
</button>
37+
<button igxButton igxEnd>Button</button>
38+
</igx-card-actions>
39+
</igx-card>
40+
```
1641

1742
### General
1843
- `IgxPivotGrid`

projects/igniteui-angular/migrations/update-15_1_0/index.spec.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,36 @@ describe(`Update to ${version}`, () => {
139139
);
140140
});
141141

142+
it('should append igxStart and igxEnd directives to the child elements of the igx-card-actions', async () => {
143+
appTree.create(`/testSrc/appPrefix/component/test.component.html`,
144+
`
145+
<igx-card-actions>
146+
<span igxButton>Span</span>
147+
<button igxButton>Button</button>
148+
<button igxButton="icon">
149+
<igx-icon>favorite</igx-icon>
150+
</button>
151+
<igx-icon>drag_indicator</igx-icon>
152+
</igx-card-actions>
153+
`
154+
);
155+
156+
const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree);
157+
158+
expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(
159+
`
160+
<igx-card-actions>
161+
<span igxButton igxStart>Span</span>
162+
<button igxButton igxStart>Button</button>
163+
<button igxButton="icon" igxEnd>
164+
<igx-icon>favorite</igx-icon>
165+
</button>
166+
<igx-icon igxEnd>drag_indicator</igx-icon>
167+
</igx-card-actions>
168+
`
169+
);
170+
});
171+
142172
it('should rename the $size property to the $scrollbar-size', async () => {
143173
appTree.create(
144174
`/testSrc/appPrefix/component/test.component.scss`,

projects/igniteui-angular/migrations/update-15_1_0/index.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,79 @@ import {
33
SchematicContext,
44
Tree
55
} from '@angular-devkit/schematics';
6+
import { Element } from '@angular/compiler';
7+
import { nativeImport } from '../common/import-helper.js';
68
import { Options } from '../../schematics/interfaces/options';
79
import { BoundPropertyObject, InputPropertyType, UpdateChanges } from '../common/UpdateChanges';
10+
import { FileChange, findElementNodes, getAttribute, getSourceOffset, parseFile, hasAttribute } from '../common/util';
811

912
const version = '15.1.0';
1013

1114
export default (options: Options): Rule => async (host: Tree, context: SchematicContext) => {
1215
context.logger.info(`Applying migration for Ignite UI for Angular to version ${version}`);
1316

17+
const { HtmlParser } = await nativeImport('@angular/compiler') as typeof import('@angular/compiler');
1418
const update = new UpdateChanges(__dirname, host, context);
19+
const cardsToMigrate = new Set<any>();
20+
const CARD_ACTIONS = ['igx-card-actions'];
21+
const prop = ['igxButton'];
22+
const changes = new Map<string, FileChange[]>();
23+
24+
const applyChanges = () => {
25+
for (const [path, change] of changes.entries()) {
26+
let buffer = host.read(path).toString();
27+
28+
change.sort((c, c1) => c.position - c1.position)
29+
.reverse()
30+
.forEach(c => buffer = c.apply(buffer));
31+
32+
host.overwrite(path, buffer);
33+
}
34+
};
35+
36+
const addChange = (path: string, change: FileChange) => {
37+
if (changes.has(path)) {
38+
changes.get(path).push(change);
39+
} else {
40+
changes.set(path, [change]);
41+
}
42+
};
43+
44+
const getChildren = (parent: Element, buttons: any[], icons: any[]) => {
45+
const cardButtons = parent.children.filter(btn => (btn as Element).attrs !== undefined && hasAttribute(btn as Element, prop));
46+
const cardIcons = parent.children.filter(btn => (btn as Element).name === 'igx-icon');
47+
buttons.push(...cardButtons);
48+
icons.push(...cardIcons);
49+
}
50+
51+
for (const path of update.templateFiles) {
52+
cardsToMigrate.clear();
53+
const cardActions = findElementNodes(parseFile(new HtmlParser(), host, path), CARD_ACTIONS);
54+
cardActions.forEach(card => {
55+
const card_action_elem = card as Element;
56+
const buttons: any[] = [];
57+
const icons: any[] = [];
58+
getChildren(card_action_elem, buttons, icons);
59+
60+
icons.map(node =>getSourceOffset(node as Element))
61+
.forEach(offset => {
62+
const { startTag, file } = offset;
63+
addChange(file.url, new FileChange(startTag.end - 1, ' igxEnd'));
64+
})
65+
66+
buttons.map(node => getSourceOffset(node as Element))
67+
.forEach(offset => {
68+
const { startTag, file, node } = offset;
69+
const { value } = getAttribute(node, prop)[0];
70+
if (value === 'icon') {
71+
addChange(file.url, new FileChange(startTag.end - 1, ' igxEnd'));
72+
} else {
73+
addChange(file.url, new FileChange(startTag.end - 1, ' igxStart'));
74+
}
75+
});
76+
});
77+
}
78+
1579
update.shouldInvokeLS = options['shouldInvokeLS'];
1680
update.addValueTransform('roundShape_is_deprecated', (args: BoundPropertyObject): void => {
1781
args.bindingType = InputPropertyType.STRING;
@@ -27,5 +91,7 @@ export default (options: Options): Rule => async (host: Tree, context: Schematic
2791
args.value += ` ? 'circle' : 'square' `;
2892
}
2993
});
94+
95+
applyChanges();
3096
update.applyChanges();
3197
};
Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
<div class="igx-card-actions__icons">
2-
<ng-content select="igx-icon, [igxButton='icon']"></ng-content>
1+
<div #buttons class="igx-card-actions__start">
2+
<ng-content select="[igxStart], [igxButton]:not([igxButton='icon']):not([igxEnd])"></ng-content>
33
</div>
44

5-
<div #buttons class="igx-card-actions__buttons">
6-
<ng-content select="[igxButton]"></ng-content>
7-
</div>
8-
9-
105
<ng-content></ng-content>
6+
7+
<div class="igx-card-actions__end">
8+
<ng-content select="[igxEnd], [igxButton='icon']:not([igxStart]), igx-icon:not([igxStart])"></ng-content>
9+
</div>

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

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,9 @@ export type IgxCardActionsLayout = (typeof IgxCardActionsLayout)[keyof typeof Ig
283283
export class IgxCardActionsComponent implements OnInit, OnChanges {
284284
/**
285285
* An @Input property that sets the layout style of the actions.
286-
* By default icons and icon buttons, as well as regular buttons
287-
* are split into two containers, which are then positioned on both ends
288-
* of the card-actions area.
289-
* You can justify the elements in those groups so they are positioned equally
290-
* from one another taking up all the space available along the card actions axis.
286+
* You can justify the elements slotted in the igx-card-action container
287+
* so that they are positioned equally from one another taking up all the
288+
* space available along the card actions axis.
291289
*
292290
* @example
293291
* ```html
@@ -316,12 +314,9 @@ export class IgxCardActionsComponent implements OnInit, OnChanges {
316314
}
317315

318316
/**
319-
* An @Input property that sets order of the buttons the actions area.
320-
* By default all icons/icon buttons are placed at the end of the action
321-
* area. Any regular buttons(flat, raised) will appear before the icons/icon buttons
322-
* placed in the actions area.
323-
* If you want to reverse their positions so that icons appear first, use the `reverse`
324-
* attribute.
317+
* @deprecated in version 15.1.0.
318+
*
319+
* An @Input property that reverses the order of the buttons in the actions area.
325320
*
326321
* @example
327322
* ```html

projects/igniteui-angular/src/lib/card/card.spec.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ describe('Card', () => {
5252
get reverse() {
5353
return `${this.base}--reverse`;
5454
},
55-
get icons() {
56-
return `${this.base}__icons`;
55+
get end() {
56+
return `${this.base}__end`;
5757
},
58-
get buttons() {
59-
return `${this.base}__buttons`;
58+
get start() {
59+
return `${this.base}__start`;
6060
}
6161
},
6262
media: `${baseClass}__media`
@@ -230,8 +230,8 @@ describe('Card', () => {
230230

231231
const actionsElement = fixture.debugElement.query(By.css('igx-card-actions'));
232232

233-
const buttons = actionsElement.query(By.css(`.${classes.actions.buttons}`)).nativeElement;
234-
const icons = actionsElement.query(By.css(`.${classes.actions.icons}`)).nativeElement;
233+
const buttons = actionsElement.query(By.css(`.${classes.actions.start}`)).nativeElement;
234+
const icons = actionsElement.query(By.css(`.${classes.actions.end}`)).nativeElement;
235235

236236
const buttonsOrder = window.getComputedStyle(buttons).getPropertyValue('order');
237237
const iconsOrder = window.getComputedStyle(icons).getPropertyValue('order');
@@ -247,8 +247,8 @@ describe('Card', () => {
247247
const actionsInstance = fixture.componentInstance.actions;
248248
const actionsElement = fixture.debugElement.query(By.css('igx-card-actions'));
249249

250-
const buttons = actionsElement.query(By.css(`.${classes.actions.buttons}`)).nativeElement;
251-
const icons = actionsElement.query(By.css(`.${classes.actions.icons}`)).nativeElement;
250+
const buttons = actionsElement.query(By.css(`.${classes.actions.start}`)).nativeElement;
251+
const icons = actionsElement.query(By.css(`.${classes.actions.end}`)).nativeElement;
252252

253253
actionsInstance.reverse = true;
254254
fixture.detectChanges();
@@ -296,8 +296,8 @@ class CardWithHeaderComponent { }
296296
<igx-card-content>Test Content</igx-card-content>
297297
298298
<igx-card-actions>
299-
<button igxButton>Test</button>
300-
<button igxButton="icon">
299+
<button igxButton igxStart>Test</button>
300+
<button igxButton="icon" igxEnd>
301301
<igx-icon>home</igx-icon>
302302
</button>
303303
</igx-card-actions>
@@ -310,8 +310,8 @@ class VerticalCardComponent {
310310
@Component({
311311
template: `<igx-card [horizontal]="true">
312312
<igx-card-actions>
313-
<button igxButton>Test</button>
314-
<button igxButton="icon">
313+
<button igxButton igxStart>Test</button>
314+
<button igxButton="icon" igxEnd>
315315
<igx-icon>home</igx-icon>
316316
</button>
317317
</igx-card-actions>

projects/igniteui-angular/src/lib/core/styles/components/card/_card-component.scss

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,12 @@
7777
@include b(igx-card-actions) {
7878
@extend %igx-card-actions !optional;
7979

80-
@include e(icons) {
81-
@extend %igx-card-actions__icons !optional;
80+
@include e(start) {
81+
@extend %igx-card-actions__start !optional;
8282
}
8383

84-
@include e(buttons) {
85-
@extend %igx-card-actions__buttons !optional;
84+
@include e(end) {
85+
@extend %igx-card-actions__end !optional;
8686
}
8787

8888
@include e(igroup) {
@@ -106,42 +106,42 @@
106106
@include m(vertical) {
107107
@extend %igx-card-actions--vertical !optional;
108108

109-
@include e(icons) {
110-
@extend %igx-card-actions__icons--vertical !optional;
109+
@include e(start) {
110+
@extend %igx-card-actions__start--vertical !optional;
111111
}
112112

113-
@include e(buttons) {
114-
@extend %igx-card-actions__buttons--vertical !optional;
113+
@include e(end) {
114+
@extend %igx-card-actions__end--vertical !optional;
115115
}
116116
}
117117

118118
@include m(reverse) {
119-
@include e(icons) {
120-
@extend %igx-card-actions__icons--reverse !optional;
119+
@include e(start) {
120+
@extend %igx-card-actions__start--reverse !optional;
121121
}
122122

123-
@include e(buttons) {
124-
@extend %igx-card-actions__buttons--reverse !optional;
123+
@include e(end) {
124+
@extend %igx-card-actions__end--reverse !optional;
125125
}
126126
}
127127

128128
@include mx(vertical, reverse) {
129-
@include e(icons) {
130-
@extend %igx-card-actions__icons--vertical-reverse !optional;
129+
@include e(start) {
130+
@extend %igx-card-actions__start--vertical-reverse !optional;
131131
}
132132

133-
@include e(buttons) {
134-
@extend %igx-card-actions__buttons--vertical-reverse !optional;
133+
@include e(end) {
134+
@extend %igx-card-actions__end--vertical-reverse !optional;
135135
}
136136
}
137137

138138
@include m(justify) {
139-
@include e(icons) {
140-
@extend %igx-card-actions__icons--justify !optional;
139+
@include e(start) {
140+
@extend %igx-card-actions__start--justify !optional;
141141
}
142142

143-
@include e(buttons) {
144-
@extend %igx-card-actions__buttons--justify !optional;
143+
@include e(end) {
144+
@extend %igx-card-actions__end--justify !optional;
145145
}
146146
}
147147
}

0 commit comments

Comments
 (0)