1

I have two components: Parent, Child.

Here is the scenario:

  • Child gets the value from Parent which continue changes
  • Child is always updated for the changed value
  • Child manipulates the value and displays it
  • On the Parent side the value doesn't get changed just becauseof it's manipulated on the Child side

An example use case: enter image description here

I've tried this with the @Input. Because the @Input value gets manipulated on the Child side, on the Parent side it changes also. This is what I want to prevent, but also still want to keep getting the updated value from the Parent side.

An example code with @Input:

@Component({
    selector: 'c-parent',
    template: `
           <div>{{question.name}}</div>
           <button type="button" label="xxx" (click)="changeTheValue()"></button> 
           <br/>       
           <c-child [tmpQuestion]="question"></c-child>`
})

export class Parent implements OnInit {

    question: Question; // don't get changed from the Child side

    ngOnInit() {
        question.name = "1"; 
    }
    changeTheValue(){
        question.name = "2";
    }
}

@Component({
    selector: 'c-child',
    template: `<div>{{tmpQuestion.name}}</div>`
})

export class Child implements OnInit {

    @Input() tmpQuestion: Question; // be updated for the changes

    ngOnInit() {
        tmpQuestion.name = "This is the question: " + question.name; //manipulate the value
    }
}

How can I do this with @Input approach or do I need to use something else?

GG.
  • 21,083
  • 14
  • 84
  • 130
Korki Korkig
  • 2,736
  • 9
  • 34
  • 51
  • You need to clone the value before you send it to the child if you don't want the parent see changes made by the child when the value is an object. Primitive values `number`, `string`, `boolean`, are copied by default. Objects are sent by reference. – Günter Zöchbauer Dec 24 '16 at 17:21

1 Answers1

1

Plunker

Using this

Added this to variables inside functions so question.name becomes this.question.name.

Primatives

Primatives (String, Number, Boolean, Symbol) are easier to work with if you want the child component to detect changes so in the parent component I sent the name property into the child component's input field.

Child Component Manipulated Value

A few things need to happen to display a manipulated value in the child component:

  • Create a variable for the manipulated value, I used manipulatedValue.
  • Move the manipulation logic into it's own function

like this:

manipulate() {
  this.manipulatedValue = "This is the question: " + this.tmpQuestionName;
}
  • Call the manipulate function inside both ngOnInit and ngOnChanges

Pipes

If all you need is to do value manipulation you might be better off using a pipe

Parent Component

@Component({
    selector: 'c-parent',
    template: `
           <div>Parent Question Name: {{question.name}}</div>
           <button type="button" label="xxx" (click)="changeTheValue()">Change the value</button> 
           <br/>       
           <c-child [tmpQuestionName]="question.name"></c-child>`
})
export class Parent implements OnInit {

    question = { name: '1' };

    ngOnInit() {
        this.question.name = "1"; 
    }
    changeTheValue(){
        this.question.name = 'new ' + this.question.name;
    }
}

Child Component

@Component({
    selector: 'c-child',
    template: `<div>Child Manipulated Value: {{manipulatedValue}}</div>`
})
export class Child implements OnChanges, OnInit {

    @Input() tmpQuestionName; // be updated for the changes
    manipulatedValue;

    ngOnInit() {
      this.manipulate();
    }

    ngOnChanges() {
      this.manipulate();
    }

    manipulate() {
      this.manipulatedValue = "This is the question: " + this.tmpQuestionName; //manipulate the value
    }
}
Community
  • 1
  • 1
adriancarriger
  • 2,970
  • 3
  • 19
  • 26