typescript 在此Angular应用的模板中使用join方法时,是什么原因导致失败?

lzfw57am  于 2023-06-07  发布在  TypeScript
关注(0)|答案(2)|浏览(213)

我用Angular 15开发了一个应用程序。
我使用手工编码的JSON和JSON server来显示“雇员”列表。

{"employees": [
    {
      "empno": "2",
      "deptno": "10",
      "firstname": "Sandy",
      "lastname": "Paton",
      "gender": "femele",
      "avatar": "sandy.png",
      "job": "Manager",
      "bio": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsam obcaecati veritatis maiore.",
      "skills": "['Management']"
    },
    {
      "empno": "8",
      "deptno": "30",
      "firstname": "Susette",
      "lastname": "Lumbard",
      "gender": "femele",
      "avatar": "femele.png",
      "job": "Programmer",
      "bio": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsam obcaecati veritatis maiore.",
      "skills": "['JAVA', 'MySQL']"
    },
    {
      "empno": "10",
      "deptno": "10",
      "firstname": "Sue",
      "lastname": "Jary",
      "gender": "femele",
      "avatar": "femele.png",
      "job": "HR Manager",
      "bio": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsam obcaecati veritatis maiore.",
      "skills": "['Recruitment']"
    }
]}

employee-details.component.ts中,我有:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Employee } from '../../models/empModel';
import { EmployeeService } from 'src/app/services/employee.service';

@Component({
  selector: 'app-employee-details',
  templateUrl: './employee-details.component.html',
  styleUrls: ['./employee-details.component.scss'],
})
export class EmployeeDetailsComponent implements OnInit {
  constructor(private ActivatedRoute: ActivatedRoute, private employeeService: EmployeeService) {}

  public empsArray: Employee[] = [];
  public employee: any = {};

  public getEmployee() {
    const empno = Number(this.ActivatedRoute.snapshot.paramMap.get('empno'));

    this.employeeService.getEmployees().subscribe((response) => {
      this.empsArray = response;

      this.employee = this.empsArray.find((item) => item.empno == empno);
    });
  }

  ngOnInit() {
    this.getEmployee();
  }
}

employee-details.component.html中,我有:

<div class="row">
    <div class="col-sm-4 col-md-3">
      <div class="poster-container text-center text-sm-start mb-3 mt-1">
        <img
          src="assets/images/{{ employee.avatar }}"
          [alt]="employee.firstname"
          class="img-fluid rounded shadow-sm"
        />
      </div>
    </div>
  
    <div class="col-sm-8 col-md-9">
      <h2>{{ employee.firstname }} {{ employee.lastname }}</h2>
  
      <p>{{ employee.bio }}</p>
  
      <div *ngIf="employee.skills.length">
        <h3>Skills</h3>
        <p>
          {{ employee.gender == 'male' ? 'His' : 'Her' }} main skills are:
          {{ employee.skills.join(', ') }}
        </p>
      </div>
    </div>
</div>

问题
每当我访问员工的详细信息时,我都会在Chrome控制台中看到以下错误:
无法读取未定义的属性(阅读“长度”)
即使{{ employee.skills }} * 确实 * 打印了技能数组,也会发生这种情况。

常见问题

1.我做错了什么?
1.解决此问题最可靠的方法是什么?

ryevplcw

ryevplcw1#

你应该删除你的.json中的引号,否则skills不是数组,请参阅diference

"employees": [
    {
      ...
      "skills": "['Management']" //<--is a string
    },
}

然后呢

"employees": [
    {
      ...
      "skills": ['Management']  //<--is an array of strings
    },
]

如果你真的得到了字符串,你应该转换(你可以使用regexpr)
为你效劳

getData()
{
    return this.httpClient.get(...).pipe(
       map((employees:any[])=>{
         employees.forEach(x=>{
           x.skills=x.skills.match(/\'([^,])*\'/g)?
                     .map(x=>x.slice(0,-1).slice(1))
         })
         return employees
       })
    )
}

getEmploye(employedId)
{
      this.httpClient.get(...).pipe(
         map((employee:any)=>{
             employee.skills=employee.skills.match(/\'([^,])*\'/g)?
                         .map(x=>x.slice(0,-1).slice(1))
             return employee
         })
      )
}

更新我不知道,因为我在严格模式下上面的代码有问题,我用map替换forEach,函数变成这样

getData() {
    const obs = of(employesData);
    return obs.pipe(
      map((employees: any[]) => {
        const regex = /\'([^,])*\'/g;
        return employees.map((employe: any) => {
          const skills = (employe.skills as string)
            .match(regex)
            ?.map((x: string) => x.slice(0, -1).slice(1));
          return { ...employe, skills: skills };
        });
      })
    );
  }
  getDataEmployed(empno: string) {
    const obs = of(employesData.find((x: any) => x.empno == empno));
    const regex = /\'([^,])*\'/g;
    return obs.pipe(
      map((employe: any) => {
        const skills = (employe.skills as string)
          .match(regex)
          ?.map((x: string) => x.slice(0, -1).slice(1));
        return { ...employe, skills: skills };
      })
    );
  }

stackblitz
注意:我不是一个好的regExpr编码员,肯定有人可以创建一个更好的表达式

pgky5nke

pgky5nke2#

奇怪的是,您将“skills”作为字符串接收,尽管它看起来是一个数组。但是当这个属性不存在,或者是null时,就会发生错误。如果你改变'if'语句,它很容易修复:

<div *ngIf="employee.skills?.length">

使用这个问号,基本上就是告诉Typescript变量/属性是可选的,并预先检查它是否真的存在。
更新:因为join()是一个数组函数。在弦上不起作用。首先,您需要接收一个数组,或者将获得的字符串转换为数组以迭代它。正确的方法是询问您在哪里接收数据,以正确的方式更改它并格式化它。
因为我知道有时这是不可能的,我会添加一个函数(在ts中)来解析技能。

function strToArr(str: string) {
    const validJSONString = string.replace(/'/g, '"');
    return JSON.parse(validJSONString);
}

并更新模板

{{ strToArr(employee.skills).join(', ') }}

相关问题