4

I have a set of "article" documents stored in an "articles" collection in a Firestore no-SQL database. I am pulling these articles into an Angular 6 (^6.0.3) project using angularfire2 (^5.0.0-rc/10) and firebase (^5.0.4). The data is held in a service as observables and then pulled into various components and converted into objects when needed.

I am having a strange issue when I try to display properties of the object in HTML through interpolation and data binding. It simply does not show anything. I click an article tile from a menu, pass the article id as a string to my service, and then create an observable that points to the article with the corresponding id. I then subscribe to the observable in my component class and store the data as an object. The object prints fine on its own, but if I reference different properties it acts as if there is no data.

This is the code from the controller for my component:

article: any = {};
articleString: string;

selectArticle(articleId: string) {
            this.articlesService.getArticleObs(articleId).subscribe((data) => {
                this.article = data;
                this.articleString = JSON.stringify(this.article);
            });
        }

Which calls this function in the service:

getArticleObs(articleId: string) {
        console.log('article id sent to service: ' + articleId);
        this.articleDoc = this.db.doc(`articles/${articleId}`);
        return this.articleDoc.valueChanges();
    }

and should display here in the HTML:

<ng-template #article>
        <div class="article-body">
            <div fxLayout="row">
                <div class="article-image">
                    <img [src]="article?.game.image">
                </div>
                <div class="article-header" fxLayout="column">
                    <div>{{this.article?.title}}</div>
                    <h1>{{ article?.game?.title }} Review:</h1>
                    <div fxLayout="row">
                        <h2>Title:{{ article?.title }}</h2>
                        <h2>Author:{{ article?.author }}</h2>
                    </div>
                </div>
            </div>
            <div class="article-content" [innerHTML]="article?.content"></div>
            <div class="article-comments">
                Comments:{{ article?.comments }}
            </div>
        </div>
        <h3>{{ articleString }}</h3>
    </ng-template>

I can console.log(article) and get a complete object.

enter image description here

I also get a complete object showing on the screen with {{articleString}} but for any of the other interpolation or databinding there is no data.

What my page looks like

Can anyone tell me why the HTML thinks that the object properties are empty strings?

UPDATE:

I just tried this in my controller:

selectArticle(articleId: string) {
            this.articlesService.getArticleObs(articleId).subscribe((data) => {
                this.article = data;
                console.log(1 + this.article);
                this.articleString = JSON.stringify(this.article);
                console.log(2 + this.article);
            });
            console.log(3 + this.article);
        }

The result in the console makes me think it is an async issue. The 3 prints first with an empty object. The 1 prints next with the complete object and then the 2, also with a complete object.

1 Answer 1

4
+50

2 Things you can try (If you haven't already):

1) Use parenthesis (do the same for all your bindings):

<h1>{{ (article)?.game?.title }} Review:</h1>

2) Use the async pipe to unwrap the Observable, change your selectArticle method:

selectArticle(articleId: string) {
  // Don't subscribe here
  this.article = this.articlesService.getArticleObs(articleId);
}

In the template (do the same for all your bindings):

<h1>{{ (article | async)?.game?.title }} Review:</h1>

Sidenote: You also have a typo in your code, this line:

<div>{{this.article?.title}}</div>

should not be using this

<div>{{article?.title}}</div>
Sign up to request clarification or add additional context in comments.

9 Comments

Thanks for pointing out the typo. I tried both suggestions and neither changed anything, but I think you are onto something with the async pipe. I don't understand that super well, but I did some more tests and I think that it may be the issue. I added the info to the question.
can you try change article: any = {}; to article: Observable<any>; and try with the async pipe. See how they do it in the docs
Here is a working demo based on your code: stackblitz.com/edit/angular-dzqva6
Awesome! I mimicked the demo (step 2) and it worked perfectly. The issue was caused because I was missing the "$" at the end of my variable. I only got it to work with "article$". What is the "$" indicating and why do I need it?
Thats quite strange because the $ symbol is just syntactic sugar commonly used denote that the property is an Observable.
|

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.