角度生产错误:类型“对象”上不存在属性

时间:2019-02-18 20:56:44

标签: node.js angular http express get

我有一个Angular 7应用,该应用正在从两个单独的端点中检索数据:

  1. http://localhost:1337/sms
  2. http://localhost:1337/total

我可以成功地向开发中的这些端点发出GET请求。但是,运行ng build --prod时出现以下错误:

ERROR in src/app/app.component.html(20,29): : Property 'total' does not exist on type 'object'.

作为一项测试,我暂时从app.component.html中删除了{{ total.total }},再次运行了ng build --prod并成功了。

这是向两个单独的端点发出GET请求的正确方法吗?或者我在Node服务器文件中做错了其他事情吗?

app.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

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

export class AppComponent implements OnInit {
  signees: object;
  total: object;

  constructor(private http: HttpClient){}

  ngOnInit(): void {
    this.http.get('http://localhost:1337/sms').subscribe(
      data => {
      this.signees = data;
      }
    );

    this.http.get('http://localhost:1337/total').subscribe(
      data => {
      this.total = data;
      }
    );

  }
}

相关的 app.component.html 代码

<section class="page-section mx-auto">
    <h3 class="text-center">{{ total.total }} people have signed the petition</h3>
    <div class="container">
      <div class="row">

      <div class="col-sm-6 col-lg-3"
      *ngFor="let signee of signees; index as i">
        <div class="card">
          <div class="card-body">
            <p class="h2">{{ signee.name }}</p>
            <ul class="signee-meta text-muted">
              <li>#{{ i + 1 }}</li>
              <li>{{ signee.date }}</li>
            </ul>
          </div>
        </div>
      </div>

    </div><!-- row -->
    </div><!-- container -->

  </section>

/total 端点(MongoDB)

app.get('/total', (req, res) => {
    collection.countDocuments({}, function(err, num) {
      assert.equal(null, err);
      res.send({total: num});
    });
  });

编辑(添加的数据结构)

数据结构(MongoDB)

{ 
  "_id" : ObjectId("5c61e0b658261f10280b5b17"), 
  "name" : "Bill Kickok", 
  "number" : "+14950395584", 
  "date" : "2/11/19" 
}

3 个答案:

答案 0 :(得分:1)

运行ng build --prod时会引发此错误,因为这种构建过程在幕后可用于Ahead of Time编译。

这是基于angular documentation的AOT上发生的事情。

  

更早地检测模板错误

     

AOT编译器在以下过程中检测并报告模板绑定错误   用户看到它们之前的构建步骤。

之所以会出现此错误,是因为在将total声明为object时,您尝试渲染总对象的属性。

为了摆脱此错误,您应该为此变量创建一个interface。例如

export interface Total {
   total: number
   // any other properties total might include
}

然后使用此接口在组件中像这样定义类型:

total: Total

如果您不想创建一个界面-这是一个不好的习惯,则可以将总计定义为anytotal: any)。

最后,直接在组件中发出http请求也是一种坏习惯。您应该创建一个服务,然后添加负责与后端通信的methods,然后将该服务注入组件并调用该方法。

我建议您进一步研究angular documentation

答案 1 :(得分:0)

如果可能的话,强烈键入这些属性是个好主意,因此,代替:

  signees: object;
  total: object;

如果是这样:

  signees: Signee[];
  total: Total;

其中SigneeTotal是接口:

export interface Signee {
  id: number;
  name: string;
  date: string;
  // ...
}

export interface Total{
  id: number;
  total: number;
  // ...
}

注意:上面的内容与data中返回的JSON结构相匹配(这就是为什么有人问您data的结构是什么样的原因。

如果总数只是您收到的一个数字,那么它将是:

total: number;

您只需绑定到total,而不是total.total

然后在发送请求时可以使用这种强类型输入,以确保响应的格式正确:

this.http.get<Signee[]>('http://localhost:1337/sms').subscribe(
  data => {
  this.signees = data;
  }
);

请注意上面代码中指定的通用参数。

答案 2 :(得分:0)

您需要在构造函数内部启动对象。

例如:

  constructor(private http: HttpClient){
    total = new Total();
}

总计是您的课程。这是在angular.io中推荐的。在构造函数中启动VAR。