Jeet
Jeet

Reputation: 395

How to trigger a change in value with ngOnchanges?

I have a parent component and a reusable child component. I want to triger the values in the child component and display the result as the input in parent component changes without using any submit button. Whenever there is any change in the input value I want to invoke the mySubmit() function the child or reusable component with the updated value as it is reponsible for rendering the figure.

In the parent component (app.component.ts) :-

*export class AppComponent implements OnInit  {

  title = 'stl-app';
  filename:string=""abc;
  colorname:string ='red';
  perspective:string='35';

  @ViewChild(reusableAppComponent) child:reusableAppComponent;

  constructor(){}

  ngOnInit():void{

  }

  ngOnChanges(changes:SimpleChanges){
        this.child.mySubmit();
  }

 ngAfterViewInit(){
    this.child.mySubmit();
  }

   changedcolor(ev :Event){

    let c=(<HTMLSelectElement>ev.target).value;
    console.log("Hello" + c);
    this.colorname=c;
    this.child.mySubmit();

  } 
}*

In the parent component.html file (appcomponent.html) :-

*

<div>
<reusable-app [filename]= "filename" [colorname] = "colorname" [perspective]= "perspective"></reusable-app>
</div>
<div class="stl" style="position:absolute; right:500px;">
<mat-form-field style="width:600px">
  <mat-label>Name of the file</mat-label>
  <mat-hint> File path of only stl file</mat-hint>
  <input  matInput [(ngModel)]="filename"  name="filename"  required>
  </mat-form-field>
<br><br>
  <mat-form-field>
    <mat-label>Camera Perspective</mat-label>
    <mat-hint> values in Integer</mat-hint>
    <input  matInput [(ngModel)]="perspective"  name="perspective"  required> 
    </mat-form-field>
    <br><br>
    <mat-form-field>
      <mat-label>Select a Color</mat-label>
      <mat-select (change) ="changedcolor($event) [(ngModel)]="colorname" name="colorname" required>
        <mat-option>None</mat-option>
        <mat-option value="red">red</mat-option>
        <mat-option value="blue">blue</mat-option>
        <mat-option value="orange">orange</mat-option>
        </mat-select>
    </mat-form-field>
  </div>

In the child component.ts (Reusableappcomponent.ts) :-

*export class ReusableAppComponent implements OnInit {
  
@Input()
filename:string;
@Input()
colorname:any;
@Input()
perspective:number;

private scene: Scene;
private camera: PerspectiveCamera;
private renderer: WebGLRenderer;
@ViewChild("myCanvas") myCanvas:any;

  constructor(private service:ImlStlAppService,private render:Renderer2,private http: HttpClient,private sanitizer: DomSanitizer) {
   }

  ngOnInit(): void {
     //add listener for the resize of the window - will resize the renderer to fit the window
     let global = this.render.listen('window', 'resize', (evt) => {
      this.onWindowResize();
    })
  }
  mySubmit(){

//Render using the input parameters

}

}*

In the child component.html (ReusableComponent.html) :

*<div style="text-align:center">
<canvas #myCanvas id="myCanvas">
</canvas>
</div>*

I am confused why the rendering is not changing when I am changing the values in the input.

Upvotes: 0

Views: 4607

Answers (2)

matan megira
matan megira

Reputation: 1

you can do ngOnChanges(changes:SimpleChanges){ this.mySubmit(); } in child component. remember to write ReusableAppComponent implements OnChanges

Upvotes: 0

Barremian
Barremian

Reputation: 31125

What you're looking for is a reactive communication between the parent and the child component. There are multiple ways to do it. A common way between unrelated components is to use a singleton service.

But since you already have sibling relationship with the component, you could attach the @Input decorator to a setter instead of a member variable. This triggers the setter anytime the corresponding variable is changed in the parent component.

Try the following

Parent Controller

export class AppComponent implements OnInit {
  title = 'stl-app';
  filename: string = ""
  abc;
  colorname: string = 'red';
  perspective: string = '35';

  constructor() { }

  ngOnInit(): void { }

  changedcolor(ev: Event) {
    let c = ( < HTMLSelectElement > ev.target).value;
    console.log("Hello" + c);
    this.colorname = c;
    this.child.mySubmit();
  }
}

Child controller

export class ReusableAppComponent implements OnInit {
  _filename: string;
  @Input() colorname: any;
  @Input() perspective: number;

  @Input() 
  public set filename(name: string) {
    this._filename = name;
    this.mySubmit();           // <-- trigger the call here
  }

  private scene: Scene;
  private camera: PerspectiveCamera;
  private renderer: WebGLRenderer;
  @ViewChild("myCanvas") myCanvas: any;

  constructor(private service: ImlStlAppService, private render: Renderer2, private http: HttpClient, private sanitizer: DomSanitizer) {}

  ngOnInit(): void {
    //add listener for the resize of the window - will resize the renderer to fit the window
    let global = this.render.listen('window', 'resize', (evt) => {
      this.onWindowResize();
    })
  }

  mySubmit() {
    //Render using the input parameters
  }
}

I've only made the filename input a setter since that's what you seem to be interested in. However if you wish to trigger the mySubmit() if any of the input variable is changed, you could make each one of them a setter.

Upvotes: 2

Related Questions