13

I have an component in which you can enter some search terms and it will filter the content using a *ngFor loop. The trouble is when I enter a search term I need to click the screen for the update to take effect visually.

Here is the part of the html code in which the loop occurs:

    <li *ngFor="let item of posts | reverse; let i = index; ">
        <div class="media" *ngIf="item.doesContainTags(searchTags)">

The code that executes on the input field where you enter the tags to search for is:

 updateSearchTags() {
    event.stopPropagation();
    // sorter is what is types into the search by tag input field
    this.searchTags = this.sorter.split(',');
 }

Here is the static function on the post object:

  doesContainTags(searchTags: string[]): boolean {

    let array = this.tags.split(',');
    if(!array || array.length === 0) {return false;}
    if(!searchTags || searchTags.length === 0) {return false;}

    for(let searchTag of searchTags){
         if(array.indexOf(searchTag) === -1) {

        } else {
        return true;
        }
    }
    return false;
 }

Here is the code which gets the posts that are looped over:

            this.postsService.subscribeAllPosts()
            .do(console.log)
            .subscribe( posts => this.posts = posts);

Here is the code in the postsService which gets the observable:

 subscribeAllPosts(): Observable<Post[]> {
    return this.af.database.list('posts')
    .map(Post.fromJsonList);
 }

So all this works but the change is not showing unless I click the screen. Is there a way to manually call it to update. I was thinking I could call this manually within the updateSearchTags function which is updated after typing in the search by tags input but I am unsure of what code would do this.

  • Update, I have changed the event to a keypress event. Now however I am trying to get this event to happen after the two way binding happens as it is now just doing it before the binding occurs. It just shows each char after you click the next one.

Update 2 - Found the keyup event. Issued sorted.

Pete
  • 2,325
  • 3
  • 16
  • 22
  • 1
    My case was to trigger **ChangeDetection** from a **service**. My component wouldn't get updated after a form control was assigned in a **service**. [The solution is here](https://stackoverflow.com/a/40075680/3944285) – Reza Taba Oct 29 '22 at 19:17

2 Answers2

25

Try to use ChangeDetectorRef as shown below to update data. Possible reason could be that you're service code is running out of Angular framework.

import { Component, ChangeDetectorRef } from 'angular2/core';

@Component({
  (...)
})
export class MyComponent {
  constructor(private cdr:ChangeDetectorRef) {}   //<<###################### here

  this.postsService.subscribeAllPosts()
                   .do(console.log)
                   .subscribe( posts => {

                        this.posts = posts; 
   
                        this.cdr.detectChanges();  //<<<#################### here
                });
}
micronyks
  • 54,797
  • 15
  • 112
  • 146
  • I have tried your code. It seems it will not update until I leave the focus of the tag search field. I have tried this.cdr.detectChanges() within the end of the updateSearchTags function also but no good. – Pete Oct 28 '16 at 17:27
  • 3
    This worked for me on a similar issue where setting a model value in an Observable handler wasn't causing UI updates until a click/UI action in the view. – c0bra Feb 15 '18 at 22:19
  • 9
    This is why I hate angular. Thank you. – Frondor Sep 28 '18 at 18:44
  • 1
    after the value changes applied try, this.cdr.markForChecj(); this.cdr.detectChanges() on the next line. It works. This is why I love Angular. Thank you. – Rinold Mar 13 '19 at 10:49
  • In my case even this hack not helping. Value is coming from redux state, state updating, value in the component - no, need to click somewere... Can't love Angular, no f way... – Anton Pegov Mar 17 '21 at 12:27
  • @Frondor man i am starting to hate angular because of the `change detection` problems do you recommend learning react? – Kardon63 Apr 09 '21 at 11:51
  • For me, it was the zone issue, I had to move the subscription code inside ngZone.run() function and it worked fine for me – mark922 Nov 24 '22 at 10:41
1

I used the (keyup) event instead of the change/blur/keypress event.

Pete
  • 2,325
  • 3
  • 16
  • 22