Stefan
Stefan

Reputation: 832

Reading a value from a map in a template (which is set via an observable)

My service is returning a Map. Now I want to use one of the values in my template but it won't show and I don't understand why.

I've created an example:

1 value is set via the constructor which is shown, the other 2 via an observable. The first one ('myKey') is shown the other one isn't.

@Injectable()
export class MessageService {

    loadTestData(): Observable<Map<string, string>> {
        const testData = new Map<string, string>();
        testData.set('mySecondKey', 'mySecondValue');
        testData.set('myThirdKey', 'myThirdValue');

        return Observable.of(testData);
    }
}

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <h3>Shown: {{test.get('myKey')}}</h3>
      <h3>Not shown: {{test.get('mySecondKey')}}</h3>
      <h3>Map size: {{test.size}}</h3>
    </div>
  `,
})
export class App implements OnInit {
  name:string;
  test: Map<string, string> = new Map<string, string>();

  constructor(private messageService: MessageService) {
    this.name = `Angular! v${VERSION.full}`
    this.test.set('myKey', 'myValue');
  }

  ngOnInit() {
    this.messageService.loadTestData().subscribe(data => {
      this.test = data;
    });

  }
}

https://plnkr.co/edit/6mUieUMJTSvekiNxEuU3

Upvotes: 0

Views: 155

Answers (2)

rusev
rusev

Reputation: 1920

Actually the code is perfectly fine with one exception - missing import of import { Observable } from 'rxjs/Rx';. Seems like current SystemJS configuration is swallowing the errors.

Here is updated plnkr - https://plnkr.co/edit/WyQzOos0IOnvRZkzWSRS?p=preview

Upvotes: 2

Vikhyath Maiya
Vikhyath Maiya

Reputation: 3202

This is because you are not waiting for the subscribed data abd trying to render it before the value arrives.Modify your code as follow

In your component declare a boolean variable

private dataAvailable:boolean=false;

And toggle the value once the data is available

ngOnInit() {
    this.messageService.loadTestData().subscribe(data => {
      this.test = data;
this.dataAvailable=true;

    });

  }

and in the template ,wait for the value

<div *ngIf="dataAvailable">
      <h2>Hello {{name}}</h2>
      <h3>Shown: {{test.get('myKey')}}</h3>
      <h3>Not shown: {{test.get('mySecondKey')}}</h3>
      <h3>Map size: {{test.size}}</h3>
    </div>

It should do the trick.You can as well use async pipe for achieving the same .You can find the docs here.Hope it helps

Upvotes: 0

Related Questions