Vivian River
Vivian River

Reputation: 32400

How to refresh data in an AngularJS component plus data in components bound to a property of its view model?

I'm working on an AngularJS application that contains a component that displays data that is fetched from a remote data source, a very common scenario.

Let's call it the "record" component.

The view model for the record looks like this:

record.viewModel = {
    firstName: "Bob",
    lastName: "Smith",
    data1: "foo",
    data2: "bar",
    dateRange: {
       start: "1/1/2019",
       end: "12/31/2019"
    }
}

I also have "date range picker" component. It uses an AngularJS "<" binding to bind to record.viewModel.dataRange.

When creating a new record, it is easy to bind a new object to the date range picker component. Just create a new object {} and assign it to record.viewModel.dateRange in the $onInit method. Easy!

However, for updating an existing record, it's much more complicated because the record to be updated is fetched asynchronously. I can't simply assign the fetched dateRange to record.viewModel.dateRange because that would change the variable's object reference while leaving the binding for the dateRangeObject still bound to the old object reference. The solution I used was to bind a function to the date range picker component and pass the new dateRange to that function.

The solution works, but it's very unwieldy. It's difficult to make code changes without breaking things, and now, I've had to create a new component where the bindings are several layers deep and it's giving me a headache just thinking about it. I don't want to even try to rig up example code because it's so ugly.

I need a better way to do this. I feel like the crux of the matter is the object reference that is bound to the date range picker component.

Can I make it so that if I fetch my view model from an asynchronous data source, I can assign the result to a variable and update the view model for the record component and the date range picker component in fell swoop?

Upvotes: 1

Views: 155

Answers (1)

georgeawg
georgeawg

Reputation: 48968

I can't simply assign the fetched dateRange to record.viewModel.dateRange because that would change the variable's object reference

record.viewModel = {
    firstName: "Bob",
    lastName: "Smith",
    data1: "foo",
    data2: "bar",
    dateRange: {
       start: "1/1/2019",
       end: "12/31/2019"
    }
}

To update the properties of an object without changing the object reference, use Object.assign

Object.assign(record.viewModel.dateRange, response.data.dateRange);

The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object.


Update

if there are components within components, I have to go thru this and recursively run Object.assign

To do a deep copy, use angular.copy:

angular.copy(record.viewModel, response.data.viewModel);

Creates a deep copy of source, which should be an object or an array.

Upvotes: 1

Related Questions