-
Notifications
You must be signed in to change notification settings - Fork 25.3k
-
Notifications
You must be signed in to change notification settings - Fork 25.3k
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
ngFor should optionally show a template when there are no items in the collection #14479
Comments
Maybe keep else as the keyword instead of creating a new empty keyword. For example, Python re-uses the else keyword: for item in items:
# do something with item
else:
# no items EDIT: Please read comment and links from epsy below, which points out that this syntax has confused Python programmers and doesn't do what I assumed. I do think empty is more clear. |
Any news about this feature ? :D |
There is a subtle difference here with async items between 'no results' and 'results still loading'. Any solution would need to target both (or optionally default to one template). |
Worth pointing out is that the "else" keyword in Python's "for-else" construct is regarded as bad naming [1][2]. Unlike what the comment above suggests, this else block will run whenever the for loop completes without being interrupted (by using break, return, or if an exception was thrown), independently of whether the loop had any iterations or not. It usually gets confused for the feature being requested here (i.e. runs when the iteratee is empty), but Python's mistake adds enough confusion to the 'else' name that it might be worth avoiding. [1] https://mail.python.org/pipermail/python-ideas/2012-June/015350.html |
<ion-item *ngIf=items?.length === 0'>No Results This works if you place it inside of the < /ion-list > but outside of *ngFor Example: This is obviously a stripped down version of what I have but it works as needed. |
@xclusive36 the reason you got a downvote, I think, is that it's easy to make a "no items displayed" conditional for something as simple as a single empty list, but doesn't address the issue of a computed value for |
I recently wrote an article on Medium which enhances I'll attach a quick attempt at this here, but note that it's not thoroughly tested and might not be ideal. It goes without saying that support in core would be preferable, of course. You can see it in action here. Edit: This does actually not work quite correctly yet, I just noticed. I don't have time right now to look into it any further, perhaps someone would want to use it as a basis or inspiration, though.
|
|
anybody else have a more elegant want to solve this ? I found using *ngIf else to check the length and display the 'no result' status cannot be re-used. I was think using custom directive to solve it ? |
I believe this issue is still relevant. Any updates? While not exactly critical, it would be nice to have this. |
This would be particularly useful in cases where an Observable is the source, and an additional subscription to it is required within the component to determine whether or not it's empty. In my current project, the source is either an Observable or null, and it comes from an external library beyond my control. I haven't investigated thoroughly yet, but this seems like it would take a lot less overhead (and less chance of error) if it were implemented as part of Angular. I have a situation where I absolutely must distinguish between loading and empty, and the code to determine this seems far more involved than I would have thought. |
I've started using a pattern where I "fix" an Observable that doesn't play well with the async pipe: class MyComponent {
/** @internal */ public readonly fixed$: Observable<Array<Thing>>;
constructor (service: MyService) {
this.fixed$ = service.maybeThings$.pipe(map(arr => arr || []));
}
} Now, if your library emits <ng-container *ngIf="fixed$ | async; let things">
<div *ngIf="things.length > 0; else noThings">...</div>
<ng-template #noThings>...</ng-template>
</ng-container> Re-reading your post, you say the source "is either an Observable or null" -- do you mean you have |
Bump. |
Add support for `default` template to be displayed when `*ngFor` has no content. closes angular#14479
Add support for `default` template to be displayed when `*ngFor` has no content. closes angular#14479
Add support for `default` template to be displayed when `*ngFor` has no content. closes angular#14479
Add support for `default` template to be displayed when `*ngFor` has no content. closes angular#14479
Hey all, despite some early approvals from team members, after further discussion we've decided not to add this feature. The main rationale here is that this can already be accomplished by using I know that there are a number of people who would find this feature useful, but ultimately we think it's to the benefit of the larger audience not add this one. |
Fair enough, but FWIW, if we're going to count bytes, we should also count the additional bytes per conditional required in an average project to be accurate on whether adding this is a net increase of bundle size or not. Every project I worked on has at least a few dozen instances of this. |
True, I have not seen a project where this usage of ngIf with ngFor would
not be used in dozen places, so for sure application, size overall would
decrease even with angular/core size increase.
Also, why are You closing issues without letting people reply to Your opinion? @jelbourn This is NOT the way
to handle the discussion. It's more of a way some old company manager would act.
Give his opinion and leave the room showing people where he really has
their opinion. By "You", I mean angular team overall, cause this is not the first issue I see this kind of handling discussion, with instat closing without letting people replay or maybe add some extra points, etc..
|
Jeremy, how did the team address the concerns I raised... good Lord, two and a half years ago? Specifically, it's very common to have an expression in the |
@thw0rted the thinking is that are generally more rare than the simple case. Adding the proposed API would definitely be useful for those more complex scenarios, but at the trade-off a tiny bit more complexity and size. And while it's inarguably a tiny addition here, lots of tiny additions like this accumulate over time. One of the more consistent themes in the feedback we get on Angular is that it's too complex and that the learning curve is too steep. Every small API addition (like this one) contributes to that, even if they are minor in isolation. Another point of feedback has been around payload size. Again 500 bytes seems inconsequential here, over time it builds up to extra kilobytes of features that are sparsely used. While we're obviously working on that in other areas as well, we have to be super mindful of the cost of every addition. I wish there was a way to satisfy every use-case, but we ultimately have to make a call on the tradeoffs, leaving someone unhappy. |
@criskrzysiu closing the issue signals that we don't plan to merge the PR, but folks are still welcome to follow-up on discussion afterwards. Closed issues/PRs are automatically locked only after 30 days of inactivity, which is mainly to prevent people from drive-by commenting on issues that were closed years ago with not-super-related questions (this happens a lot). As for rationale, I tried to summarize where we ended up, but going into more depth, it was a combination of factors:
The team genuinely takes feedback seriously, but ultimately have to make a decision about which path has the most benefit/cost to the largest number of applications. We can definitely be wrong, but we're doing our best in trying to synthesize everything we hear from different parts of the community. |
From my experience onboarding people this is true, and having to jump through hoops to make simple things work is part of that problem. More API surface is not equivalent to a higher complexity per se. To name a different example, Angular not having an equivalent of functional components in React, ie components that don't require all of this overhead of a class and decorators and declaring them, causes significant complexity to achieve something as simple as sharing a tooltip across places in an application.
The roadmap contains no such item. Would you mind sharing the things the Angular team is working on / planning on doing to achieve this? Does this consequently (to the above reasoning) mean there are plans to deprecate certain APIs? I really think Angular would benefit from communicating such internal efforts with the open source community better. Unfortunately it seems a lot is happening behind closed doors.
Fair point.
To me this just reads like "ng-template is good enough for user code, but not good enough for official APIs", which is a disappointing message to bring across. How would people ever learn to use some of the more advanced Angular features if the framework itself doesn't want to use them?
Not moving forward because of a hypothetical future that may or may not exist in some form is end-stage design paralysis. It's just not a good reason IMO, and a blanket argument that could be used to deny any feature request.
All the more reason such a framework level feature supported actual, average, every day use cases like showing an empty state for empty collections. |
It's not exactly a roadmap item, more of a point of consideration that goes into deciding what to work on / how to spend our time. This was a part of the rationale behind ivy- simplifying the generated code, getting rid of concepts like component factories /
That's not quite the intent here. It's more that using the API has has more going if you were to try to explain it to someone new. E.g, with this simplified example: <ul>
<li *ngFor="let user of users">{{user.name}}</li>
</ul>
<div *ngIf="!users.length" class="empty-message">
No users found
</div> vs. <ul>
<li *ngFor="let user of users; whenEmpty: emptyMessage">{{user.name}}</li>
</ul>
<ng-template #emptyMessage>
<div class="empty-message">
No users found
</div>
</ng-template> The latter example just has more stuff to explain (the ng-template and the template var). It's not insurmountable, but still a trade-off. For any APIs where an
Yeah, this wasn't a particularly impactful point in deciding anything, and we would have decided the same thing without it. I just wanted to mention it to highlight that even small changes can have unexpected long-term implications. And, honestly, our goal of providing smooth upgrade paths for all apps does make us pretty conservative about changes to the framework because we bear the cost of bringing users along with those changes. Those cost weigh heavily on the work we prioritize, which means we tend to do more work on stability and backwards compatibility than new features. |
Fair enough. Thanks for your responses, I appreciate that! |
@Airblader et al - FWIW it is possible to create a fairly small directive of your own that will achieve this result - although I haven't checked the corner cases. I might be missing something: https://stackblitz.com/edit/angular-ivy-grtarz?file=src%2Fapp%2Fapp.component.html The nice thing about this is that the application developer doesn't need to use any particularly new syntax, just add the |
Yeah, I'm aware I can create my own directives. :-) My issue with this is, however, that one of Angular's selling points, to me anyway, is that compared to competitors like React it's more of an out of the box solution. That is the trade-off for it not being as lightweight as them, and it's something that can reasonably be argued when talking to people. However, the entire argument goes down the drain when very basic useful features are not added. My pet peeve for this is #15280, and this one is just closely related to it for me. I've had some newjoiners on my team coming from React lately, and I like showing them the benefits Angular brings to the table, but I have to admit that they also have been making very good points about things in Angular that are just frustratingly immature for the framework at this point, be it ngLet, type-safety issues in templates, DX for discoverability of directives and content projection, … |
Lots of the Angular built-in pieces expect to be extended: consider router guards, http interceptors, form validators, etc. My example shows that you even extend The question of what should be "out of the box" is very subjective. It is always a trade off. And in this case it seems to me that this is an extension scenario rather than a core feature of Angular. Regarding your pet peeve, it looks like it has dropped off the radar since #15280 (comment). Perhaps something to bring back to the table in the New Year @IgorMinar ? |
It is, and this issue has 166 upvotes at the time of writing. So clearly this is not an edge-case scenario, but something a lot of people run into and expect the framework to handle.
Guards and interceptors are (purely) APIs specifically built around extending them. When trying to extend ngIf or ngFor, some things are possible, but you also very quickly hit roadblocks, because they are not really written with the intention of extending them. In general directives are hard to "extend" at the moment, for example I tried to extend Anyway, I don't really want to argue this decision. :-) I get the motivation of why it was rejected (and appreciate you guys taking the time to respond). I also don't want to look like the guy who's hating on Angular. I enjoy Angular and working with it quite a lot, and I try to show others all the good things about Angular, but I also had to onboard a bunch of people coming from other frameworks and they often raise good points where Angular just feels "feature-spotty". |
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. |
I'm submitting a ... (check one with "x")
Now that you can give
ngIf
a template to display as an else condition (#13297), it would be nice ifngFor
got the same treatment for when there are no items in the collection.Current behavior
Often, my collections come from an observable, so in order to display a "No results" message i do:
Or, in 4.0.0:
Expected behavior
It would be nice to be able to do something like this:
Which would be similar to how
ngIf
handleselse
cases.The text was updated successfully, but these errors were encountered: