fix(bindable): parent referenced expression-values now load properly using an update call (#8670)

closes #8666 
closes #6981 
closes #5054
This commit is contained in:
DimitrisRK
2020-06-30 08:28:04 +03:00
committed by GitHub
parent ec17727e91
commit 6b0028afd7
4 changed files with 78 additions and 9 deletions

View File

@ -22,6 +22,7 @@ export function loadExamples() {
examples.set("width-percent", "list-view/width-percent-page");
examples.set("item-re-layout", "list-view/item-re-layout-page");
examples.set("safe-area", "list-view/safe-area-page");
examples.set("parents-expression", "list-view/parents-expression-page");
return examples;
}

View File

@ -0,0 +1,27 @@
import { fromObject } from "tns-core-modules/data/observable";
export function onLoaded(args)
{
const page = args.object;
page.bindingContext = fromObject(
{
prefix: "This is a prefix for: ",
languageData: [
{
name: "English",
},
{
name: "Portuguese"
},
{
name: "Spanish"
},
{
name: "Russian"
},
{
name: "Greek"
}
]
});
}

View File

@ -0,0 +1,20 @@
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="onLoaded" class="page">
<Page.actionBar>
<ActionBar title="My App" icon="" class="action-bar">
</ActionBar>
</Page.actionBar>
<ListView items="{{ languageData }}" separatorColor="red">
<ListView.itemTemplate>
<StackLayout columns="*,40" rows="*,*">
<!-- It works if not an expression -->
<Label row="1" text="{{ $parents['Page'].prefix }}"
class="font-weight-bold" fontSize="16" />
<!-- Until component gets loaded, $parents['Page'].prefix will return undefined -->
<Label row="1" text="{{ $parents['Page'].prefix + name }}"
class="font-weight-bold" fontSize="16" />
</StackLayout>
</ListView.itemTemplate>
</ListView>
</Page>

View File

@ -469,30 +469,51 @@ export class Binding {
let parentViewAndIndex: { view: ViewBase, index: number };
let parentView;
let addedProps = newProps || [];
if (expression.indexOf(bc.bindingValueKey) > -1) {
let expressionCP = expression;
if (expressionCP.indexOf(bc.bindingValueKey) > -1) {
model[bc.bindingValueKey] = model;
addedProps.push(bc.bindingValueKey);
}
if (expression.indexOf(bc.parentValueKey) > -1) {
parentView = this.getParentView(this.target.get(), bc.parentValueKey).view;
if (parentView) {
model[bc.parentValueKey] = parentView.bindingContext;
addedProps.push(bc.parentValueKey);
}
}
let success: boolean = true;
let parentsArray = expression.match(parentsRegex);
let parentsArray = expressionCP.match(parentsRegex);
if (parentsArray) {
for (let i = 0; i < parentsArray.length; i++) {
// This prevents later checks to mistake $parents[] for $parent
expressionCP = expressionCP.replace(parentsArray[i], "");
parentViewAndIndex = this.getParentView(this.target.get(), parentsArray[i]);
if (parentViewAndIndex.view) {
model[bc.parentsValueKey] = model[bc.parentsValueKey] || {};
model[bc.parentsValueKey][parentViewAndIndex.index] = parentViewAndIndex.view.bindingContext;
addedProps.push(bc.parentsValueKey);
}
else
{
success = false;
}
}
}
if (expressionCP.indexOf(bc.parentValueKey) > -1) {
parentView = this.getParentView(this.target.get(), bc.parentValueKey).view;
if (parentView) {
model[bc.parentValueKey] = parentView.bindingContext;
addedProps.push(bc.parentValueKey);
}
else
{
success = false;
}
}
// For expressions, there are also cases when binding must be updated after component is loaded (e.g. ListView)
if (!success)
{
let targetInstance = this.target.get();
targetInstance.off("loaded", this.loadedHandlerVisualTreeBinding, this);
targetInstance.on("loaded", this.loadedHandlerVisualTreeBinding, this);
}
}
private getSourcePropertyValue() {