2

I've just started learning Angular4 and I am facing an issue I cannot explain.

I'm now trying to build two components :

My main component is chatComponent it is supposed to display a list of child components msgComponent.

For this I defined an array of message msgArray in app.chatComponent and iterate over the messages through à *ngFor directive. For each messages I want to display a child component app.messageComponent.

So far, everything works well except the first message in msgArray is never displayed...

Why?

Here is my app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgForOf  } from '@angular/common';
import { NgModule } from '@angular/core';
import { NgModel, FormsModule }   from '@angular/forms';


import { ChatComponent } from './app.chatComponent';
import { MsgComponent } from './app.msgComponent';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule 
  ],
  declarations: [
    ChatComponent,
    MsgComponent
  ],
  providers: [],
  bootstrap: [ChatComponent, MsgComponent]
})
export class AppModule { }

Here is my main component : app.chatComponent.ts

import { Component } from '@angular/core';
import { MsgComponent } from './app.msgComponent';
import { Msg } from './app.msgModel';

var msgArray: Msg[] = [
  { id: '11', content: 'msg0' },
  { id: '11', content: 'msg1' },
  { id: '12', content: 'msg2' },
  { id: '13', content: 'msg3' },
  { id: '14', content: 'msg4' },
  { id: '15', content: 'msg5' },
  { id: '16', content: 'msg6' },
  { id: '17', content: 'msg7' },
  { id: '18', content: 'msg8' },
  { id: '19', content: 'msg9' },
  { id: '20', content: 'msg10' }
];

@Component({
  selector: 'chat-component',
  templateUrl: './app.chatComponent.html',
  styleUrls: ['./app.chatComponent.css']
})
export class ChatComponent {
    messages: Msg[] = msgArray;
    msg: Msg = new Msg();
}

app.chatComponent.html

<div>
    <ul class="messages">
        <msg-component *ngFor="let msg of messages" [msg]="msg.content"></msg-component>
    </ul>
</div>
<input [(ngModel)]="msg.content">

Here is my child component : app.msgComponent.ts

import { Component, Input } from '@angular/core';
import { Msg } from './app.msgModel';
@Component({
  selector: 'msg-component',
  templateUrl: './app.msgComponent.html',
  styleUrls: ['./app.msgComponent.css']
})
export class MsgComponent {
    @Input() msg: Msg;
}

app.msgComponent.html

<li>{{msg}}</li>

See demo on plunker

5
  • there is a typo in app.chatComponent.html. Should be "let msg of messages" Commented Sep 14, 2017 at 16:00
  • @rjustin You're right sorry I corrected it was a copy/past mistake. But it doesn't explain my problem :) Commented Sep 14, 2017 at 20:27
  • Can you make a plunker with what you have and get it to run? Commented Sep 14, 2017 at 20:43
  • @rjustin here is the demo on plunker, as you can see my first message's content is not displayed. ( actually the value of the first message is null ) plnkr.co/edit/mttSZ6sanD8k7GCgwUSx?p=preview Commented Sep 15, 2017 at 9:01
  • This a very odd problem. I have looked at this for 20 minutes now and am baffled. It has something to do with the @Input msg being null. if you set that it will show in the first item. This is not expected behavior. Ill keep fiddling with it. Commented Sep 15, 2017 at 16:41

1 Answer 1

1

Okay, the problem is that you are bootstrapping the msg component breaking the first render loop like so:

import { BrowserModule } from '@angular/platform-browser';
import { NgForOf  } from '@angular/common';
import { NgModule } from '@angular/core';
import { NgModel, FormsModule }   from '@angular/forms';


import { ChatComponent } from './app.chatComponent';
import { MsgComponent } from './app.msgComponent';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule 
  ],
  declarations: [
    ChatComponent,
    MsgComponent
  ],
  providers: [],
  bootstrap: [ChatComponent, MsgComponent]
})
export class AppModule { }

Instead try this:

import { BrowserModule } from '@angular/platform-browser';
import { NgForOf  } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule }   from '@angular/forms';
import { NgModel } from '@angular/forms';

import { ChatComponent } from 'src/app.chatComponent';
import { MsgComponent } from 'src/app.msgComponent';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule 
  ],
  declarations: [
    ChatComponent,
    MsgComponent
  ],
  providers: [],
  bootstrap: [ChatComponent]
})
export class AppModule { }

here is a working simplified version.

You dont need to bootstrap all you components, you just need to have them in declarations.

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

3 Comments

Tanks for this answer, it's working well. How would you explain quickly the role of this "bootstrap" directive ?
@jmchey If this answer worked for you please mark it as accepted to help others in the future. Here is the link to docs about bootstrapping angular.io/guide/bootstrapping
I'm doing it sorry, I'm new here :)

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.