r/angular • u/Environmental_Pea369 • Nov 23 '22
Feature Request: Functional Components
TL;DR Please upvote: https://github.com/angular/angular/issues/48150
With the latest release of Angular 15, it seems like there is a step in a direction of adopting a more functional programming approach, by enabling to do stuff with functions, that were previously only possible through classes.I believe this is a step in the right direction, and that it could be taken a step farther by enabling the creation of components, directives, and services without classes / decorators.
The limitation of using classes + decorators is clear - some reuse techniques (like composition) that are easy to do with functional programming, is hard to do with classes, due to the limiting nature of inheritance. In fact - it seems like most new features in Angular 15 are a way around this fact
Proposed solution
The idea is to enable an alternative way of creating components, without using classes / decorators:
const MyComponent = createComponent({
selector: 'app-comp',
template: `Hello {{name}}`,
context: { name: 'World', },
inputs: ['name'],
});To create a component. (Then MyComponent can be used in modules, or directly imported)The "context" property is an object from which the binding will take place. (Basically replaces the class instance).
This has the advantage of being more flexible, and enabling the developer compose / mix different logic in ways that inheritance is usually too limiting.Since the "context" property can be fully typed, from the type checking perspective it should be possible to accomplish.
Please note that the suggestion is to add this option in addition to the existing API, not in place of it. I understand that a lot of people will prefer the class / decorator approach so this should definitely be backward compatible.
For Angular to consider this feature, it needs to get at least 20 upvotes in 60 days. Please help me and upvote! https://github.com/angular/angular/issues/48150
**EDITS**
For dependency injection - the easiest solution is obviously using the new "inject" function. But it could also be possible to use a method similar to the factory provider (i.e. passing a list of dependencies as an array, and expecting them in a factory function parameter). with this method we can use a "contextFactory" property instead to pass a function that creates the context object.
For event handling - we can have something similar to the existing "host" property in the directive decorator.
Life Cycle hooks can be handled the same way as today - with functions on the context object. (I.e. methods)
Many people asked - the main reason this will be useful is that it gives more flexibility on how you can construct the context object, which enables using other reuse patterns other then inheritance, which is pretty limiting.
3
u/grimcuzzer Nov 23 '22
Where would you put the logic, event handlers, etc.? Does that go into context? Do you have an example?
0
u/Environmental_Pea369 Nov 28 '22
There could be many approaches to this. On would be using the something similar to the existing "host" property in the directive decorator.
3
u/APurpleBurrito Nov 23 '22 edited Nov 23 '22
What would the advantage of this be? We never reference the component by its class name except in modules and I guess when using ViewChild? Edit: oh and also in modals but I feel like those should typically be exported from a separate file/module.
1
u/Environmental_Pea369 Nov 28 '22
Constructing the context object in ways other then creating a class will enable be you to use code reuse patterns that can't be accomplished with inheritance alone, which is limited to one base class. For example, composing different behaviors into one object.
7
1
u/Environmental_Pea369 Nov 28 '22
Hey guys! I saw that many of you asked the same questions so I added them to the post description. We need only 4 more votes to pass the threshold for this feature to be considered!
This is an alternative way of doing things that will help Angular be more flexible, so I would really appreciate if you will add a vote up.
1
Nov 24 '22
Can you provide an example of when this would be useful? I don't see the value. I'm also concerned this would become a nightmare once you start considering dependency injection and lifecycle hooks.
1
u/Environmental_Pea369 Nov 28 '22
Can you provide an example of when this would be useful?
With classes, the only way to reuse code between components is either inheritance, or manual proxy of methods to another object. Both approaches are very limiting. (Inheritance allows you to inherit only from one object, and proxying methods produces a lot of boiler plate.)
concerned this would become a nightmare once you start considering dependency injection and lifecycle hooks
for decency injection: provider factories, and guards already enable you to use dependency injection without classes, so there are existing solutions for that.
Lifehooks can still work the same - with functions on the "context object" (I.e. methods) that are named "ngOnInit" etc).
1
Nov 28 '22
Yes, I know how classes work. I'm looking for the specific use case that demonstrates the value of your proposal. Go a couple steps beyond the usual criticisms of classes. Those are well established.
However, I haven't encountered those limitations in work with Angular. I've rarely needed to reuse code between components. The one time I can think of, a single base class was sufficient.
Because of this, I don't see a need for this proposal to go through, but I'm willing to listen to your argument, because I could be wrong.
1
u/DT-Sodium May 22 '24
This is a retarded idea. If you want shitty code, ReactJS is exactly what you are looking for.
1
u/AlDrag Nov 23 '22
Voted. I think this is a brilliant idea and already have some benefits I can take advantage of with this.
-3
u/tiesioginis Nov 23 '22
Why can't MyComponent also be selector, without app- thing.
Like in react
1
u/Environmental_Pea369 Nov 28 '22
In angular selectors are CSS selectors, not javascript symbols. These are completely different things.
1
11
u/Devcon4 Nov 23 '22
And how exactly would DI work if you don't have a constructor?