JET Version: v15.1
Hi Community
We are performing an upgrade of a large number of JET applications from 10.x to 15.x.
Previously we were getting away with using <oj-bind-for-each> inside <oj-form-layout> to create a dynamic form region aware that this isn’t technically supported if the content can change:
https://forums.oracle.com/ords/apexds/post/issue-with-form-component-and-oj-bind-for-each-combination-4633
In v10.x we seemed to get away with it as it was working on most of our apps. Now in v.15.x, it fails when the data provider data changes:
knockout-3.5.1.debug.js:2978 Uncaught Error: Cannot find closing comment tag to match: ko _ojBindForEach_:{data:keyInfoDataProvider}
at getVirtualChildren (knockout-3.5.1.debug.js:2978:19)
at Object.childNodes (knockout-3.5.1.debug.js:3018:43)
at Object.emptyNode (knockout-3.5.1.debug.js:3025:58)
at OjForEach.recreateContent (ojknockout.js:3769:26)
at OjForEach.onDataChange (ojknockout.js:3757:14)
at Function.notifySubscribers (knockout-3.5.1.debug.js:1401:38)
at Function.valueHasMutated (knockout-3.5.1.debug.js:1645:34)
at MySearchViewModel.observable [as keyInfoDataProvider] (knockout-3.5.1.debug.js:1609:28)
at fetchProcessInfo (request-search.js:231:22)
at MySearchViewModel.self.handleProcessAction (request-search.js:343:17)
Is there a workaround or supported approach to generate dynamic content within <oj-form>?
Many thanks.
Simplified code:
HTML:
<oj-form-layout id="myform">
<oj-bind-for-each data="[[mySearchDataProvider]]">
<template data-oj-as="attr">
<oj-bind-if test="[[attr.data.dataType == 'TEXT']]">
<oj-label for="[[attr.data.id]]">
<oj-bind-text value="[[attr.data.label]]"></oj-bind-text>
</oj-label>
<oj-input-text :id="[[attr.data.id]]"
label-hint="[[attr.data.label]]">
</oj-input-text>
</oj-bind-if>
<and so on>
</template>
<oj-bind-for-each>
</oj-form-layout>
View Model
// Definition
self.mySearchData = ko.observableArray([
{id: 1, label: "Hello"},
{id: 2, label: "World"}
]);
self.keyInfoDataProvider(new ArrayTreeDataProvider(self.mySearchData, { keyAttributes: 'id' }));
// On button click
self.mySearchData(
{id: 1, label: "Hello"},
{id: 2, label: "Big"},
{id: 3, label: "World"}
);