Reputation: 57126
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
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
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