0
votes

I have a class UserList with a private internal variable that is designed to only be available to accessor functions. How can I access that internal list in a performant manner within an ngFor binding?

class UserList {
  private users:user[] = []
  public addUser():void{..} 
  public removeUser():void{..}
  public listUsers():user[]{
    return this.users; //this is the only way to access the private users list
  } 
}

and then in some component..

@component ({...})
class AppComponent {
  users:UserList = new UserList();
}

and in that component's template, the getter function is called..

<span *ngFor="let user in users.listUsers()">
  {{ user.username }}
</span>

So clearly this doesn't perform well, because angular can't possibly know when this list changes and will have to call users.listUsers() constantly to keep the view updated. Can I somehow limit this behavior and inform Angular that the list has changed with some event? I don't want to make the list public, and I don't want to access the private property directly in the template.

References: Angular2 - should private variables be accessible in the template?

Update with solution:

Amit's suggestion to use OnPush change detection worked out. I built a callback into the users service to inform any components using it of a change to the private user list. The app component could then call markForChange() to update the view. This let me refresh the view without breaking either the dependency injection pattern or the encapsulation I was attempting to enforce.

I still feel unsatisfied with this approach, because the change detection scheme affects the entire component and not the element. To me it seems strange that Angular wouldn't be able to efficiently bind the result of a function to an element without creating a performance sinkhole or breaking design patterns, or re-configuring the entire component to observe that behavior.

2
Perhaps create getters/setters for the relevant variables? - P. Moloney
That's what I've done. I would prefer in the private list was only accessable by the getters. But that limits what I can bind in the template. I have to bind the getter function, which means angular has to constantly call that function to see whether data has changed. I'm now looking into OnPush change detection - Austin

2 Answers

1
votes

You could use OnPush change detection strategy, and mark the component to detect changes as soon as you know the list has changed.

1
votes

This should not. I am requesting you to don't do it. It will break DI.
Please call your private data from your service and make a public variable for template