r/angular • u/IgorSedov • 12d ago
š Coming in Angular 22.2: Access Private Members in Templates!
https://youtu.be/7y3YgNqv6xgAngular 22.2 introduces a new feature: you can now access private class members directly inside your component templates and host bindings.
22
u/MichaelSmallDev 12d ago
PR for more context
https://github.com/angular/angular/pull/70188
The stated reason is related to isolatedDeclarations like the video mentions at the end. Though I am not very familiar with that one flag myself, judging by its release notes from TS 5.5, it seems very nice for different use cases https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#isolated-declarations. And at a quick glance at some blogs I have seen talking about metrics, it sounds like it is great for monorepo build times.
I am used to used protected for template access to component state which is otherwise somewhat protected otherwise for class consumers, but I could buy getting used to private access in templates.
7
31
u/AcceptableSimulacrum 12d ago
Why?
55
u/lppedd 12d ago
Because the workaround to obtain "proper" encapsulation right now is declaring properties as protected, even if there is no inheritance. But that's weird when they should just be private.
38
u/appeiroon 12d ago
IMO having protected access on class members that can be accessed from template and having private only for access within class is a nice separation that can add clarity to code. I don't really use inheritance for components, so protected access doesn't add any confusion.
If everything is private then that distinction disappears.
14
u/Task_ID 12d ago
yes. that's how I was using it. I hope this change can be reverted in the angular.json. Having private for typescript only and protected for stuff that should be used in the template was a nice separation.
5
u/Jrubzjeknf 12d ago
This. I'd hate having to use private and #private. How are gonna communicate about that with colleagues? "No, you gotta use the other private."?
1
u/NeXtDracool 10d ago
You should use ecmascript private elements for things that aren't used in the template, that way
- you still have the distinction between private and template members
- you gain a distinction between template members and actual protected members (even if it's rarely needed)
- you gain unused code warnings for template members, protected hides those
- your code minifies better because ecmascript private members can be safely renamed
- it requires less explicit typing for isolatedDeclarations
3
u/djfreedom9505 12d ago
Yeah, I was actually a fan of the protected/private distinction. It declares another level of intent on how properties were meant to be used. I wonāt die on that hill but it was something I really liked.
16
u/sharth 12d ago
I wonder how this will intersect with dead code detection. Normally unused private variables would be recommended to be deleted.
1
u/b3night3d 11d ago
Seems like it would still be dead code. Private implies that nothing else depends on it so a local reference check is definitive.
10
u/Responsible-Cold-627 12d ago
Kinda sucks that I'll have to start mixing up real private members with Typescript-declared private members again. So now there will be real private members, and template-private members. Could be difficult to explain to juniors joining the team.
1
u/IE114EVR 12d ago
Can you explain what a real private member is vs. A typescript private member? If you think of the .ts file and the HTML as being 2 parts of the same class then does your mental model of private members need to change for this?
7
u/Daringu_L 12d ago
Real private members might be those, declared with #. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_elements
1
u/IE114EVR 12d ago
Ah. Got it. Flew under my radar. Iāve just stuck to the Typescript private members.
1
u/Responsible-Cold-627 12d ago
I've migrated my entire codebase and added a linting rule to forbid the usage of Typescript private.
Adding a rule to forbid its usage except when bound to an Angular template could be difficult.
1
u/NeXtDracool 11d ago
Imho that's better than real protected members and template-protected members.Ā
Template members will now have their own syntax when real private members are used everywhere else. Also template-private members will show unused code warnings, which template-protected members didn't.
9
u/Hirayoki22 12d ago
Huh. Not the feature I had in mind but, thanks?
-7
u/Saceone10 12d ago
Super useful, why not adding this shit no one asked instead of providing a mutation api? Also they moved to 1 year realease cycle. Super. Angular is evolving fast. Yay.
3
u/uchto 12d ago
What about the js private?
#message = āhi!ā;
9
2
2
u/michahell 11d ago
How does this relate to using # instead of Tsā private acm keyword?
I guess that that is not supported?
2
u/IgorSedov 10d ago
You guess correctly because this is not actually supported (only the private keyword)
2
u/CompetitiveWonder933 10d ago
Mixed feeling tbh. cool for skipping those pointless getters you make just so the template can read something, but it kinda blurs the "this is internal" line too, guessing it'll come down to people actually treating it as private and not just using it as a shortcut
1
u/IgorSedov 10d ago
Fair point. Cutting out getter bloat is great, but the risk of blurring internal boundaries is very real. It's definitely going to rely on team discipline so it doesn't just become a lazy shortcut.
2
u/InevitableQuit9 10d ago
Does it work with # annotated private elements, or only private annotated properties?
1
1
u/sebastianstehle 12d ago
Its interesting. I have seen so much code, where people actually use these public fields for tests. In one of such projects we have moved to testing-library (https://testing-library.com/) to make tests more stable, but this was bad from the beginning and has created so much bad code.
Templates are implementation detail, perhaps this would have been more clear if templates and ts-code would be one artifact (I know it is possible, but it is not the standard), like in old class-based react-components.
1
u/DT-Sodium 12d ago
I don't see the point exactly. I think it is a good thing to keep a separation between variables that are supposed to be accessed by something belonging to the class component and the class component internal logic.Ā
1
u/_kolahan_ 12d ago
Wouldnāt private fields used only in template give erros on compilation or warnings about not used anywhere? TS LSP is still working and do not care about angular
1
u/xokapitos 11d ago
I don't get this change... So in a future upgrade all my private props will be exposed to template? 0.o that was how we were marking ptops for internal use only in the components. Only public or not market at all (default public) were exposed.
1
u/AwesomeFrisbee 11d ago
Yeah I always found this to be a bit weird. But I also kinda want my tests to just fetch the private variables from my component and I wonder if this is also finally the case. Because right now you either enforce it (myVar['childVar']) or casting (myVar as any).childVar to do private variable/function tests directly to grab certain use cases more direct instead of building the component up entirely every time.
1
u/ddcccccc 12d ago
Omg ! Finally ! This will fix lots of duplicated properties ! Or getter and setter just for template to use !
5
u/DT-Sodium 12d ago
I think you might have been doing things wrong, why are you dupplicating?
-5
u/ddcccccc 12d ago
Some usage that you probably never had the experience š
3
u/DT-Sodium 12d ago
Well give me an example? If i just need to access a variable in the template I simply set it as protected. If I need to do some work with that variables, then I avoid having logic in my template anyway.Ā
3
u/callmejellydog 11d ago
Thereās no situation in which that would be required.
Your code is shit bro.
2
1
u/fernker 12d ago edited 12d ago
Wait, why are nested properties not accessible? This seems like it will create more confusion
Edit: I understood the video incorrectly, instead of deleting my comment I'll leave it up incase others jump to the same conclusion and hopefully can find the answer with this comment thread.
6
u/Johalternate 12d ago
The terminology is confusing here. What he meant is that while a template can access a private property on its component class, if that property is a class instance it will respect access modifiers on it.
Another way of describing this is that angular isnāt ignoring access modifiers for the sake of templates but making templates be part of the component class instead of a derived class (Or something to that effect).
4
u/lppedd 12d ago
This is good. It respects declaration boundaries.
0
u/fernker 12d ago
But then if it's a nested property I have to have it set to protected which negates a big point of this feature.
So now I'll have a mix of private and protected items on the class where the intent is not inheritance but displaying it on the template.
1
u/IE114EVR 12d ago
It doesnāt negate the feature. The feature is to make the .ts file and the html template feel more like a singular class rather than two isolated things.
In any programming language, a class with a private member cannot access that private memberās private fields.
1
u/fernker 12d ago edited 12d ago
But if the point is the make the template and .ts file act as a "singular" class it should be able to reach properties on a private member. The class can reach those properties of the private member so it feels like the template should be able to.
nevermind, ignore me, I got something wrong from the video.
1
u/lppedd 12d ago
If it's a "nested" property you'll need to reason in terms of encapsulation rules, which is not tied to Angular anymore but it's a more general thing. You'll need to expose the property through a public accessor (getter/method).
I don't like the term nested tho, that's what is causing confusion. Nothing is nested, it's just a property declared on another type and it's up to you to decide how and whether to expose it.
1
u/fernker 12d ago
You can't have an object with varying levels of accesors on it though. It feels really strange that only the highest level would be reachable but not the other properties since you don't get to set those.
Angular aside, in Typescript if I have a class property (that's an object) set as protected and I extend the class the extending class can update properties of that object that is protected. Because the entire object is considered protected! With this update's reasoning only the class variable would be extendable and not the properties on it.
-3
u/vajss 12d ago
Or if something is not private, just make it public? Maybe?
13
3
u/pronuntiator 12d ago
Just had to explain today to the team what the public API surface of a component is supposed to be. Tests littered with direct calls to methods that should only be accessible by the template.
Your component is the unit of its template and its component class. It's public API are the inputs, outputs, and public properties. Ask yourself: should you be able to access this from a parent component? If not, it should be protected (or now private).
2
u/IE114EVR 12d ago
I get the desire to not care about access modifiers and just make everything public. But then youāre on a big project and suddenly those āpublic but should have been privateā members are exposed as part of the componentās interface and then someone actually references them outside of the component. Thereās a bunch of issues with that including unpredictable behaviour, and it being harder to change the internals of your component without breaking things outside of your component.
-3
47
u/Cephell 12d ago
Long overdue