【问题标题】:Identifier not defined未定义标识符
【发布时间】:2020-04-09 13:55:44
【问题描述】:

我是 Angular 9 的初学者,我正在尝试创建一个应用程序。但是我有一些关于属性定义的小问题。我希望有人会好心地帮助我。 首先,我的项目是这样的:

我的 app.component.html 被定向到我的管理器文件夹:

<button mat-raised-button id="Upgrade (click)="modal='Managers'">Managers</button>
<app-manager *ngIf="modal=='Managers'" (closemodalevent)="modal=null" [manager]="world.managers.pallier"></app-manager>

我的 app.component.ts:

import { Component, Input } from '@angular/core';
import { RestserviceService } from './restservice.service';
import { World, Product, Pallier } from './world';
import { MatDialogConfig, MatDialog } from '@angular/material/dialog';
import { ModalComponent } from './modal/modal.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  products = [
    {logo: "./assets/Avatar.jpg" },
    {logo: "./assets/Avatar.jpg" },
    {logo: "./assets/Avatar.jpg" },
    {logo: "./assets/Avatar.jpg" },
    {logo: "./assets/Avatar.jpg" },
    {logo: "./assets/Avatar.jpg" }
  ];
  title = 'AngularProject';
  world: World = new World();
  server: String;
  qtmulti: number = 1;
  modal: string=null;

  constructor(private service: RestserviceService) {
    this.server = service.getServer();
    service.getWorld().then(world => { this.world = world; });
  }
}

我的 manager.component.html:

<div class="Modal" (clickOutside)="closemodal()">
  <div><h1 class="ManagerTitle">Managers make you feel better !</h1></div>
  <div>
    <div *ngFor="let manager of world.managers.pallier">
      <div *ngIf="!manager.unlocked" class="ManagerLayout">
        <div>
          <div class="logo"><img class="LogoImage" [attr.src]="server+manager.logo"></div>
        </div>
        <div>
          <div class="ManagerName">{{manager.name}}</div>
          <div class="ManagerCible">{{world.products.product[manager.idcible-1].name}}</div>
        </div>
        <div class="ManagerCost">{{manager.seuil}}</div>
      </div>
      <button mat-raised-button id="HireButton" (click)="hireManager(manager)"
              [ngClass]="{'selectable': (world.money >= manager.seuil)}"> Hire !</button>
    </div>
  </div>
</div>

我在这里遇到了世界和服务器的错误,即:

未定义标识符“世界”。组件声明、模板变量声明和元素引用不包含这样的成员。

未定义标识符“服务器”。组件声明、模板变量声明和元素引用不包含这样的成员。

但是我已经在 app.component.ts 中定义了服务器和世界...

我提前感谢愿意花时间帮助我的人。

编辑:对不起,我忘了把它放在这里,因为它是一个朋友为我做的.ts

我的 manager.component.ts:

import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core';
import { World, Pallier } from '../world';

@Component({
  selector: 'app-manager',
  templateUrl: './manager.component.html',
  styleUrls: ['./manager.component.css']
})
export class ManagerComponent implements OnInit {
  canclose=false;
  @Input() manager: Pallier[];

  @Output() closemodalevent = new EventEmitter<void>();

  constructor() { }

  ngOnInit(): void {
  }

  hireManager(manager : Pallier){
    alert(manager.name + 'has been hired')
    if (this.world.money >= manager.seuil) {
      this.world.money = this.world.money - manager.seuil;
      this.world.managers.pallier[this.world.managers.pallier.indexOf(manager)].unlocked = true;
      this.world.products.product.forEach(element => {if (manager.idcible == element.id) {this.world.products.product[this.world.products.product.indexOf(element)].managerUnlocked = true;}});
    }
  }

  closemodal(){
    console.log(this.canclose);
    if(this.canclose){
      this.closemodalevent.emit();
    }else{
      this.canclose=true;
    }
  }

我的世界.ts:

export class World {
    name : string; 
    logo : string;
    money: number; 
    score: number; 
    totalangels: number;
    activeangels: number;
    angelbonus: number;
    lastupdate: string; 
    products : { "product": Product[] };
    allunlocks: { "pallier": Pallier[]};
    upgrades: { "pallier": Pallier[]};
    angelupgrades: { "pallier": Pallier[]};
    managers: { "pallier": Pallier[]};

    constructor() {
        this.products = { "product":[ ] } ;
        this.managers = { "pallier":[ ] };
        this.upgrades = { "pallier":[ ] };
        this.angelupgrades = { "pallier":[ ] };
        this.allunlocks = { "pallier":[ ] };
    }
}

【问题讨论】:

  • 你需要展示manager.component.ts的内容。 world 应该在其中声明。
  • 显示 manager.component.ts 文件内容。
  • @AzizulHoq 对不起,他们现在在这里 :)

标签: angular typescript


【解决方案1】:

查看你的 app.component.html,你有这一行

<app-manager *ngIf="modal=='Managers'" (closemodalevent)="modal=null" [manager]="world.managers.pallier"></app-manager>

假设你的 manager.component.ts 期望这个输入,这意味着将传递给组件的值是 world.managers.pallier 中的解析值

查看您的代码,我希望在您的 manager.component.ts 中有类似的内容

  @Input() manager: []CustomType;

这是为了使值匹配 这意味着在你的 manager.component.html 中你应该迭代 manager,就像这样

<div class="Modal" (clickOutside)="closemodal()">
  <div><h1 class="ManagerTitle">Managers make you feel better !</h1></div>
  <div>
    <div *ngFor="let singleManager of manager">
      <div *ngIf="!singleManager.unlocked" class="ManagerLayout">
        <div>
          <div class="logo"><img class="LogoImage" 
           [attr.src]="server+singleManager.logo"></div>
        </div>
        <div>
          <div class="ManagerName">{{singleManager.name}}</div>
          <div class="ManagerCible">{{world.products.product[singleManager.idcible- 
           1].name}}</div>
        </div>
        <div class="ManagerCost">{{singleManager.seuil}}</div>
      </div>
      <button mat-raised-button id="HireButton" (click)="hireManager(singleManager)"
              [ngClass]="{'selectable': (world.money >= singleManager.seuil)}"> Hire !</button>
    </div>
  </div>
</div>

为了在子组件中访问服务器,你还需要在你的 app.component 中传递值

<app-manager *ngIf="modal=='Managers'" (closemodalevent)="modal=null" [manager]="world.managers.pallier" [server]="server"></app-manager>

你的 manager.component.ts 也应该期待这个输入,所以添加这一行 @Input() server: String;

应该有效

另外,请查看Component Communcation documentation 以正确理解此逻辑的工作原理

【讨论】:

  • 感谢您的帮助!所以对于世界,我应该在我的 manager.component.ts 中添加:@Input() world: World 我应该在我的应用程序模式中添加:[world] = "world",对吗?对于这个我不确定,因为 world 是一个文件 .ts...
  • 原则上是对的。但是,如果world 是 .ts 文件中的 json(一种可接受的为开发/测试目的设置数据的方式),只需确保将其导出到变量中以便您可以导入它(例如 import {testData} from './test-data.ts'
  • 好的,我完全理解。非常感谢你们俩的帮助:D
  • 理论上,如果它在外部文件中,它也应该可以工作。然而,这种方法是首选,因为这个值很可能来自数据库,并且可能随时间变化
【解决方案2】:

直接在模板中查看 cmets。

<div class="Modal" (clickOutside)="closemodal()">
  <div><h1 class="ManagerTitle">Managers make you feel better !</h1></div>
  <div>

    <!-- world should be a property of manager.component.ts-->
    <div *ngFor="let manager of world.managers.pallier">

      <div *ngIf="!manager.unlocked" class="ManagerLayout">
        <div>

          <!-- put server inside single quotes -->
          <div class="logo"><img class="LogoImage" [attr.src]="'server'+manager.logo"></div>

        </div>
        <div>
          <div class="ManagerName">{{manager.name}}</div>
          <div class="ManagerCible">{{world.products.product[manager.idcible-1].name}}</div>
        </div>
        <div class="ManagerCost">{{manager.seuil}}</div>
      </div>
      <button mat-raised-button id="HireButton" (click)="hireManager(manager)"
              [ngClass]="{'selectable': (world.money >= manager.seuil)}"> Hire !</button>
    </div>
  </div>
</div>

此外,在模板中使用可选链是一个很好的做法。

代替:

<div class="ManagerCible">
  {{world.products.product[manager.idcible-1].name}}
</div>

用途:

<div class="ManagerCible">
  {{world?.products?.product[manager.idcible-1]?.name}}
</div>

问号将保护您的代码免受null 值的影响(假设worldnull/undefined....您会收到一条错误消息,指出您无法访问productsundefined。问号避免了这个错误)。

【讨论】:

  • 感谢您的帮助,我不知道可选链接的技巧:D。但我有一个问题,灵魂服务器真的是单引号吗?通常它是一个属性没有?
  • 如果你不把它放在单引号里,它会被认为是manager.component.ts中应该存在的属性
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多