0

i'm making an angular application and i have an empty array


addresses : any [] = [];


then after a click event i start an http observable to charge the data from a server

and then i make a pipe map to take what i want and then i make a subscribe

const URL ='some url';
onSearch() {
this.httpClient
  .get(`URL${{some data to generate the http observable}}`)
  .pipe(
    map(response => response.address),
    tap( => console.log("address array", address))    // address array [Object, Object, Object]
  )
  .subscribe(address => this.addresses = address);
}

in the html template i have this

<button (click)="onSearch()"> search address </button>

<ul *ngFor="let address of addresses">

<li>{{address.one}} - {{address.two}} - {{address.three}}</li>

</ul>

the firs time i clcik the button is ok i see the result , but the second time i click the button

the first result is deleted from the second.

My problem is how can i store multiple result in an array and how can i see thei in the html temlate?

2 Answers 2

3

Leveraging angular's change detection

You can try this.

.subscribe(addressArray => 
  addressArray.foreach(
    address => this.addresses.push(address)
  )
);

or this:

.subscribe(addressArray => {
  for (const address of addressArray){
    address => this.addresses.push(address);
  }
});

These two approaches do not work well with angular change detection since they're are mutating an existing array rather than creating a new array.

These approaches both create new arrays and angular change detection will have an easy time spotting.

this:

.subscribe(addressArray =>
  this.addresses = this.addresses.concat(addressArray)
);

or this:

.subscribe(addressArray =>
  this.addresses = [...this.addresses, ...addressArray]
);

They're all very similar ways of achieving the same thing.

Leveraging Angular's async Pipe

Here's a very different way: Output your result array directly in your stream!

Instead of an array like this:

addresses: any[] = [];

You have an Observable and a Subject like this:

newAddresses = new Subject<any[]>();
addresses = newAddresses.pipe(
    scan((acc, val) => ([...acc,...val]), [])
)

Then your search emits results directly to your subject.

const URL ='some url';
onSearch() {
  this.httpClient
    .get(`URL${{some data to generate the http observable}}`)
    .subscribe(response => this.newAddresses.next(response.address));
}

Now in your HTML, you can subscribe to this array using angular's async pipe

<button (click)="onSearch()"> search address </button>
<ul *ngFor="let address of addresses | async">
  <li>{{address.one}} - {{address.two}} - {{address.three}}</li>
</ul>

This is a reasonable amount of extra work. So why bother?

  1. Flexibility: Now any number of methods can update your addresses, and they'll all get managed by scan in a uniform way.
  2. Maintainability: If you want to change or format addresses in the future, there's a simple & singular place to do it.
  3. Extenability: You can add in fancy RxJS operators like debounce to control how results appear on the screen. It's a really nice way to stop display-stuttering when events get queued up.
  4. Performance: If your application relies on pushing data rather than binding it, you can turn off angular's change detection entirely and boost the performance of your app :).

Even if you're not going to turn off change detection, you can mutate a massive array in memory and not worry about whether change detection will pick it up or need to explicitly tell change detection to check the contents of your array for changes.

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

1 Comment

Thanks, its works for me: .subscribe(addressArray => this.addresses = [...this.addresses, ...addressArray] );
1

You can try this.

.subscribe(address => this.addresses = [...address, ...this.addresses]);

2 Comments

did you use a spread operator? what does it means this sintax [...address, ...this.addresses] ??
Yes, I used the spread operator to copy the result address, in your globally declared address.If this helped, you can mark it as the answer. For more info, you can visit, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

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.