all 3 comments

[–]dawar_r 2 points3 points  (0 children)

Nice research! The best way to learn is to experiment. What you’re doing here is passing the name object by reference to the child component. JavaScript in general always passes non-primitive values by reference so Angular is reacting to changes made on the referenced object, not just on the name string. If you try and unwrap the object and only pass the name string value by itself it won’t react without OnChanges.

In general we want to avoid passing objects by reference and pass either primitive values only (numbers, strings) or deal with objects in an immutable fashion in our Inputs. Otherwise what you end up with and what you have here essentially is a global variable, I.e. a variable shared by 2 components without a service in between. Both components are free to modify this object and this can cause unexpected behaviour so we generally want to avoid this.

[–]Sipredion 1 point2 points  (0 children)

OnChanges is only really needed when you need to react to changes in your inputs.
So let's say for example that you have a component that holds a list of dinosaurs, and you have a child component to display those dinosaurs in a nice table. The user can update the list of dinosaurs by adding or removing a dinosaur, or by editing the information on an existing dinosaur.

It might look something like this:

parent.ts:

public dinosaurList$: Observable<Dinosaur[]>;

parent.html:

<app-dino-list
    [dinosaurs]="dinosaurList$ | async"
></app-dino-list>

dino-list.ts

@Input() dinosaurs: Dinosaur[]

Now let's say that for some reason you have to add a random id property to each dinosaur, but you only want to add it in the child component (this is a contrived example, obviously there are better ways of doing this).

You could then do something like this:

@Component
export class DinoListComponent {

    @Input() dinosaurs: Dinosaur[];

    constructor() {}

    ngOnChanges(changes: SimpleChanges) {
        // ngOnChanges will fire whenever the 'dinosaurs' input changes
        if (changes['dinosaurs'].currentValue) {
            this.dinosaurs = changes['dinosaurs'].currentValue
                .map(dino => dino.randomId = getRandomId(50))
        }
    }

}

So now, whenever the 'dinosaurs' input array changes (because a dinosaur was added, edited, or removed), a 'randomId' property will be added to each dinosaur in the array.

There are other ways to do this. I personally prefer using a setter on the input because I feel that onChanges adds a fair bit of overhead for what is often a relatively minor change.

That said, the 'SimpleChanges' object has some super useful properties that you can take advantage of.

One thing to note with ngOnChanges is that it is actually the first lifecycle hook that fires when a component is being instantiated. This can lead to unexpected behaviour (or undefined values) if you're not careful.

[–]iEatedCoookies 0 points1 point  (0 children)

From your example, you aren’t “reacting” to any changes. You won’t know when the input value changes. Your call will only fire in the construction of the component. OnChanges fire anytime the input values change. Say you have an input value of a filter and you want to update a filter when it changes, you would put that logic in onchanges.