feat: convert components to use OnPush change detection strategy 2#3100
feat: convert components to use OnPush change detection strategy 2#3100Akshat55 merged 18 commits intocarbon-design-system:nextfrom
Conversation
Signed-off-by: rrothschild18 <raultonello18@gmail.com>
Signed-off-by: rrothschild18 <raultonello18@gmail.com>
Signed-off-by: rrothschild18 <raultonello18@gmail.com>
Signed-off-by: rrothschild18 <raultonello18@gmail.com>
Signed-off-by: rrothschild18 <raultonello18@gmail.com>
…m#3066 Signed-off-by: rrothschild18 <raultonello18@gmail.com>
Signed-off-by: rrothschild18 <raultonello18@gmail.com>
…m#3066 Signed-off-by: rrothschild18 <raultonello18@gmail.com>
…em#3066 Signed-off-by: rrothschild18 <raultonello18@gmail.com>
…stem#3066 Signed-off-by: rrothschild18 <raultonello18@gmail.com>
…esign-system#3066 Signed-off-by: rrothschild18 <raultonello18@gmail.com>
✅ Deploy Preview for carbon-angular-next ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
✅ Deploy Preview for carbon-components-angular ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
| items = [{ content: "one", id: 0, selected: false }, { content: "two", id: 1, selected: false }]; | ||
| selected: ListItem; | ||
| onSelect() {} | ||
| @Input() menuIsClosed = true; |
There was a problem hiding this comment.
The unit tests are using a mock component called DropdownTest as a wrapper to the real Dropdown(cds-dropdown) component.
The unit test below is failing due not trigger change detection correctly. It happens because the wrapper component mutate a specific "non-reactive class property" inside Dropdown component and with changeDetection.Default it would work as intended, but with OnPush this property is inaccessible.
The property menuIsClosed seems to control the state if the dropdown closed or not. Its not a derived state and not specificly bounded to any user event change that would make sense to explicit call marckForCheck() somewhere.
// The failing test
it("should propagate the change in selected option back to the form and emit a selected event", () => {
fixture = TestBed.createComponent(DropdownTest); // An angular PseudoApplicationComponentFixture, access to real component
wrapper = fixture.componentInstance;
spyOn(wrapper, "onSelect");
fixture.detectChanges();
element = fixture.debugElement.query(By.css("cds-dropdown")); // Typeof DebugElement has only access to the DOM
element.componentInstance.menuIsClosed = false; // Directly mutating CarbonComponent component class property
fixture.detectChanges();
element.nativeElement.querySelector(".cds--list-box__menu-item__option").click();
fixture.detectChanges();
expect(element.nativeElement.querySelector(".cds--list-box__label").textContent).toEqual("one");
expect(wrapper.onSelect).toHaveBeenCalled();
expect(wrapper.model.content).toEqual("one");
expect(wrapper.model.selected).toBe(true);
});Solution 1 (implemented) - Update Dropdown "non reactive class property" to be an angular reactive @Input and rely on angular change detection by receiving an new @input reference change. Also updated the docs.
@Component({
template: `
<cds-dropdown
...
[menuIsClosed]="menuIsClosed" //
...
>
<cds-dropdown-list [items]="items"></cds-dropdown-list>
</cds-dropdown>`
})
class DropdownTest {
...
@Input() menuIsClosed = true; // Add mock @Input
...
}Solution 2 - Re-write all unit tests for not using "wrapper" components since they make testing a little harder with OnPush + class properties that are not @Inputs.
Any other solutions are welcome. Im open to suggestions since the component is big and have few unit tests.
There was a problem hiding this comment.
I think it might be worth making it an input... I can see use cases of it having it dynamically open/close. However, the naming isn't the best.
Might be better to create a new input (Something like isOpen) and pass data to menuIsClosed using setter? This way angular runs change detection as well.
Then in next official release, we can probably replace all instances of menuIsClosed with the newly created variable. 🤔 Thoughts on this @zvonimirfras.
There was a problem hiding this comment.
isOpen makes more sense than menuIsClosed, for sure.
I don't see a need for a setter when we can just use !isOpen instead. Possibly do vice-versa during deprecation period.
There was a problem hiding this comment.
Rename menuIsClosed to isOpen is way better, it sounded weird for me too. While migrating components im trying to change less code possible.
Ill implement the suggestion of creating an input setter as suggested.
Rrothschild18
left a comment
There was a problem hiding this comment.
I've added a few explanations of my thought process.
Akshat55
left a comment
There was a problem hiding this comment.
Requires some minor changes, really liked the intro of the menuIsClosed input (To be converted to a setter). Thanks for contributing this @Rrothschild18
src/dropdown/dropdown.component.ts
Outdated
| * Set to `true` if the dropdown is closed (not expanded). | ||
| */ | ||
| menuIsClosed = true; | ||
| @Input() menuIsClosed = true; |
There was a problem hiding this comment.
We can change the following to something like this & update all instaces of menuIsClosed calls to use isOpen.
| @Input() menuIsClosed = true; | |
| @Input() isOpen = false; | |
| /** Deprecated as of v6 - Will be removed in v7 */ | |
| set menuIsClosed (isClosed: boolean) { | |
| this.isOpen = !isClosed; | |
| this.changeDetectorRef.markForCheck(); | |
| } |
There was a problem hiding this comment.
I still want to run markForCheck here so it doesn't break anything on release. Teams are/could be using ViewChild to update this variable
There was a problem hiding this comment.
A notice of deprecation should also improve dev experience if they are using it.
Signed-off-by: rrothschild18 <raultonello18@gmail.com>
Signed-off-by: rrothschild18 <raultonello18@gmail.com>
Signed-off-by: rrothschild18 <raultonello18@gmail.com>
Signed-off-by: rrothschild18 <raultonello18@gmail.com>
Signed-off-by: Akshat Patel <38994122+Akshat55@users.noreply.github.com>
Signed-off-by: Akshat Patel <38994122+Akshat55@users.noreply.github.com>
|
🎉 This PR is included in version 6.0.0-rc.12 🎉 The release is available on: Your semantic-release bot 📦🚀 |
…ular into cca6-eslint-migration * 'next' of github.com:klaascuvelier/carbon-components-angular: fix: set id to popover content and aria-live attribute (carbon-design-system#3110) feat: add new menu based components (carbon-design-system#3106) feat: convert components to use OnPush change detection strategy 2 (carbon-design-system#3100) docs: add updated getting started steps (carbon-design-system#3107) chore(deps-dev): bump serialize-javascript from 6.0.1 to 6.0.2 (carbon-design-system#3104) chore(deps-dev): bump store2 from 2.14.2 to 2.14.4 (carbon-design-system#3095) chore(deps-dev): bump serialize-javascript from 6.0.1 to 6.0.2 in /integration/ng17 (carbon-design-system#3103) fix: pass autoAlign property to icon button (carbon-design-system#3101) ci: bump deprecated version of GH action and resolve integration test build issue (carbon-design-system#3102) fix: set publish config access to 'public' (carbon-design-system#3098) fix: add publish config to library (dist) package.json (carbon-design-system#3097) feat: create npmrc file to enable publishing with provenance ci: bump github actions to latest version fix: typing for loading translation strings (carbon-design-system#3077)
Update components to use On Push, part of issue-3066
Changelog
Changed
Dropdown + fix unit tests
File Uploader
Inline loading