danday74
danday74

Reputation: 57126

In the Angular2 team example code, why does apparent one way binding seem to work like two way binding?

This plunker is created by the Angular team:

https://angular.io/resources/live-examples/structural-directives/ts/plnkr.html

in file structural-directives.component.html there is the code ...

<div><!-- Visibility -->
  <button (click)="isVisible = !isVisible">show | hide</button>
  <heavy-loader [style.display]="isVisible ? 'inline' : 'none'" [logs]="logs"></heavy-loader>
</div>

<div><!-- NgIf -->
  <button (click)="condition = !condition">if | !if</button>
  <heavy-loader *ngIf="condition" [logs]="logs"></heavy-loader>
</div>

<h4>heavy-loader log:</h4>
<div *ngFor="let message of logs">{{message}}</div>

then in the file heavy-loader.component.ts there is the code ...

@Input() logs: string[];

and elsewhere in same file ..

this.logs.push(msg);

NOW I would NOT expect this push(msg) in the child component to effect the logs array in the parent component since the binding is one way from parent to child.

However, it is indeed effecting the logs array in the parent structural-directives component as proved by this code in the parent template ..

<div *ngFor="let message of logs">{{message}}</div>

Which when executed shows that messages are being added to the parent's logs array.

Can anyone explain why this is happening? thanks

Upvotes: 1

Views: 43

Answers (2)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657761

@Picci is right.

There is a difference if you use primitive types (boolean, number, string, and object reference) which are passed by value - that means when passed, a copy of the value is created for the receiver.

For objects (and array is an object) only a copy of the reference that points to the object is created and handed to the receiver but both references still point to the same array.

When the array content (or that of any other object) changes, both see these changes because there is only one array.

Upvotes: 2

Picci
Picci

Reputation: 17762

The point to focus, in my opinion, is that there is one single instance of the logs array shared among StructuralDirectivesComponent and HeavyLoaderComponent.

In StructuralDirectivesComponent you create the instance via the line

logs: string[] = [];

and then pass this same instance to HeavyLoaderComponent via

<heavy-loader *ngIf="condition" [logs]="logs"></heavy-loader>

At this point, any change made to logs by HeavyLoaderComponent is seen also by StructuralDirectivesComponent and viceversa since they are dealing with the same instance.

In this respect I am not sure whether it is correct to talk about 2-way 1-way binding but rather about sharing model among components.

I hope it helps

Upvotes: 2

Related Questions