2

I have the following html:

<!-- See click event -->
<div *ngFor="let tabComp of tabCompArr" (click)="selectTab(tabComp)">
    {{ tabComp.title }}
</div>

And in component:


ngOnInit() {
    this.tabCompArr = [...]
}

selectTab( selectedTab ) {
    // this changes tabCompArr property. WHY?
    selectedTab.active = true;
}

Why setting selectedTab.active to true, changes the tabCompArr property? Isn't the selectedTab a local variable?

Vahid Najafi
  • 4,654
  • 11
  • 43
  • 88
  • Yes, `selectedTab` is a local variable, but it **references** a different variable, so changes to the local variable will modify the reference also. If you don't want this behavior, you need to directly pass the value of the reference. – Rich Aug 28 '19 at 15:11
  • I would say because you are passing a portion of the original variable tabCompArr as written "let tabComp of tabCompArr". So your selectTab(tabComp) changes the original one by reference. – andrea06590 Aug 28 '19 at 15:11

3 Answers3

2

You need to undestand what is call-by-sharing. This is how parameters are passed to a function in JavaScript.

Consider the following example:

var obj = { foo: 1 };

function selectTab( obj) {
   obj.foo = 2;
}


selectTab(obj);

obj.foo // prints 2

The same will happen if you take any object from array and pass it to a function.

var arr = [{ foo: 1 }];

function selectTab( obj) {
   obj.foo = 2;
}

selectTab(arr[0]);

arr // prints [{foo: 2}]

Array keeps reference to that object which we pass by sharing to function where the foo property has changed.

See also:

yurzui
  • 205,937
  • 32
  • 433
  • 399
1

It happens because you have the same array tabCompArr at html and your typescript file. As array is reference type, so changing an item of array will change an item of an array.

For example:

let array = [{a: true, q: 1}, {b: false, r: 2}, ];
let item = array[0];
item.a = false;

console.log(array);

UPDATE:

You can create another variable to avoid such behavior:

chosenTab: any;

selectTab( selectedTab ) {
    // this changes tabCompArr property. WHY?
    this.chosenTab.active = true;
}
StepUp
  • 36,391
  • 15
  • 88
  • 148
  • So, I pass the value to the function's argument. The argument should have a local variable, isn't it? I don't know what I missing, maybe a feature of javascript! – Vahid Najafi Aug 28 '19 at 15:11
  • So, you mean I pass it by reference, not value? How can I pass the value? Is it possible? – Vahid Najafi Aug 28 '19 at 15:13
  • Yes, modify your function so that it takes the value you want. IE `selectTab(tabComp.active)`. Objects and arrays are simply references to their child values. – Rich Aug 28 '19 at 15:14
-2

It's happen due to Two way biding functionality of Angular. In Two way binding if variable created in .ts file and if you update it from UI side then it automatically update to original object .

Thanks,

Ronak Patel
  • 630
  • 4
  • 15
  • 1
    It has nothing to do with two-way binding and Angular itself – yurzui Aug 28 '19 at 15:16
  • This has nothing to do with two way binding. OP's problem is he doesn't understand how JavaScript handles references to values. – Rich Aug 28 '19 at 15:17
  • Sorry, this doesn't make any sense with Angular two-way data binding. – Vahid Najafi Aug 28 '19 at 15:17
  • @VahidNajafi It's definitely happen due to two way binding functionality.You don't need to update that value to array, if you update that to that parameter it's directly affect to that array. just console log that array after you update that parameter , you will find updated array. – Ronak Patel Aug 28 '19 at 15:21
  • There is no form here, so "two-way data binding" doesn't make any sense. Please check the accepted answer. – Vahid Najafi Aug 28 '19 at 15:23