0

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.

Jeet
  • 359
  • 1
  • 6
  • 24
  • 2
    You are not implementing `OnChanges` and `ngOnChanges` only triggered when there is/are change(s) in the `@Input` variables. But there are no `@Input` variables in your parent component – Sivakumar Tadisetti Jul 31 '20 at 13:05
  • So how should I deal with it now? Is there any way to do without ngOnchanges? – Jeet Jul 31 '20 at 13:08
  • 2
    I agree with @SivakumarTadisetti, you can use `(ngModelChange)` inside your parent's template to call `this.child.submit` instead of the `ngOnChanges` – StPaulis Jul 31 '20 at 13:15
  • @StPaulis - When I do (ngModelChange)="this.child.mySubmit()" , the changes are happening but it is not simultaneous change. When 2 changes are made then the first change change is reflecting. Why is it so? Am I doing anything wrong? – Jeet Jul 31 '20 at 14:22
  • Be careful, that the order matters, If you put ngModel above ngModelChange it will called first, otherwise the opposite. – StPaulis Aug 01 '20 at 13:47

2 Answers2

2

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.

ruth
  • 29,535
  • 4
  • 30
  • 57
0

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