-
Notifications
You must be signed in to change notification settings - Fork 26.2k
Template Local Variables #15280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
you can create such directive yourself |
@DzmitryShylovich yes, I could of course. Just a copy of ng_if with the key bit of conditional code removed. Still, I have this here is a feature request, because I think it makes much sense as a feature of Angular for everyone to use. I'd be happy to implement it, of course. (Incidentally, I put together something roughly analogous to the |
@DzmitryShylovich You mean like your one, right? http://plnkr.co/edit/Sunu2LPQVAaWZvZRcWXb?p=preview |
@mlc-mlapis yeap |
I second this.
The local How can I achieve this without ngIf ? |
I've found another place where this would be useful and it might help turning your opinion. I have list of favorites, and a message when there's no favorite. Since the variable is not null, but an empty array, <ng-container *ngIf="favoritesObservable | async as favorites">
<my-list *ngIf="favorites.length > 0; else noFavoritesMessage"
[elements]="favorites">
</my-list>
<ng-template #noFavoritesMessage>
Your favorites list is still empty. To add the first one you can ...
</ng-template>
</ng-container> Having to have a wrapping |
@tinchou you can map empty array to null
|
It is clear that having multiple subscription of the same observable is not the way to go. There is absolutely no reason that angular should not have a way to create a local variable, might it be ngLet or something else. Creating loca variables in ngIf is just a hack to achieve that function 8000 nality. And this hack reaches its limit when you need to use a falsy value from your local variable. |
While local variales in templates could still make sense, avoiding multiple subscriptions could also be done with the share operator on Observables. |
Also discussed in some depth in #2451 |
we are using this in production
the usage is
|
is there a better syntax for this template? <h1 *ngIf="isLoggedIn$ | async; else anonymous">
<div *ngIf="profile$ | async as profile;"> Hallo, {{profile.name}}</div>
</h1>
<ng-template #anonymous>
<h1>Hallo</h1>
</ng-template> |
@xmlking may be you need *ngLet |
@xmlking thats kinda off topic though, you are asking for support... |
Seems this is an old thread and not being implemented. But I thought I'd add one more use case.
Given the code above, we do a lot of data mapping on the client side. applicationMethods$ is just a map amongst several maps saved in the store. The problem here is that after using an async pipe here, it seems anywhere else I call it in the same template does not work. That is, perhaps it takes the subscription and completes or something funky like that. :) Technically, I'd like to use the same map elsewhere in the template. How do I accomplish this without going to the component file. An NgLet for the map would have been ideal, and maybe would alllow me multiple subs of it. |
@nnennajohn thats a different issue. If you look the src code of the async pipe, you would notice that it doesnt do something similar to what you describe. I can think of 2 (common) options:
|
Both are valid usages so it's up to you to choose how you write your code. |
I just had an evil idea:
At least I guess we don't need a scoped |
Fair enough - more unreadable code to shovel out for me :D But I get it - objectively it's preference. |
This feature is unnecessary. The variables should not be defined in template. The variables should be changed in typescript. The template layer should be simple and just used to render views. Please do not add more to template. |
I definitely do not agree with this. The new let syntax is just a tool. I am also a big fan of clean templates, but how do you deal with situations in which you need to re-use thevalue of a resolved observable in multiple parts without subscribing to it multiple times? Typically in previous versions you could
|
I will use the second one and i think others use this way before. I do not know why they need this feature. Maybe you are right. |
I think there is still a use case for this. Consider a list whose list-items have an observable property:
It's contrived but obviously a common use case. One extra subscription might not be a big deal but sometimes it's a lot more. Now, I might solve this by adding an extra conditional element to the markup, to create a temporary variable in the for-loop scope using |
I think the most important thing is when will it be evaluated. If it will work like signals so if we do: |
First of all, this is a completely optional feature so you can decide not to use it in your project. The code for it will be tree-shaken if you don't use it. As for advantages over existing solutions, these are some off the top of my head:
|
Now these are some compelling arguments! |
I have thought about it more, researched how Svelte does it. Makes perfect sense to introduce constraints . I love that this feature solves the pains we had. However allowing to fantasy go wild with declaring let at the top is not compelling for me. As mentioned "code however you like it's optional" I'm also not sold on this reasoning. Knowing pollution of template with overusing let will happen - to just accept it as a "choice". Especially when this concept is already being used in the wild with the constraints to exactly avoid this scenario. I would reconsider. A lot of people that interacted with my thoughts on various platforms and some experts I know in real life do see the benefits that are clear. But we are afraid about lack of the constraints. PS: I have seen arguments from Alex as well - it's definitely a challenge for scoping it. But allowing to use it so freely is also not the best choice in my opinion.
|
@danielglejzner can you elaborate on the kinds of constraints you're thinking about? Usually when we introduce constraints at the framework level, it's to avoid cases that break the mental model, not to arbitrarily catch code that we deem to be "inappropriate". As for overusing template variables: I don't think that's a reason not to implement something. The goal is to provide developers the tools to build web apps, we aren't there to police their coding style. Every single part of the framework can cause issues if it's "overused". Furthermore, there's a clear need for something like this, because we've seen many cases over the years where developers have had to implement directives like |
I don't deny any of your points. If people want to break it they will. It's hard to make a compelling case to constrain using @let in the light of what you have written. I have been thinking that trackBy could be a good example of such constraints already introduced. If we go without constraints we need to have clear and well visible guidelines. While specifying massive amount of variables is not going to directly affect performance ( I think ) it will affect readability so the least we can do is have a clear guidelines that already appear in many articles written on the subject. |
There are only two flavors of constraint I can imagine which are reasonable to apply:
There is no difference functionally between these options, and this kind of constraint would not prevent the case of "many variables at the top of the template". It would only add friction to using I do think having many variables at the top is not necessarily a code smell. Expression aliases are not "logic" - you can't do anything with them that you couldn't do in a binding. In that sense, the ability to give names to your binding expressions is incredibly helpful for making templates more readable. Other types of restrictions like "you can't make a |
I have no more arguments :) thanks for the discussion. |
I have two questions about @let and signals:
|
Did someone let https://github.com/let know that they will get spammed a lot? 🙃 |
We're still aiming to support narrowing, regardless of By using backticks around |
Enables the new `@let` syntax by default. `@let` declarations are defined as: 1. The `@let` keyword. 2. Followed by one or more whitespaces. 3. Followed by a valid JavaScript name and zero or more whitespaces. 4. Followed by the `=` symbol and zero or more whitespaces. 5. Followed by an Angular expression which can be multi-line. 6. Terminated by the `;` symbol. Example usage: ``` @let user = user$ | async; @let greeting = user ? 'Hello, ' + user.name : 'Loading'; <h1>{{greeting}}</h1> ``` Fixes angular#15280.
I wonder if they will consider supporting object/array destructuring syntax in the future :) @let { a, b } = object
@let [a, b] = array |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
[X] feature request
Current behavior
The new syntax is a great improvement!
... And was discussed at length in #15020.
Expected behavior
The ability to capture the async pipe output and make it available as a template variable, is much appreciated and very useful. Unfortunately, this capability is currently bound closely to
*ngIf
; it is only available is a feature of*ngIf
. (I am aware that there is something similar for*ngFor
, unrelated to this feature request).Here's what I request: that this capability be yanked apart from the conditional (
*ngIf
), and made available elsewhere.I don't know what syntax would make the most sense. Perhaps:
Or alternatively; it would be excellent to have a syntax to directly use any observable anywhere in a template, with the reactivity handled by Angular, and without worrying about potentially multiple async pipe instances needlessly subscribing many times. For example, imagine the following syntax:
What is the motivation / use case for changing the behavior?
I have a use case in front of me, the details which don't matter, where:
*ngIf
s which exists solely for the purpose of giving access to this ability to capture the async values to template variables.The text was updated successfully, but these errors were encountered: