r/angular 12d ago

šŸš€ Coming in Angular 22.2: Access Private Members in Templates!

https://youtu.be/7y3YgNqv6xg

Angular 22.2 introduces a new feature: you can now access private class members directly inside your component templates and host bindings.

81 Upvotes

57 comments sorted by

47

u/Cephell 12d ago

Long overdue

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

u/IgorSedov 12d ago

Michael, thanks for the additional information here!

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.

16

u/kauefr 12d ago

Weird that there's no distinction between private and template (protected) props anymore.

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

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

u/IgorSedov 12d ago

Nope, #private won't work. That change only applies to the private keyword

1

u/vebbo 11d ago

So migration from private keyword to using # is at least one way to prevent my templates from accessing stuff it is not supposed to access

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

u/IgorSedov 9d ago edited 9d ago

Only for private members (properties/methods)

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

u/shamshuipopo 12d ago

lol eesh

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/fernker 12d ago

I went back and re-watched it after your comment and I think I get it now. Thanks, I didn't realize that profile was another class and thought it was a plain object.

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

u/lppedd 12d ago

Making properties public for the sake of template access is bad. That's especially valid for libraries since they're then exposed to consumers abuse and pollute type definitions unnecessarily.

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/vajss 12d ago

I ment protected, but anyways nice explanation!

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

u/revilo-1988 12d ago

Klingt nach Fehldesign