【问题标题】:Angular - Component data binding not working the 2nd timeAngular - 组件数据绑定第二次不起作用
【发布时间】:2021-05-19 19:17:40
【问题描述】:

我无法修复数据绑定在我的第二个app-orders-list-section 上不起作用的错误。

这是父 app-orders-list 的 .html:

<div class="list-container">
    <label class="list-header" *ngIf="filteredSlotsOrders.length > 0" style="margin-top: 1.625rem;">DELIVERY SLOTS ORDERS</label>
    <div style="height: 50vh; overflow-y: scroll;" *ngIf="filteredSlotsOrders.length > 0">
        <div *ngFor="let date of timelinesWithSlots">
            <app-orders-list-section
                [slotsOrders]="filteredSlotsOrders"
                [timeline]="date"
                [isDeliverySlotsActive]="true"
                [searchTerm]="searchTerm"
            ></app-orders-list-section>
        </div>
    </div>
</div>
<div class="list-container">
    <label class="list-header" *ngIf="filteredNoSlotsOrders.length > 0" style="margin-top: 2.438rem;">ORDERS WITHOUT SLOTS</label>
    <div style="height: 50vh; overflow-y: scroll;" *ngIf="filteredNoSlotsOrders.length > 0">
        <div *ngFor="let date of timelinesWithNoSlots">
            <app-orders-list-section
                [noSlotsOrders]="filteredNoSlotsOrders"
                [timeline]="date"
                [isDeliverySlotsActive]="false"
                [searchTerm]="searchTerm"
            ></app-orders-list-section>
        </div>
    </div>
</div>

这是app-orders-list对应的.ts文件:

@Component({
    selector: 'app-orders-list',
    templateUrl: './orders-list.component.html',
    styleUrls: ['./orders-list.component.css'],
})
export class OrdersListComponent implements OnChanges{
    
    @Input() ordersWithSlots: Order[] = [];
    @Input() ordersWithNoSlots: Order[] = [];
    @Input() timelinesWithSlots: string[] = [];
    @Input() timelinesWithNoSlots: string[] = [];
    @Input() isDeliverySlotsActive: boolean;
    @Input() searchTerm: string;
    filteredSlotsOrders: Order[] = [];
    filteredNoSlotsOrders: Order[] = []

    ngOnChanges(changes: SimpleChanges): void {
        // keep orders updated on changes
        if(changes.ordersWithSlots){
            if(changes.ordersWithSlots.currentValue != changes.ordersWithSlots.previousValue){
                this.filteredSlotsOrders = this.ordersWithSlots;
            }
        }
        if(changes.ordersWithNoSlots){
            if(changes.ordersWithNoSlots.currentValue != changes.ordersWithNoSlots.previousValue){
                this.filteredNoSlotsOrders = this.ordersWithNoSlots;
            }
        }
        ...
        ...
    }
    ...

数据来自智能组件,app-orders-list 的父级。这是数据流开始的地方,它是这样设置的,在ngOnInit()

/* this is executed periodically with timer() */
getInitialPendingTabOrders(){
        this.apiManager.fetchShopOrders(this.currentPendingTabOrdersCount, "status=PENDING&status=FULFILLED").subscribe(orders => {
            const loadedOrders: OrdersList = orders;
            this.nextSetOfPendingTabOrdersUrl = orders.next;
            // slots
            this.loadedSlotsPendingOrders = this.ordersService.filterOrders(loadedOrders["results"], OrderStatus.PENDING, true);
            this.loadedSlotsProcessedOrders = this.ordersService.filterOrders(loadedOrders["results"], OrderStatus.PROCESSED, true);
            this.loadedSlotsPendingOrders.push(...this.loadedSlotsProcessedOrders);
            this.pendingSlotsOrderTimelines = this.ordersService.createTimelines(this.loadedSlotsPendingOrders);
            // no slots
            this.loadedNoSlotsPendingOrders = this.ordersService.filterOrders(loadedOrders["results"], OrderStatus.PENDING, false);
            this.loadedNoSlotsProcessedOrders = this.ordersService.filterOrders(loadedOrders["results"], OrderStatus.PROCESSED, false);
            this.loadedNoSlotsPendingOrders.push(...this.loadedNoSlotsProcessedOrders);
            this.pendingNoSlotsOrderTimelines = this.ordersService.createTimelines(this.loadedNoSlotsPendingOrders);
            this.pendingNoSlotsOrderTimelines.reverse();
        })
}

对于智能组件 .html:

 <app-orders-list
     [ordersWithSlots]="loadedSlotsPendingOrders"
     [ordersWithNoSlots]="loadedNoSlotsPendingOrders"
     [timelinesWithSlots]="pendingSlotsOrderTimelines"
     [timelinesWithNoSlots]="pendingNoSlotsOrderTimelines"
     [isDeliverySlotsActive]="isDeliverySlotsActive"
     [searchTerm]="searchTerm"
></app-orders-list>

对于第一个app-orders-list-section,绑定工作正常。但是,在第二个容器中,app-orders-list-section 中的绑定为空。

这是我的 app-orders-list-section 组件的 .ts:

@Input() timeline: string;
@Input() slotsOrders: Order[] = [];
@Input() noSlotsOrders: Order[] = [];
@Input() isDeliverySlotsActive: boolean;
@Input() searchTerm: string;
sectionOrders: Order[] = [];

constructor(private datePipe: DatePipe) {}

ngOnInit(): void {
    this.createSectionOrders();
    this.sortOrders();
}

ngOnChanges(changes: SimpleChanges): void {
    console.log(this.isDeliverySlotsActive) // prints always true
    if(changes.slotsOrders){
        console.log("hello") // this prints!
        if(changes.slotsOrders.currentValue != changes.slotsOrders.previousValue){
            this.createSectionOrders();
            this.sortOrders();
        }
    }
    if(changes.noSlotsOrders){
        console.log("hello") // this doesn't print!
        if(changes.noSlotsOrders.currentValue != changes.noSlotsOrders.previousValue){
            this.createSectionOrders();
            this.sortOrders();
        }
    }
}
...

为什么会检测到slotsOrders 的更改(我可以打印数据)但没有检测到noSlotsOrders 的更改?即使我尝试打印isDeliverySlotsActive,结果也将始终为真,即使对于第二个容器我希望将此字段设置为false

提前谢谢你。

【问题讨论】:

    标签: angular typescript data-binding


    【解决方案1】:

    我想我对为什么会发生这种情况有一个很好的猜测。仅当 filteredNoSlotsOrders 在您的父组件的内存中分配了一个新位置并且我敢打赌这不会发生时,才会发生更改。为了对 Array 和 Object 类型进行角度变化检测,它们必须在内存中有一个新位置。

    代替:

    const newOrder = {};
    this.filteredNoSlotsOrders.push(newOrder);
    

    做:

    const newOrder = {};
    this.filteredNoSlotsOrders = [...this.filteredNoSlotsOrders, newOrder];
    

    当您从数组中删除数据时,请使用filter。从本质上讲,每次filteredNoSlotsOrders 更改时,都会对其进行不可变更改(将其分配给内存中新位置的新数组)。

    如果你能在每次filteredNoSlotsOrders变化时显示父组件,我可以帮你一成不变地做到。

    【讨论】:

    • 嗨!感谢你的回复。您可能正在做一些事情,因为我确实在数据流开始的智能组件中使用了push()。我同时更新了我的问题!
    • 我想我的问题是,为什么第一个数组filteredSlotsOrders 被检测到而filteredNoSlotsOrders 不是?两种方式的过程不一样吗?
    • 你确定这条线运行吗? this.filteredNoSlotsOrders = this.ordersWithNoSlots;.
    • 是的。我尝试打印,它被调用了 2 次。第一个打印是空的,而第二个打印显示订单。
    • 我可能已经找到了错误的根源。 this.pendingNoSlotsOrderTimelines 在智能组件上打印空,而它应该有数据。该数组包含每个订单分组/部分的时间线。如果订单对应于该部分的时间线,我会检查每个部分。当然,如果订单没有关联的时间线,则不会显示。如果这确实是原因,我会及时通知你。同时,我是否真的需要将每个Input() 数据保存在组件中的一个新的单独字段中,并将这个新字段向下传递?
    猜你喜欢
    • 2014-06-05
    • 2013-01-23
    • 1970-01-01
    • 2017-12-31
    • 2016-10-23
    • 1970-01-01
    • 2018-03-10
    • 1970-01-01
    • 2019-04-09
    相关资源
    最近更新 更多