0

I am trying to update the value of an Array in my service from child component.

Here is the service at the top level of application

feature.service.ts

export class FeatureService {
    
  private myFeatures: MyFeature[] = [
    new Feature(1, '1st Empty String'),
    new Feature(2, '2nd Empty String'),
    new Feature(3, '3rd Empty String'),
  ];
        
  getFeatures() {
    return this.myFeatures.slice();
  }
}

printFeatureArray() {
  console.log(this.myFeatures); 
}

As you can see it, it initialises MyFeatures Array to hold the most up date version of my data,

I would like to change this data through a child component, and be able to call the printFeatureArray function to print the updated values.

Here are the child components constructing my feature items from the getDocFeatures function generating a reference for display, this component is used to create individual items per instance.

component.ts

export class Component {
  myFeatures: MyFeature[] | undefined;
        
  constructor(private docBuilderService: DocBuilderService) {}
    
  ngOnInit() {
    this.myFeatures = this.FeatureService.getDocFeatures();
  }
}

component.html

<div
  class="list"
  *ngFor="let myFeature of myFeatures; let i = index"
>
          
<app-my-item [docFeature]="docFeature"></app-my-item>
</div>

Finally from within the my-item component I have an input HTML element that I would like to record user input and populate the myFeatures Array on the very top level.

<input
  #inputTag
  (keyup)="getValue(inputTag.value)"
  [ngClass]="addClassTemplate()"
  (click)="onSelected()"
  type="text"
  placeholder="{{ docFeature?.inputValue }}"
/>

my-item.component.ts


export class MyItemComponent {
  value: string | undefined;
        
  constructor() {}
          
  getValue(value: string) {
    console.log(value);
  }
}

How do i update the original Array inside the service from the bottom level of this component tree?

Thanks!

2
  • Use a Subject and a Subscription. Then you can subscribe to it. If you change anything all subscribed components gets informed. Commented Feb 12, 2023 at 17:56
  • The component to the Service. And the service call the Subjects "next" method to push a new value. Look for Angular Service Subject. I think you wanna find many. If not let me know Commented Feb 12, 2023 at 18:23

1 Answer 1

0

Service

For a cross communication a Subject in a Service is the best practice.

myService

private mySubject: Subject<string> = new Subject();

getMySubject() {
  return this.mySubject.asObservable();
}

doSomething(text: string) {
  this.mySubject.next(text);
}

Component

Code Behind

...
private mySub!: Subscription;
myTextData: string = "";

constuctor(private myService: MyService) {}

ngOnInit(): void {
  this.mySub = this.myService.getMySubject().subscribe(data => { this.myTextData = data; }
}

ngOnDestroy(): void {
  this.mySub.unsubscribe();
}

Components HTML

<div>
  {{ myTextData }}
</div>

You can use an array of objects, too. And then use it with *ngFor. All the same. Every time the service calls the Subjects next method, all components they subscribe to it will be updated.

Important We have the mySub object which we unsubscribe on ngOnDestroy this is very important! Otherwise the subscription is multiplied and fires multiple times. Thats not what we want :-). Second Important In the Service we'll never return the Subject directly. Instead we return its Observable. Looks a little strange but that is the correctly way to do this and not a workaround.

All about this here.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.