Skip to content

feat: convert components to use OnPush change detection strategy 2#3100

Merged
Akshat55 merged 18 commits intocarbon-design-system:nextfrom
Rrothschild18:on-push/branch-4
Feb 17, 2025
Merged

feat: convert components to use OnPush change detection strategy 2#3100
Akshat55 merged 18 commits intocarbon-design-system:nextfrom
Rrothschild18:on-push/branch-4

Conversation

@Rrothschild18
Copy link

Update components to use On Push, part of issue-3066

Changelog

Changed

Dropdown + fix unit tests
File Uploader
Inline loading

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>
@netlify
Copy link

netlify bot commented Feb 5, 2025

Deploy Preview for carbon-angular-next ready!

Name Link
🔨 Latest commit 25e8dbe
🔍 Latest deploy log https://app.netlify.com/sites/carbon-angular-next/deploys/67b26c9525f78000081d1443
😎 Deploy Preview https://deploy-preview-3100--carbon-angular-next.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@netlify
Copy link

netlify bot commented Feb 5, 2025

Deploy Preview for carbon-components-angular ready!

Name Link
🔨 Latest commit 25e8dbe
🔍 Latest deploy log https://app.netlify.com/sites/carbon-components-angular/deploys/67b26c9585cd6e0008522938
😎 Deploy Preview https://deploy-preview-3100--carbon-components-angular.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

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;
Copy link
Author

@Rrothschild18 Rrothschild18 Feb 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Author

@Rrothschild18 Rrothschild18 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a few explanations of my thought process.

@Rrothschild18 Rrothschild18 marked this pull request as ready for review February 5, 2025 23:07
@Rrothschild18 Rrothschild18 requested a review from a team as a code owner February 5, 2025 23:07
Copy link
Author

@Rrothschild18 Rrothschild18 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

@Rrothschild18 Rrothschild18 changed the title On push/branch 4 feat: convert components to use OnPush change detection strategy Feb 5, 2025
@Rrothschild18 Rrothschild18 changed the title feat: convert components to use OnPush change detection strategy feat: convert components to use OnPush change detection strategy 2 Feb 5, 2025
Copy link
Contributor

@Akshat55 Akshat55 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requires some minor changes, really liked the intro of the menuIsClosed input (To be converted to a setter). Thanks for contributing this @Rrothschild18

* Set to `true` if the dropdown is closed (not expanded).
*/
menuIsClosed = true;
@Input() menuIsClosed = true;
Copy link
Contributor

@Akshat55 Akshat55 Feb 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can change the following to something like this & update all instaces of menuIsClosed calls to use isOpen.

Suggested change
@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();
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@Akshat55 Akshat55 merged commit 65df40e into carbon-design-system:next Feb 17, 2025
14 checks passed
@github-actions
Copy link

🎉 This PR is included in version 6.0.0-rc.12 🎉

The release is available on:

Your semantic-release bot 📦🚀

klaascuvelier added a commit to klaascuvelier/carbon-components-angular that referenced this pull request Feb 26, 2025
…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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants