Search code examples
angularangular6angular-servicesangular-dynamic-components

Access an instance of a component and change its value in angular 6


<rio-hello name="World"></rio-hello>
<rio-hello [name]="helloName"></rio-hello>
  1. onClick of the first component I want to change the value of the second component

  2. The value (the name) should be changed from "helloworld" to "myworld". Both components are loaded on the same page. How can I differentiate between them and change the value?

  3. If both are loaded dynamically how can I access the instance and change value dynamically?

Small example: https://stackblitz.com/edit/angular-iew4mn

in this dynamically loaded component not mentioned


Solution

  • I've create a stackblitz building up on your example which makes it possible to change the name of a HelloComponent by clicking on another HelloComponent

    Explanation

    In order to access different instances of a Component (HelloComponent) I used a service (HelloService) which "knows" about the existence of every HelloComponent-Instance.

    import { Injectable } from '@angular/core';
    import { HelloComponent } from './hello.component';
    
    @Injectable({
      providedIn: 'root',
    })
    
    export class HelloService {
      helloCompoents = {}
    
      constructor() { }
    
      add(_id: number, _component: HelloComponent) {
        // store a reference to the component and use the components id as identifier
        this.helloCompoents[_id] = _component;
      }
    
      change(_id) {
        // here you can define the new name
        this.helloCompoents[_id].name = 'some other name'
      }
    
    }
    

    The service is quite simple. All it does is provide

    1. a function to add a new HelloComponent-instance to an object helloComponents (id as key, HelloComponent-instance as value) and
    2. a function which enables you to change the name of an HelloComponent-instance by using the id of the HelloComponent to identify the component which should be changed.

    Since the service doesn't know about any HelloComponent-instances yet, we need to change the HelloComponent:

    import { Component, Input, OnInit } from '@angular/core';
    import { HelloService } from './hello.service';
    
    @Component({
      selector: 'hello',
      template: `<h1 (click)="change()">Hello {{name}}!</h1>`,
      styles: [`h1 { font-family: Lato; }`]
    })
    export class HelloComponent implements OnInit {
      @Input() id: number;
      @Input() name: string;
      @Input() changeHelloComponentId: number;
    
      constructor(private helloService: HelloService) { }
    
      ngOnInit() {
        // add the current HelloComponent to the list of helloComponents within the service
        this.helloService.add(this.id, this);
      }
    
      change() {
        // call the change function of the service which will then change the name of the defined HelloComponent
        this.helloService.change(this.changeHelloComponentId);
      }
    }
    

    On creation of the HelloComponent-instance now we use HelloService to add the current instance to the helloComponents of the service.

    And the click function will call the helloService.change(..) function which then changes the name.

    The template of the HelloComponent now looks like this:

    <div *ngFor="let list of data ">
        <hello id="{{list.id}}" name="{{ list.name }}" changeHelloComponentId="{{list.changeId}}"></hello>
    </div>
    

    I've added id which is the id of the current HelloComponent-instance and changeHelloComponentId which is the id of the HelloComponent-instance whos name should be changed if the current item is clicked.

    Lastly you need to change your data-list:

    this.data = [
          { id: 0, "name": "rio", changeId: 1 },
          { id: 1, "name": "angu" }]