(collection: Iterable<unknown> | undefined | null)
| 502 | * @codeGenApi |
| 503 | */ |
| 504 | export function ɵɵrepeater(collection: Iterable<unknown> | undefined | null): void { |
| 505 | const prevConsumer = setActiveConsumer(null); |
| 506 | const metadataSlotIdx = getSelectedIndex(); |
| 507 | try { |
| 508 | const hostLView = getLView(); |
| 509 | const hostTView = hostLView[TVIEW]; |
| 510 | const metadata = hostLView[metadataSlotIdx] as RepeaterMetadata; |
| 511 | const containerIndex = metadataSlotIdx + 1; |
| 512 | const lContainer = getLContainer(hostLView, containerIndex); |
| 513 | |
| 514 | if (metadata.liveCollection === undefined) { |
| 515 | const itemTemplateTNode = getExistingTNode(hostTView, containerIndex); |
| 516 | metadata.liveCollection = new LiveCollectionLContainerImpl( |
| 517 | lContainer, |
| 518 | hostLView, |
| 519 | itemTemplateTNode, |
| 520 | ); |
| 521 | } else { |
| 522 | metadata.liveCollection.reset(); |
| 523 | } |
| 524 | |
| 525 | const liveCollection = metadata.liveCollection; |
| 526 | reconcile(liveCollection, collection, metadata.trackByFn, prevConsumer); |
| 527 | |
| 528 | // Warn developers about situations where the entire collection was re-created as part of the |
| 529 | // reconciliation pass. Note that this warning might be "overreacting" and report cases where |
| 530 | // the collection re-creation is the intended behavior. Still, the assumption is that most of |
| 531 | // the time it is undesired. |
| 532 | if ( |
| 533 | ngDevMode && |
| 534 | metadata.trackByFn === ɵɵrepeaterTrackByIdentity && |
| 535 | liveCollection.operationsCounter?.wasReCreated(liveCollection.length) && |
| 536 | isViewExpensiveToRecreate(getExistingLViewFromLContainer(lContainer, 0)) |
| 537 | ) { |
| 538 | const message = formatRuntimeError( |
| 539 | RuntimeErrorCode.LOOP_TRACK_RECREATE, |
| 540 | `The configured tracking expression (track by identity) caused re-creation of the entire collection of size ${liveCollection.length}. ` + |
| 541 | 'This is an expensive operation requiring destruction and subsequent creation of DOM nodes, directives, components etc. ' + |
| 542 | 'Please review the "track expression" and make sure that it uniquely identifies items in a collection.', |
| 543 | ); |
| 544 | console.warn(message); |
| 545 | } |
| 546 | |
| 547 | // moves in the container might caused context's index to get out of order, re-adjust if needed |
| 548 | liveCollection.updateIndexes(); |
| 549 | |
| 550 | // handle empty blocks |
| 551 | if (metadata.hasEmptyBlock) { |
| 552 | const bindingIndex = nextBindingIndex(); |
| 553 | const isCollectionEmpty = liveCollection.length === 0; |
| 554 | if (bindingUpdated(hostLView, bindingIndex, isCollectionEmpty)) { |
| 555 | const emptyTemplateIndex = metadataSlotIdx + 2; |
| 556 | const lContainerForEmpty = getLContainer(hostLView, emptyTemplateIndex); |
| 557 | if (isCollectionEmpty) { |
| 558 | const emptyTemplateTNode = getExistingTNode(hostTView, emptyTemplateIndex); |
| 559 | const dehydratedView = findAndReconcileMatchingDehydratedViews( |
| 560 | lContainerForEmpty, |
| 561 | emptyTemplateTNode, |
nothing calls this directly
no test coverage detected