8

I have a class (interface) in my angular 4 app which has a lot of fields. Note that the instance of this class/interface is immutable (i.e. the members will NEVER be changed).

E.g.

public interface IHaveALotOfFields {
    field1: string;
    //...
    field500: string;
}

This interface is provided via a (singleton / application level provided) service which exposes the class as a member. E.g.

@Injectable()
public class MyService {
    public translations: ITranslationsProvider;
}

The service is injected into a lot of components (almost all components) and often used in their corresponding template and often also in the ts-part of the component. E.g.

@Component({
               template: `Value: {{service.field500}}`
           })
export class MyComponent {
    public constructor(public service: MyService) {
    }

    private doSomething(): string {
        return this.service.field1;
    }
}

Now my questions:

  • Will a big class (with a lot of fields) make angular slow because of the change detection?
  • Is there any way to mark a class as "Ignore me on change detection"? (something similar to ChangeDetectionStrategy.OnPush, but instead of specifying this for each component, can be declared on the class itself or on the member of the service)

Please note that I don't want to change the change-detection strategy of all my components to OnPush.

OschtärEi
  • 2,255
  • 3
  • 20
  • 41
  • The interface is just a way of type checking. It won't get injected... Only objects get injected that have been instantiated by new for a classes. An Interface is a contract the class will adhere to. In the interface you assign properties and method signatures for the contract... Services have @Injectable and Angular takes care of instantiation of those for you automatically wiring things together. – JGFMK Jul 20 '17 at 09:15
  • I know. I have concrete classes which implement this interface. The `MyService` basically gets an instance of a class which implements the interface injected. – OschtärEi Jul 20 '17 at 11:58
  • The interface is not injected only objects.. This is what I was hoping to help you with. i.e. You can't do new on an interface... – JGFMK Jul 20 '17 at 12:05

1 Answers1

4

Will a big class (with a lot of fields) make angular slow because of the change detection?

No. Angular change detection performs two operations that read class properties:

  • DOM update on the current component
  • input bindings update of child components/directives

For these operations Angular compiler creates two functions:

  • updateRenderer - reads fields used in the template
  • updateDirectives - read fields specified in input binding expressions

These functions read only specific properties from the service. For your example

Value: {{service.field500}}

the updateRenderer function will look something along the lines:

function(_ck,_v) {
    var _co = _v.component;
    var currVal_0 = _co.service.field500;
    _ck(_v,1,0,currVal_0);

These functions are called on each digest loop. But as you can see only the relevant property will be read from the service. So it doesn't matter how many properties there are on the service.

Is there any way to mark a class as "Ignore me on change detection"?

I assume you're asking about one-time binding like we had in AngularJS. Maybe it will be added in Angular as well. I'll be monitoring that and update the answer if something comes up. But as you probably know you can disable/enable change detection for the component using cd.detach/cd.attach. You can listen for some signal from the service and run cd manually when neeed.

Here is the list of articles you could read to understand the mechanics of change detection better:

Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
  • Thanks for the great answer. What I mean with the way to mark a class as "Ignore me on change detection" is,if there is a way to tell angular that properties/fields of this specific class are "constant" (have constant values) and will never change. No matter if the class was injected from a service or as an input or however else. – OschtärEi Jul 21 '17 at 12:19
  • @OschtärEi, ah, I see. No, unfortunately there's no way yet to do that. In AngularJS we had one-time binding. Maybe it will be added in Angular as well. I'll be monitoring that and update the answer if something comes up. But as you probably know you can disable/enable change detection for the component using `cd.detach/cd.attach`. You can listen for some signal from the service and run cd manually when neeed. – Max Koretskyi Jul 21 '17 at 12:23
  • Thanks again. But if i use `detach/attach` all the change detection of the component will be detached (what I don't want) and also I would need to do this in all my components (since almost all components use this "big class" (it's for translations). – OschtärEi Jul 21 '17 at 12:44
  • 1
    @OschtärEi, I understand. As I said, there's nothing else you can do for now. – Max Koretskyi Jul 21 '17 at 12:51