5

I share array of objects to my components trough service. So in one moment I want to replace one of the array object's properties with the properties of new object(I replace the object). So my shared object should update in all templates where it is used.

https://plnkr.co/edit/0sRxSivEaEPLsNAJo7MV?p=preview

// my.component.ts
@Component({ 
selector: 'my-component',
template: '<div>MyComponent: {{item.name}}</div>',
})
export class MyComponent implements OnInit {
  constructor(private myService: MyService) {}

  private item = myService.myListData[0];

  ngOnInit() {
    // 1. - This triggers change detection in app.ts template
    this.item.name = 'Name 1111';

    setTimeout(() => {
      // 2. - This doesn't trigger change detection in app.ts template
      let newObj = {name: 'Name 222', age: 225};
      this.item = newObj;
    }, 3000);
  }
}

In my case //1 change template value in app.ts and my.component.ts but //2 trigger change only in my.component.ts

I'm wondering why //2 is doesn't update app.ts template and is there a way to do it without looping trough object properties?

Update: I managed to solve my issue by using Object.assign(). There is no change detection when replacing objects.

setTimeout(() => {
  // 2. - This doesn't trigger change detection in app.ts template
  let newObj = {name: 'Name 222', age: 225};
  Object.assign( this.item , newObj);
}, 3000);
10
  • 3
    Quite a lot of captions but almost no context. Please post the components class, including the @Component() decorator and the template of the component and explain the actual behavior and expected behavior. Commented Jan 18, 2017 at 8:14
  • Ok, I think now it is ok. Thank you Commented Jan 18, 2017 at 8:29
  • 1
    There is still no HTML. let before let item is redundant or even invalid (not a TS pro). I think this variable assignments code should be inside a method. Doesn't make sense the way you have it. Commented Jan 18, 2017 at 8:32
  • 1
    I think it is. Change detection happens all the time, no matter if you change something or not. What you're probably talking about is whether change detection should detect a change and update the view. For that we need to see your view (HTML) and your explanation what the actual and expected behavior is. Commented Jan 18, 2017 at 8:37
  • 2
    What you seem to expect doesn't have anything to do with change detection. If you assign a new (different) object to this.item then there is no connection between AppComponent and MyComponent anymore. Why do you expect anything to update in AppComponent? Commented Jan 18, 2017 at 12:25

2 Answers 2

3

I know this is a bit of an old question, but I was running into an issue where change detection wasn't running "correctly", or at least when I anticipated it would.

In my case, assigning a variable I was watching, we'll call it oldValue, wasn't triggering the change detection. This was how I had it originally:

// INCORRECT APPROACH
oldValue = newValue

As noted in the Updated... portion of the OP's question, a good solution is to use Object.assign():

// CORRECT APPROACH
Object.assign(oldValue, newValue)

In this case (in my experience), change detection would get run on oldValue.

Cheers!

Sign up to request clarification or add additional context in comments.

Comments

0

I think the OP is wanting to bind several views to the same service data. Here is a plunker (modified poster's original) showing how it can be done. Basically bind the views to the same service member and not to the component's individual members. So that the changes reflects automatically in all the similar bindings.

https://plnkr.co/edit/PNQmLarmP3g7j7f42cXD?p=preview

@Component({ 
    selector: 'my-component',
    template: '<div>MyComponent: {{myService.Item.name}}</div>',
})
export class MyComponent implements OnInit {
   constructor(private myService: MyService) {}

   private item = myService.myListData[0];

   ngOnInit() {
     // 1. - This triggers change detection
     this.item.name = 'Name 1111'
     this.myService.Item = this.item;

     setTimeout(() => {
       // 2. - This doesn't trigger change detection in app.ts template
       let newObj = {name: 'Name 222', age: 225};
       this.myService.Item = newObj;
     }, 3000);
   }
}

On this topic, I always wondered if there is a way to achieve the same and create a reference to a service member like a short-hand to be used in the component HTML.

Item = Alias of MyService.Item ;

and the HTML would simply bind to

{{Item}}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.