Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my angular app update result only if I resize my screen?

I started using Angular and Reactive programming 3 days ago so I m new to this technology.

I have successfully implemented a spring boot backend server that will give me tweets by tag.

Now I'm trying to show for every received message on my flux an element to a list component in my angular app.

I'm successfully login to the console the search result but my ngFor is not working ... I don't know where I'm missing the good practice.

Here is my angular app implementation

My reactive twitter service:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of, BehaviorSubject } from 'rxjs';
import { ITweet } from './model/itweet';

@Injectable({
    providedIn: 'root'
})
export class ReactiveTwitterSpringService {

    tweetSubject = new BehaviorSubject<ITweet>(new ITweet);

    currentTweet = this.tweetSubject.asObservable();

    tweetTag: string;

    baseUrl = 'http://localhost:8081/search';

    search(tag: string) {

        const url = this.baseUrl + '/' + tag.trim().split(' ').join('_');

        return Observable.create(
            observer => {
                const enventSource = new EventSource(url);
                enventSource.onmessage = (message) => {
                    const json = JSON.parse(message.data);
                    console.log(new ITweet(json.tweetData.name, json.tweetData.text, json.tag));
                    this.tweetSubject.next(new ITweet(json.tweetData.name, json.tweetData.text, json.tag));
                    observer.next(new ITweet(json.tweetData.name, json.tweetData.text, json.tag));
                };
                enventSource.onerror = (error) => {
                    if (enventSource.readyState === 0) {
                        console.log('The stream has been closed by the server.');
                        enventSource.close();
                        observer.complete();
                    } else {
                        observer.error('EventSource error: ' + error);
                    }
                };
               return () => enventSource.close();
            }
        );
    }

    constructor() { }
}

My component where I have the search and the list of results:

import { Component, OnInit } from '@angular/core';
import { BreakPointService } from '../../providers/break-point.service';
import { ReactiveTwitterSpringService } from '../../reactive/reactive-twitter-spring.service';
import { ITweet } from '../../reactive/model/itweet';
import { Subscription } from 'rxjs';

@Component({
    selector: 'app-tweet-list',
    templateUrl: './tweet-list.component.html',
    styleUrls: ['./tweet-list.component.css']
})
export class TweetListComponent implements OnInit {
    list_div_class;
    search_input_class;

    search_results: ITweet[] = new Array();
    subscribe: Subscription = new Subscription();
    constructor(private tweetService: ReactiveTwitterSpringService) { }

    search(tag) {
        this.search_results = new Array();
        this.subscribe.unsubscribe();
        this.subscribe = new Subscription();
        this.subscribe.add(this.tweetService.search(tag).subscribe(tweet => {
            this.search_results.push(tweet);
            console.log(tweet);
        }));
        console.log('array contains ' + this.search_results);
    }

    ngOnInit() {
        BreakPointService.current_css.subscribe(value => {
            console.log('value is ' + value);
            this.setupCss(JSON.parse(value));
        });
    }

    setupCss(value: any): any {
        this.list_div_class = value.list_div_class;
        this.search_input_class = value.search_input_class;
    }
}

The html template related to my component:

<div class="{{list_div_class}}">
  <input type="text" class="{{search_input_class}}" (keyup.enter)="search(searchInput.value)" #searchInput>
  <ul class="w3-ul">
    <li *ngFor="let tweet of search_results ">
        data
      <app-tweet-detail [detail]="tweet"></app-tweet-detail>
    </li>
  </ul>
</div>

I'm watching lot of tutorials but I don't know why I'm getting data on my console but not in my array? I feel that I'm using observables the wrong way, but to be honest I don't have understood them very well.

What am I doing wrong? And how to fix it ?

Update

Accidentally I resized my screen and the data was displayed, why?

here is images of my html content before and after resise

before

after

after

Thank you

For full project github repository

like image 219
Mohammed Housseyn Taleb Avatar asked Nov 18 '25 10:11

Mohammed Housseyn Taleb


1 Answers

In Angular, We need to manually trigger change-detection by calling changeDetectorRef.detectChanges() or you can use subject/behavior subject with async observable.

Approach 1:

constructor(private cdr: ChangeDetectorRef){} 
this.subscribe.add(this.tweetService.search(tag).subscribe(tweet => {
    this.search_results.push(tweet);
    this.search_results = this.search_results.slice();
    this.cdr.detectChanges();
    console.log(tweet);
}));

Approach 2:

public this.search_results$ = new Subject<any>();
this.subscribe.add(this.tweetService.search(tag).subscribe(tweet => {
    this.search_results.push(tweet);
    this.search_results$.next(this.search_results);
    console.log(tweet);
}));

Template:

<li *ngFor="let tweet of search_results$ | async ">
    data
  <app-tweet-detail [detail]="tweet"></app-tweet-detail>
</li>
like image 96
Suresh Kumar Ariya Avatar answered Nov 20 '25 22:11

Suresh Kumar Ariya



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!