Skip to content

Commit

Permalink
Merge pull request #2639 from IDEMSInternational/fix/data-items-neste…
Browse files Browse the repository at this point in the history
…d-templates

fix: data items nested templates
  • Loading branch information
esmeetewinkel authored Dec 20, 2024
2 parents 4c184e6 + 462cebe commit 13fdb23
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,6 @@ export class DataItemsService {
// HACK - still want to be able to use localContext from parent rows so copy to child processor
processor.templateRowMap = JSON.parse(JSON.stringify(templateRowMap));
await processor.processContainerTemplateRows();
return processor.renderedRows;
return processor.renderedRows();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export function updateItemMeta(
}

// Apply recursively to ensure item children with nested rows (e.g. display groups) also inherit item context
if (r.rows) {
if (r.rows && r.type !== "data_items" && r.type !== "items") {
r.rows = updateItemMeta(r.rows, itemData, dataListName);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injector } from "@angular/core";
import { Injector, signal } from "@angular/core";
import { FlowTypes } from "src/app/shared/model";
import { getGlobalService } from "src/app/shared/services/global.service";
import { SyncServiceBase } from "src/app/shared/services/syncService.base";
Expand All @@ -9,6 +9,7 @@ import { mergeTemplateRows } from "../../utils/template-utils";
import { TemplateFieldService } from "../template-field.service";
import { TemplateTranslateService } from "../template-translate.service";
import { TemplateVariablesService } from "../template-variables.service";
import { isEqual } from "packages/shared/src/utils/object-utils";

/** Logging Toggle - rewrite default functions to enable or disable inline logs */
let SHOW_DEBUG_LOGS = false;
Expand All @@ -34,7 +35,7 @@ export class TemplateRowService extends SyncServiceBase {
/** List of overrides set by parent templates for access during parent processing */
/** Hashmap of all rows keyed by nested row name (e.g. contentBox1.row1.title) */
public templateRowMap: ITemplateRowMap = {};
public renderedRows: FlowTypes.TemplateRow[]; // rows processed and filtered by condition
public renderedRows = signal<FlowTypes.TemplateRow[]>([], { equal: isEqual }); // rows processed and filtered by condition

constructor(
private injector: Injector,
Expand Down Expand Up @@ -234,7 +235,7 @@ export class TemplateRowService extends SyncServiceBase {
const renderedRows = this.filterConditionalTemplateRows(
JSON.parse(JSON.stringify(processedRows))
);
this.renderedRows = renderedRows;
this.renderedRows.set(renderedRows);
log("[Rows Processed]", logName, { rows, processedRows, renderedRows });
return processedRows;
}
Expand Down
35 changes: 27 additions & 8 deletions src/app/shared/components/template/template-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ export class TemplateComponent implements OnInit, AfterContentInit, ITemplateRow
this._row = row;
if (this.componentRef) {
log("[Component Update]", row.name, row);
this.componentRef.instance.row = row;
this.componentRef.setInput("row", row);
this.hackForceReprocessNestedTemplate();
} else {
log("[Component Create]", row.name, row);
}
Expand Down Expand Up @@ -130,7 +131,7 @@ export class TemplateComponent implements OnInit, AfterContentInit, ITemplateRow
// Depending on row type, either prepare instantiation of a nested template or a display component
switch (row.type) {
case "template":
return this.renderTemplateComponent(TemplateContainerComponent, row);
return this.renderTemplateComponent(row);
default:
const displayComponent = TEMPLATE_COMPONENT_MAPPING[row.type];
if (displayComponent) {
Expand All @@ -145,15 +146,12 @@ export class TemplateComponent implements OnInit, AfterContentInit, ITemplateRow
}

/** Create and render a nested template component */
private renderTemplateComponent(
component: typeof TemplateContainerComponent,
row: FlowTypes.TemplateRow
) {
private renderTemplateComponent(row: FlowTypes.TemplateRow) {
const viewContainerRef = this.tmplComponentHost.viewContainerRef;
const componentRef = viewContainerRef.createComponent(component);
const componentRef = viewContainerRef.createComponent(TemplateContainerComponent);
// assign input variables (note template name taken from the row's value column)
componentRef.instance.parent = this.parent;
componentRef.instance.row = row;
componentRef.setInput("row", row);
componentRef.instance.name = row.name;
// assign templatename input using signal
componentRef.setInput("templatename", row.value);
Expand All @@ -169,4 +167,25 @@ export class TemplateComponent implements OnInit, AfterContentInit, ITemplateRow
componentRef.instance.row = row;
this.componentRef = componentRef;
}

/**
* If the current template is generated as a child of data_items then updates to
* parent variables will not propagate down. Force reprocessing to workaround
* See issue https://github.com/IDEMSInternational/open-app-builder/issues/2636
*/
private async hackForceReprocessNestedTemplate() {
if (this._row.type === "template") {
const componentRef = this.componentRef as ComponentRef<TemplateContainerComponent>;
if (componentRef.instance.parent) {
// HACK - if parent template changes name of nested child template instance fully
// recreate the template container
if ((componentRef.instance.templatename(), this._row.value)) {
this.componentRef.destroy();
this.renderTemplateComponent(this._row);
// TODO - test better ways to manage from container, confirming test cases from
// https://github.com/IDEMSInternational/open-app-builder/issues/2636
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,27 @@
<div>name: {{ name || "(undefined)" }}</div>
</div>
<!-- Template Component-->
<plh-template-component
*ngFor="
let row of templateRowService.renderedRows | filterDisplayComponent;
trackBy: trackByRow
"
class="row"
[row]="row"
[parent]="this"
[attr.data-name]="row.name"
[attr.data-type]="row.type"
data-debug-mode
></plh-template-component>
@for (row of templateRowService.renderedRows() | filterDisplayComponent; track row._nested_name) {
<plh-template-component
class="row"
[row]="row"
[parent]="this"
[attr.data-name]="row.name"
[attr.data-type]="row.type"
data-debug-mode
></plh-template-component>
}
</ng-template>

<!-- Normal Mode -->
<ng-template #noDebugger>
<plh-template-component
*ngFor="
let row of templateRowService.renderedRows | filterDisplayComponent;
trackBy: trackByRow
"
class="row"
[row]="row"
[parent]="this"
[attr.data-name]="row.name"
[attr.data-type]="row.type"
></plh-template-component>
@for (row of templateRowService.renderedRows() | filterDisplayComponent; track row._nested_name) {
<plh-template-component
class="row"
[row]="row"
[parent]="this"
[attr.data-name]="row.name"
[attr.data-type]="row.type"
></plh-template-component>
}
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,12 @@ export class TemplateContainerComponent implements OnInit, OnDestroy {
if (shouldProcess) {
if (full) {
console.log("[Force Reload]", this.name);
// ensure angular destroys previous row components before rendering new
// (note - will cause short content flicker)
this.templateRowService.renderedRows = [];
// allow time for other pending ops to finish
await _wait(50);
await this.renderTemplate(this.templatename());
} else {
await this.templateRowService.processRowUpdates();
console.log("[Force Reprocess]", this.name, this.templateRowService.renderedRows);
console.log("[Force Reprocess]", this.name, this.templateRowService.renderedRows());
for (const child of Object.values(this.children || {})) {
await child.forceRerender(full, shouldProcess);
}
Expand Down Expand Up @@ -203,7 +200,7 @@ export class TemplateContainerComponent implements OnInit, OnDestroy {
log("[Template] Rendered", this.name, {
template,
ctxt: { ...this },
renderedRows: { ...this.templateRowService.renderedRows },
renderedRows: { ...this.templateRowService.renderedRows() },
rowMap: this.templateRowService.templateRowMap,
});
// if a parent exists also provide parent reference to this as a child
Expand Down

0 comments on commit 13fdb23

Please sign in to comment.