0

I am trying to create components in angular 2 for this html

<div class="tab-content">
    <div class="tab-pane fade in active" id="playerCard" role="tabpanel" aria-labelledby="playerCard-tab">
        <div class="card">
            <div class="card-block">
                <h4 class="card-title text-muted">UltimateWarrior15</h4>
                <h6 class="card-subtitle text-muted">
                    Adventurer card
                </h6>
            </div>
            <img data-src="holder.js/100px180/?text=Image">
            <div class="card-block">
                <div class="form-group row">
                    <label class="col-xs-2 col-form-label">Rank</label>
                    <div class="col-xs-10">
                        <label class="form-control text-muted">D</label>
                    </div>
                </div>
                <div class="form-group row">
                    <label class="col-xs-2 col-form-label">Age</label>
                    <div class="col-xs-10">
                        <label class="form-control text-muted">15</label>
                    </div>
                </div>
                <div class="form-group row">
                    <label class="col-xs-2 col-form-label">Gender</label>
                    <div class="col-xs-10">
                        <label class="form-control text-muted">Male</label>
                    </div>
                </div>
                <div class="form-group row">
                    <label class="col-xs-2 col-form-label">Race</label>
                    <div class="col-xs-10">
                        <label class="form-control text-muted">Human</label>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

I created player-record component

import { Component } from '@angular/core';

@Component({
    moduleId: module.id,
    selector: 'player-record',
    templateUrl: 'player-record.component.html'
})
export class PlayerRecord {
    label: string;
    value: string
}

and its html template

<div class="form-group row">
    <label class="col-xs-2 col-form-label">{{label}}</label>
    <div class="col-xs-10">
        <label class="form-control text-muted">{{value}}</label>
    </div>
</div>

Then I created player-card component

import { Component } from '@angular/core';

import { Player } from './player';

const CONTENT_CARD_META = {
    "rank": "Rank",
    "age": "Age",
    "gender": "Gender",
    "race": "Race"
};

@Component({
    moduleId: module.id,
    selector: 'player-card',
    templateUrl: 'player-card.component.html'
})
export class PlayerCard {
    player: Player;
}

Its html template looks like this

<div class="tab-pane fade in active" id="playerCard" role="tabpanel" aria-labelledby="playerCard-tab">
    <div class="card">
        <div class="card-block">
            <h4 class="card-title text-muted">{{player.name}}</h4>
            <h6 class="card-subtitle text-muted">
                Adventurer card
            </h6>
        </div>
        <img data-src="holder.js/100px180/?text=Image">
        <div class="card-block">
            <!-- pseudo code
                    CONTENT_CARD_META.foreach { field, label ->
                        new PlayerRecord(label, player[field]).html
                    }
            -->
        </div>
    </div>
</div>

Player is just some kind of stub class that I am planning to replace with service call.

export class Player {
    id: string;
    rank: string;
    age: number;
    gender: string;
    race: string;
}

But how to iterate over CONTENT_CARD_META, get property from player object by key and the add markup of player-record component with the data inside the template of player-card?

Sample flow I made in pseudocode

<!-- pseudo code
        CONTENT_CARD_META.foreach { field, label ->
            new PlayerRecord(label, player[field]).html
        }
-->
lapots
  • 12,553
  • 32
  • 121
  • 242
  • Sounds like you want `*ngFor` and a subcomponent with `@Input`. Could you give a more minimal example to clarify the important parts? – jonrsharpe Nov 15 '16 at 18:12
  • @jonrsharpe I do not have any. I just created bunch of files `player.ts`, `player-card.component.html`, `player-card.component.ts`, `player-record.component.html`, `player-record.component.ts` and did not integrate it to the core angular 2 app – lapots Nov 15 '16 at 18:25
  • ...what? Please give a [mcve], it's currently unclear what your specific problem is. Are all of the styling-related elements really necessary, for example? – jonrsharpe Nov 15 '16 at 18:26
  • @jonrsharpe I do not know the way to provide minimal example of angular2 without those `package.json.` etc. I guess I search the answer myself – lapots Nov 15 '16 at 18:31

1 Answers1

0

Try this:

<div class="tab-pane fade in active" id="playerCard" role="tabpanel" aria-labelledby="playerCard-tab">
<div class="card">
    <div class="card-block">
        <h4 class="card-title text-muted">{{player.name}}</h4>
        <h6 class="card-subtitle text-muted">
            Adventurer card
        </h6>
    </div>
    <img data-src="holder.js/100px180/?text=Image">
    <div class="card-block">
        <div class="form-group row" *ngFor="let playerAttributeKey of Object.keys(CONTENT_CARD_META)"

          <label class="col-xs-2 col-form-label">{{CONTENT_CARD_META[playerAttributeKey]}}</label>
                <div class="col-xs-10">
                    <label class="form-control text-muted">{{player[playerAttributeKey]}}</label>
                </div>

      </div>
    </div>
</div>

or if you need the ordering preserved (although out of scope for this question really)...change CONTENT_CARD_META to be:

const CONTENT_CARD_META = [
    {"key": "rank", "display" "Rank"},
    {"key": "age", "display" "Age"},
    {"key": "gender", "display" "Gender"},
    {"key": "race", "display" "Race"}
];

...and...

<div class="tab-pane fade in active" id="playerCard" role="tabpanel" aria-labelledby="playerCard-tab">
<div class="card">
    <div class="card-block">
        <h4 class="card-title text-muted">{{player.name}}</h4>
        <h6 class="card-subtitle text-muted">
            Adventurer card
        </h6>
    </div>
    <img data-src="holder.js/100px180/?text=Image">
    <div class="card-block">
        <div class="form-group row" *ngFor="let playerAttribute of CONTENT_CARD_META"

          <label class="col-xs-2 col-form-label">{{playerAttribute.display]}}</label>
                <div class="col-xs-10">
                    <label class="form-control text-muted">{{player[playerAttribute.key ]}}</label>
                </div>

      </div>
    </div>
</div>

Brandon
  • 984
  • 1
  • 11
  • 26
  • The issue with this is that JS object order isn't guaranteed - if the OP wants the labels to appear in a specific order, they shouldn't be relying on it. That's why [key-value iteration is not supported](http://stackoverflow.com/a/31537666/3001761). – jonrsharpe Nov 15 '16 at 19:22