简体   繁体   English

打字稿父母/子女

[英]Typescript Parent/Child

Angular2/Typescript - Parent/Child Directive(?) Angular2 / Typescript-父/子指令(?)

I'm new to, and very much still learning, Angular2/Typescript/javascript. 我是Angular2 / Typescript / javascript的新手,并且仍在学习中。 As a result, I'm not entirely sure how to title my question. 结果,我不确定如何为我的问题加上标题。 The basis of my app is a card game. 我的应用程序的基础是纸牌游戏。 The premise (relative to my struggle) is that the game has 2 players and each player has a hand of 5 cards. 前提(相对于我的奋斗而言)是游戏有2个玩家,每个玩家有5张牌。 I have API calls to build/return the hand of cards. 我有API调用来建立/返还手牌。

In my app.component template, I have 2 div blocks; 在我的app.component模板中,我有2个div块; one for each players' hand of cards. 每个玩家的手牌一张。 Currently, I have it working by building two distinct arrays of cards (named p1cards and p2cards). 目前,我通过构建两个不同的卡阵列(名为p1cards和p2cards)来工作。 Here is the relative code for that: 这是相对的代码:

<div class="player1Cards" id="player1Cards">
  <ul class="list-group">
    <div draggable *ngFor="let card of p1cards" [dragData]="card" 
class="list-group-item">
      <img src="{{cardBluePath + card.fileName}}">
    </div>
  </ul>
</div>

<div class="player2Cards" id="player2Cards">
  <ul class="list-group">
    <div draggable *ngFor="let card of p2cards" [dragData]="card" 
class="list-group-item">
      <img src="{{cardBluePath + card.fileName}}">
    </div>
  </ul>
</div>

And here is the actual export class of the entire AppComponent: 这是整个AppComponent的实际导出类:

@Injectable()
export class AppComponent implements OnInit
{
  @ViewChild(ModalComponent) errorMsg: ModalComponent;

  errorMessage: string;
  gameBoard: GameBoard[];
  name: {};
  mode = 'Observable';

  //we need a gameboard (maybe not)

  //we need an array of players
  player:Player;
  players:Player[] = [];

  p1cards:Card[] = [];
  p2cards:Card[] = [];
  droppedItems = [];

  //This tells us where the card images can be found
  cardBluePath = "/assets/deck/Blue/";
  cardRedPath = "/assets/deck/Red/";

  //The boardService will handle our API calls
  boardService;

  //Initialize the API service
  constructor(boardService:BoardService) {
    this.boardService = boardService;
  }


  //On load...
  ngOnInit()
  {
    //Create the game
    this.boardService.createGame()
        .subscribe(
         error =>  this.errorMessage = <any>error);

   //Create the players
   this.createPlayer(0);
   this.createPlayer(1);
 }


  createPlayer(player: number)
  {
    var playerName;
    if (player == 0) {playerName = "Player1"} else {playerName = "Player2"};

    //We'll make a call to the API to build the hand of cards
    this.boardService.buildHand(player)
        .subscribe(
         cardList =>
         {
           var cardData = [];
           cardData = JSON.parse(cardList.toString());

           var i, itemLength, card
           itemLength = cardData.length;
           for(i=0;i<itemLength;i++)
           {
             let card = new Card();
             Object.assign(card,
             {
               "cardNum":i,
               "id": cardData[i].id,
               "displayName": cardData[i].displayName,
               "fileName": cardData[i].fileName,
               "left": cardData[i].left,
               "top": cardData[i].top,
               "right": cardData[i].right,
               "bottom": cardData[i].bottom,
               "level": cardData[i].level,
               "native": cardData[i].native
             });

             if (player == 0) {this.p1cards.push(card)} else {this.p2cards.push(card)};
             ////this.cards.push(card);
           }

           //Now we will create the player and feed it the hand
           this.player = new Player(playerName);
           if (player ==0) {this.player.cardHand = this.p1cards} else {this.player.cardHand = this.p2cards};
           this.players.push(this.player);
         }
       );
  }


  //When a card is dropped...
  onItemDrop(e: any, slot: any)
  {
      e.dragData.slot = slot;

      //Update the object
      this.boardService.playCard(slot, e.dragData.card)
          .subscribe(result => {
            //If the slot is open and the card is played, physically move the item
            if (result == "true" )
            {
              this.droppedItems.push(e.dragData);
              this.removeItem(e.dragData, this.p1cards);
            }
            else{
              window.alert("Slot already occupied.");
              //this.modalWindow.show()
              //this.errorMsg.showErrorMessage("Slot already occupied.");
              //this.errorMsg.show();
            }
          });
  }


  //Remove the card from the hand
  removeItem(item: any, list: Array<any>)
  {
      let index = list.map((e) => {
          return e.cardNum
      }).indexOf(item.cardNum);
      list.splice(index, 1);
  }
}

The createPlayer function is really where the question begins. createPlayer函数确实是问题的起点。 Currently, it will make the API call and parse the JSON back into an array of cards. 当前,它将进行API调用并将JSON解析回卡数组中。 Right now, the array of cards lives locally in the AppComponent (as p1cards or p2cards). 现在,卡阵列在本地驻留在AppComponent中(如p1cards或p2cards)。

What I want to do instead is create a player objects (component) for each player, assign their respective hand of cards, and then put those players in an array. 我要做的是为每个玩家创建一个玩家对象(组件),分配他们各自的手牌,然后将这些玩家放在一个数组中。 I had that part working (pieces of the code still exist above, but not all of it), but I hit a wall in my *ngFor to display the cards. 我的那部分工作正常(上面的代码仍然存在,但不是全部),但是我在* ngFor上碰了壁以显示卡片。 In pseudocode, I understood what I needed to do, but in practice I couldn't figure it out. 在伪代码中,我理解了我需要做的事情,但是实际上我无法弄清楚。

I knew that div class player1Cards needed to be something like "let player of Players where name = player1", and then I needed to iterate over the player.cardHand[] array to display each of the cards. 我知道div类player1Cards需要类似于“让玩家成为name = player1的玩家”,然后我需要遍历player.cardHand []数组以显示每张卡。 I tried quite a few things, but nothing worked. 我尝试了很多事情,但没有任何效果。

So then, after a few hours of Google searching, I came to the conclusion that I needed a child view for the player to handle it. 因此,经过Google几个小时的搜索后,我得出的结论是,需要播放器使用子视图才能对其进行处理。 I currently have the following for that: 我目前有以下几点:

My player.html is: 我的player.html是:

<div draggable *ngFor="let card of cardHand" [dragData]="card" class="list-group-item">
  <img src="{{cardBluePath + card.fileName}}">
</div>

And my player.ts is: 我的player.ts是:

import { Component, Input, OnInit } from '@angular/core';
import { Card } from './card';


@Component({
    selector: 'player',
    templateUrl: './player.html',
})

export class Player implements OnInit
{
  public cardHand: Card[];
  cardBluePath = "/assets/deck/Blue/";

  constructor
  (
    public name: string
  )
  {}

  ngOnInit()
  {

  }
}

Then in my AppComponent template, I added the block (and Imported the player.ts) 然后,在我的AppComponent模板中,添加了代码块(并导入了player.ts)

I get an error message on App.Component "inline template:69:16 caused by: No provider for String!". 我在App.Component上收到一条错误消息“内联模板:69:16,其原因是:没有字符串提供者!”。 Of all the Google research I performed and all of the changes I tried (ViewChild, Input/Output, Reference), I could not get it to work. 在我执行的所有Google研究和尝试的所有更改(ViewChild,输入/输出,参考)中,我都无法使它起作用。 I don't recall exactly what I did, but at one point I was able to eliminate the error, but the card array was not getting passed to the player (I wish I had committed or stashed that code). 我记不清自己做了什么,但是有一次我能够消除错误,但是卡阵列并没有传递给玩家(我希望我已经提交或保存了该代码)。

In my mind, I understand the task at hand, I just can't make it happen. 在我看来,我理解手头的任务,只是无法实现。 I know I need to create the Player object and feed it the respective cardHand in order for the player html to be able to parse it. 我知道我需要创建Player对象并将其各自的cardHand喂给它,以便Player html能够解析它。 I can do that fine in AppComponent, but once I try to do it as a parent/child, I get stuck. 我可以在AppComponent中做到这一点,但是一旦我尝试作为父母/孩子来做,就会陷入困境。

Can someone help get me going in the right direction? 有人可以帮助我朝正确的方向前进吗?

in your player component, if you want to access another component: 1. that component needs a import statement on top 2. within the @component section, you need to include it in Providers 3. also include it in the constructor 在播放器组件中,如果要访问另一个组件:1.该组件顶部需要导入语句2.在@component部分中,您需要将其包括在提供者中3.还要将其包括在构造函数中

For more information, visit here: https://angular.io/guide/dependency-injection 有关更多信息,请访问此处: https : //angular.io/guide/dependency-injection

I know I need to create the Player object and feed it the respective cardHand in order for the player html to be able to parse it. 我知道我需要创建Player对象并将其各自的cardHand喂给它,以便Player html能够解析它。 I can do that fine in AppComponent, but once I try to do it as a parent/child, I get stuck. 我可以在AppComponent中做到这一点,但是一旦我尝试作为父母/孩子来做,就会陷入困境。

I agree that it makes sense to create an array of player objects, each with an array of cards in their hand. 我同意创建一系列玩家对象是有意义的,每个玩家手中都拥有一副纸牌。 Something like this: 像这样:

let player1 = {name:'Player 1',hand:[]} 
let player2 = {name:'Player 2',hand:[]}
this.players = [player1, player2]

player1.hand.push(this.dealCard())
...

player2.hand.push(this.dealCard())
...

You can then create a player component to show the players (and even a card component to show their hand). 然后,您可以创建一个播放器组件来显示玩家(甚至是纸牌组件来显示他们的手)。 In your root template you'll loop through the players, creating your player component and passing in the player data, including their hands. 在您的根模板中,您将遍历播放器,创建播放器组件并传入播放器数据(包括其手)。

<player-component *ngFor="let player of players" [player]="player"></player-component>

Make sure your player component has an input to receive the player data: 确保您的播放器组件具有输入以接收播放器数据:

export class PlayerComponent implements OnInit {
 @Input() player: Player;
  constructor() { }

  ngOnInit() { }
}

Then in the <player-component> template loop through the player's hand and render the cards: 然后在<player-component>模板中循环遍历玩家的手并渲染纸牌:

<p>I am {{player.name}}. My hand is:</p>
<ul>
  <li *ngFor="let card of player.hand">{{card}}</li>
</ul>

Here is a plunker showing a working demo that's a simplified version of this setup: https://plnkr.co/edit/5Hz8P7poCb9Ju5IR6MWs?p=preview You should be able to configure it to the specific setup of your game. 这是一个显示该安装程序简化版本的工作演示的插件: https ://plnkr.co/edit/5Hz8P7poCb9Ju5IR6MWs?p=preview您应该能够将其配置为您游戏的特定设置。 Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM