Angular中跨模型计算数值相乘提示属性未定义如何解决
Angular 购票金额自动计算功能实现方案
核心问题说明
你遇到的属性未定义报错主要来自以下几个原因:
getTicket是异步请求,数据返回前currentTicket的属性未完成初始化,直接参与运算会抛出undefined错误- 模板中同时使用
[(ngModel)]双向绑定和value属性,二者逻辑冲突导致值更新异常 - 数量变更事件未正确绑定计算逻辑,且计算方法未做非空兼容
- 保存用户购票记录时错误调用了
ticketService的创建接口,应该调用userticketService
具体修复步骤
1. 修改组件类代码
你需要补充计算方法、异步请求后的初始值计算、修复保存接口调用:
import { Component, OnInit } from '@angular/core'; import { EventService } from 'src/app/services/event.service'; import { Event } from 'src/app/models/event.model'; import {TicketService} from 'src/app/services/ticket.service'; import {Ticket} from "../../models/ticket.model"; import {Userticket} from "../../models/userticket.model"; import {UserticketService} from "../../services/userticket.service"; import {ActivatedRoute, Router} from "@angular/router"; @Component({ selector: 'app-userticket-buy', templateUrl: './userticket-buy.component.html', styleUrls: ['./userticket-buy.component.css'] }) export class UserticketBuyComponent implements OnInit { // 初始化简化,后续异步请求会覆盖赋值 currentTicket: Ticket = { price: 0, eventid: null }; events?: Event[]; submitted = false; currentUserTicket: Userticket = { qty: 1, paid: 0, ticketid: null }; message = '' constructor( private eventService: EventService, private ticketService:TicketService, private userticketService:UserticketService, private route: ActivatedRoute, private router: Router) { } ngOnInit(): void { this.message = ''; this.getTicket(this.route.snapshot.params.id); this.retrieveEvents(); } // 新增计算方法,添加非空兼容避免undefined报错 calculatePrice(): void { const price = this.currentTicket?.price ?? 0; const qty = this.currentUserTicket?.qty ?? 0; this.currentUserTicket.paid = price * qty; } getTicket(id: string): void { this.ticketService.get(id) .subscribe( data => { this.currentTicket = data; // 拿到票价后先计算初始应付金额 this.calculatePrice(); // 直接给用户购票记录赋值票ID,不需要在模板写隐藏输入框 this.currentUserTicket.ticketid = data.id; console.log(data); }, error => { console.log(error); }); } saveOrder(): void { const data = { qty: this.currentUserTicket.qty, paid: this.currentUserTicket.paid, ticketid: this.currentUserTicket.ticketid }; // 修复接口调用,保存用户购票记录应该用userticketService this.userticketService.create(data) .subscribe( response => { console.log("city") console.log(response); this.submitted = true; }, error => { console.log(error); }); } retrieveEvents(): void { this.eventService.getAll() .subscribe( data => { this.events = data; console.log(data); }, error => { console.log(error); }); } }
2. 修改模板代码
移除冲突的value属性,绑定数量变更事件,删除冗余的隐藏输入框:
<div> <div *ngIf="currentTicket.id" class="edit-form"> <h4>Билет</h4> <form> <div class="form-group"> <label for="qty">Количество</label> <input type="number" class="form-control" id="qty" [(ngModel)]="currentUserTicket.qty" name="qty" (input)="calculatePrice()" min="1" /> <!-- 删除冗余的隐藏ticketid输入框,改为组件内赋值 --> </div> <div class="form-group"> <label for="paid">Сумма к оплате</label> <input type="number" class="form-control" id="paid" [(ngModel)]="currentUserTicket.paid" name="paid" readonly /> </div> <div class="form-group"> <p>Событие: {{currentTicket.eventid?.name}}</p> <p>Зал: {{currentTicket.eventid?.hallid?.name}}</p> <p>Город: {{currentTicket.eventid?.cityid?.name}}</p> </div> </form> <button type="submit" class="badge badge-success mb-2" (click)="saveOrder()" > Подтвердить </button> <p>{{ message }}</p> </div> <div *ngIf="!currentTicket.id"> <br /> <p>Нет доступа...</p> </div> </div>
补充优化点
- 给数量输入框加了
min="1"属性,避免用户输入小于1的购票数量 - 应付金额输入框加了
readonly属性,防止用户手动修改金额 - 计算方法添加了空值合并运算符
??做兜底,即使属性未赋值也不会抛出undefined错误
内容的提问来源于stack exchange,提问作者Bogdan Onyshenko
相关产品推荐
相关产品推荐

