Skip to content

Commit 6b0028a

Browse files
authored
fix(bindable): parent referenced expression-values now load properly using an update call (#8670)
closes #8666 closes #6981 closes #5054
1 parent ec17727 commit 6b0028a

File tree

4 files changed

+78
-9
lines changed

4 files changed

+78
-9
lines changed

Diff for: e2e/ui-tests-app/app/list-view/main-page.ts

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export function loadExamples() {
2222
examples.set("width-percent", "list-view/width-percent-page");
2323
examples.set("item-re-layout", "list-view/item-re-layout-page");
2424
examples.set("safe-area", "list-view/safe-area-page");
25+
examples.set("parents-expression", "list-view/parents-expression-page");
2526

2627
return examples;
2728
}
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { fromObject } from "tns-core-modules/data/observable";
2+
3+
export function onLoaded(args)
4+
{
5+
const page = args.object;
6+
page.bindingContext = fromObject(
7+
{
8+
prefix: "This is a prefix for: ",
9+
languageData: [
10+
{
11+
name: "English",
12+
},
13+
{
14+
name: "Portuguese"
15+
},
16+
{
17+
name: "Spanish"
18+
},
19+
{
20+
name: "Russian"
21+
},
22+
{
23+
name: "Greek"
24+
}
25+
]
26+
});
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="onLoaded" class="page">
2+
3+
<Page.actionBar>
4+
<ActionBar title="My App" icon="" class="action-bar">
5+
</ActionBar>
6+
</Page.actionBar>
7+
8+
<ListView items="{{ languageData }}" separatorColor="red">
9+
<ListView.itemTemplate>
10+
<StackLayout columns="*,40" rows="*,*">
11+
<!-- It works if not an expression -->
12+
<Label row="1" text="{{ $parents['Page'].prefix }}"
13+
class="font-weight-bold" fontSize="16" />
14+
<!-- Until component gets loaded, $parents['Page'].prefix will return undefined -->
15+
<Label row="1" text="{{ $parents['Page'].prefix + name }}"
16+
class="font-weight-bold" fontSize="16" />
17+
</StackLayout>
18+
</ListView.itemTemplate>
19+
</ListView>
20+
</Page>

Diff for: nativescript-core/ui/core/bindable/bindable.ts

+30-9
Original file line numberDiff line numberDiff line change
@@ -469,30 +469,51 @@ export class Binding {
469469
let parentViewAndIndex: { view: ViewBase, index: number };
470470
let parentView;
471471
let addedProps = newProps || [];
472-
if (expression.indexOf(bc.bindingValueKey) > -1) {
472+
let expressionCP = expression;
473+
if (expressionCP.indexOf(bc.bindingValueKey) > -1) {
473474
model[bc.bindingValueKey] = model;
474475
addedProps.push(bc.bindingValueKey);
475476
}
476477

477-
if (expression.indexOf(bc.parentValueKey) > -1) {
478-
parentView = this.getParentView(this.target.get(), bc.parentValueKey).view;
479-
if (parentView) {
480-
model[bc.parentValueKey] = parentView.bindingContext;
481-
addedProps.push(bc.parentValueKey);
482-
}
483-
}
478+
let success: boolean = true;
484479

485-
let parentsArray = expression.match(parentsRegex);
480+
let parentsArray = expressionCP.match(parentsRegex);
486481
if (parentsArray) {
487482
for (let i = 0; i < parentsArray.length; i++) {
483+
// This prevents later checks to mistake $parents[] for $parent
484+
expressionCP = expressionCP.replace(parentsArray[i], "");
488485
parentViewAndIndex = this.getParentView(this.target.get(), parentsArray[i]);
489486
if (parentViewAndIndex.view) {
490487
model[bc.parentsValueKey] = model[bc.parentsValueKey] || {};
491488
model[bc.parentsValueKey][parentViewAndIndex.index] = parentViewAndIndex.view.bindingContext;
492489
addedProps.push(bc.parentsValueKey);
493490
}
491+
else
492+
{
493+
success = false;
494+
}
494495
}
495496
}
497+
498+
if (expressionCP.indexOf(bc.parentValueKey) > -1) {
499+
parentView = this.getParentView(this.target.get(), bc.parentValueKey).view;
500+
if (parentView) {
501+
model[bc.parentValueKey] = parentView.bindingContext;
502+
addedProps.push(bc.parentValueKey);
503+
}
504+
else
505+
{
506+
success = false;
507+
}
508+
}
509+
510+
// For expressions, there are also cases when binding must be updated after component is loaded (e.g. ListView)
511+
if (!success)
512+
{
513+
let targetInstance = this.target.get();
514+
targetInstance.off("loaded", this.loadedHandlerVisualTreeBinding, this);
515+
targetInstance.on("loaded", this.loadedHandlerVisualTreeBinding, this);
516+
}
496517
}
497518

498519
private getSourcePropertyValue() {

0 commit comments

Comments
 (0)