@vectoriox/iox-builder 2.6.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -5057,6 +5057,9 @@ class BuilderComponent {
|
|
|
5057
5057
|
if (inGlobal)
|
|
5058
5058
|
this.globalElementsChange.emit([...this.globalElements]);
|
|
5059
5059
|
this.cdr.detectChanges();
|
|
5060
|
+
// If the wrapped node lives in a Repeater template, rebuild its repeated rows so
|
|
5061
|
+
// every clone picks up the new wrapper (and re-resolves the now-nested bindings).
|
|
5062
|
+
this._refreshRepeaterFor(node);
|
|
5060
5063
|
this.panelEventService.emit(PanelEventTypes.LAYOUT_CHANGED, this.layout);
|
|
5061
5064
|
this._selectAfterDrop(wrapped);
|
|
5062
5065
|
}
|
|
@@ -5324,6 +5327,17 @@ class BuilderComponent {
|
|
|
5324
5327
|
}
|
|
5325
5328
|
return null;
|
|
5326
5329
|
}
|
|
5330
|
+
/** If `node` lives inside a Repeater template, tell that repeater to rebuild its preview rows so
|
|
5331
|
+
* a structural change (e.g. wrapping a template child) propagates to every repeated row. No-op
|
|
5332
|
+
* when the node is not inside a repeater. */
|
|
5333
|
+
_refreshRepeaterFor(node) {
|
|
5334
|
+
const repeater = this.findRepeaterAncestorOf(node, this.layout)
|
|
5335
|
+
?? this.findRepeaterAncestorOf(node, this.globalElements);
|
|
5336
|
+
if (!repeater)
|
|
5337
|
+
return;
|
|
5338
|
+
const ref = this.overlayService.getNodeRef(repeater);
|
|
5339
|
+
ref?.componentRef?.instance?.refreshTemplate?.();
|
|
5340
|
+
}
|
|
5327
5341
|
/** Emit ELEMENT_SELECT with the ancestors the panels need (symbol + repeater item scope). */
|
|
5328
5342
|
_emitElementSelect(node, componentRef) {
|
|
5329
5343
|
const symbolAncestor = this.findSymbolAncestorOf(node, this.layout)
|
|
@@ -6071,6 +6085,10 @@ class BuilderRepeaterComponent {
|
|
|
6071
6085
|
this._source = '';
|
|
6072
6086
|
this._sourcePath = '';
|
|
6073
6087
|
this._limit = 10;
|
|
6088
|
+
/** Monotonic fetch token — editing a binding sets `source` and `sourcePath` as two separate inputs,
|
|
6089
|
+
* each firing a fetch; the transient mismatched one (old source + new path, or vice-versa) must not
|
|
6090
|
+
* clobber the correct result if it resolves last. Only the newest fetch's response is applied. */
|
|
6091
|
+
this._fetchSeq = 0;
|
|
6074
6092
|
}
|
|
6075
6093
|
ngOnInit() {
|
|
6076
6094
|
this.bindingSub = this.panelEventService.subscribe(event => {
|
|
@@ -6096,11 +6114,14 @@ class BuilderRepeaterComponent {
|
|
|
6096
6114
|
fetchData() {
|
|
6097
6115
|
if (!this._source)
|
|
6098
6116
|
return;
|
|
6117
|
+
const seq = ++this._fetchSeq;
|
|
6099
6118
|
this.isLoading = true;
|
|
6100
6119
|
this.cdr.markForCheck();
|
|
6101
6120
|
// Resolve BY ALIAS so `derived` sources (e.g. galleryImages = product.gallery) follow their
|
|
6102
6121
|
// parent. `sourcePath` (legacy/back-compat) still repeats over an array property inline.
|
|
6103
6122
|
this.dataSourceService.fetchRepeaterItemsByAlias(this._source, (a) => this.dsRegistry.findByAlias(a), this._sourcePath).subscribe(items => {
|
|
6123
|
+
if (seq !== this._fetchSeq)
|
|
6124
|
+
return; // a newer fetch superseded this one — ignore stale items
|
|
6104
6125
|
this.items = items.slice(0, this._limit);
|
|
6105
6126
|
this.refreshPreviews();
|
|
6106
6127
|
this.isLoading = false;
|
|
@@ -6126,21 +6147,36 @@ class BuilderRepeaterComponent {
|
|
|
6126
6147
|
const item = this.items[0];
|
|
6127
6148
|
if (!item || !this.children.length)
|
|
6128
6149
|
return;
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6150
|
+
this.applyBindingsToNodes(this.children, item);
|
|
6151
|
+
}
|
|
6152
|
+
/** Apply item[0]'s bound values to the live template row, walking the WHOLE subtree — not just
|
|
6153
|
+
* direct children. A bound node can sit any level deep once a template child is wrapped in a
|
|
6154
|
+
* container (or otherwise nested), so recursion is required or the first row shows defaults. */
|
|
6155
|
+
applyBindingsToNodes(nodes, item) {
|
|
6156
|
+
for (const child of nodes) {
|
|
6157
|
+
if (child.bindings?.length) {
|
|
6158
|
+
const ref = this.overlayService.getNodeRef(child);
|
|
6159
|
+
if (ref?.componentRef) {
|
|
6160
|
+
for (const binding of child.bindings) {
|
|
6161
|
+
const value = resolvePath(item, binding.path);
|
|
6162
|
+
if (value !== undefined) {
|
|
6163
|
+
ref.componentRef.instance[binding.prop] = value;
|
|
6164
|
+
}
|
|
6165
|
+
}
|
|
6166
|
+
ref.componentRef.changeDetectorRef.detectChanges();
|
|
6139
6167
|
}
|
|
6140
6168
|
}
|
|
6141
|
-
|
|
6169
|
+
if (child.children?.length) {
|
|
6170
|
+
this.applyBindingsToNodes(child.children, item);
|
|
6171
|
+
}
|
|
6142
6172
|
}
|
|
6143
6173
|
}
|
|
6174
|
+
/** Rebuild preview rows after the template STRUCTURE changed (e.g. a child was wrapped, deleted,
|
|
6175
|
+
* or moved). Deferred so the new DOM + overlay refs exist before bindings are re-applied. */
|
|
6176
|
+
refreshTemplate() {
|
|
6177
|
+
if (this.items.length)
|
|
6178
|
+
setTimeout(() => this.refreshPreviews());
|
|
6179
|
+
}
|
|
6144
6180
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BuilderRepeaterComponent, deps: [{ token: DragEngineService }, { token: OverlayService }, { token: BuilderDataSourceService }, { token: DataSourceRegistryService }, { token: PanelEventService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6145
6181
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", type: BuilderRepeaterComponent, isStandalone: false, selector: "app-builder-repeater", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId", source: "source", sourcePath: "sourcePath", limit: "limit" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, ngImport: i0, template: `
|
|
6146
6182
|
<ng-template #badgeContent>
|