diff --git a/apps/tests/ui/bindable-tests.ts b/apps/tests/ui/bindable-tests.ts index c57e5f63b..137fcf057 100644 --- a/apps/tests/ui/bindable-tests.ts +++ b/apps/tests/ui/bindable-tests.ts @@ -13,6 +13,7 @@ import bindingBuilder = require("ui/builder/binding-builder"); import labelModule = require("ui/label"); import textFieldModule = require("ui/text-field"); import fs = require("file-system"); +import appModule = require("application"); // // For information and examples how to use bindings please refer to special [**Data binding**](../../../../bindings.md) topic. @@ -513,5 +514,31 @@ export var test_BindingToSource_FailsAfterBindingContextChange = function () { TKUnit.assertEqual(testLabel.text, expectedValue); } + helper.buildUIAndRunTest(createLabel(), testFunc); +} + +export function test_BindingToDictionaryAtAppLevel() { + var createLabel = function () { + var label = new labelModule.Label(); + return label; + } + var pageViewModel = new observable.Observable(); + var testPropertyName = "testValue"; + var expectedValue = "expectedValue"; + pageViewModel.set("testProperty", testPropertyName); + var dict = {}; + dict[testPropertyName] = expectedValue; + appModule.resources["dict"] = dict; + + var testFunc = function (views: Array) { + var testLabel = (views[0]); + testLabel.bind({ sourceProperty: "testProperty", targetProperty: "text", expression: "dict[testProperty]" }); + + var page = (views[1]); + page.bindingContext = pageViewModel; + + TKUnit.assertEqual(testLabel.text, expectedValue); + } + helper.buildUIAndRunTest(createLabel(), testFunc); } \ No newline at end of file diff --git a/js-libs/polymer-expressions/polymer-expressions.js b/js-libs/polymer-expressions/polymer-expressions.js index 5d9077016..11339d41e 100644 --- a/js-libs/polymer-expressions/polymer-expressions.js +++ b/js-libs/polymer-expressions/polymer-expressions.js @@ -405,7 +405,7 @@ var Path = require("js-libs/polymer-expressions/path-parser").Path; getValue: function (model, isBackConvert, changedModel, observer) { var value = getFn(this.expression)(model.context, observer, changedModel); for (var i = 0; i < this.filters.length; i++) { - value = this.filters[i].transform(model.context, observer, model.resources, isBackConvert, [value]); + value = this.filters[i].transform(model.context, observer, model.context, isBackConvert, [value]); } return value; diff --git a/ui/builder/binding-builder.ts b/ui/builder/binding-builder.ts index 0911c8ba5..258c3c0fa 100644 --- a/ui/builder/binding-builder.ts +++ b/ui/builder/binding-builder.ts @@ -1,4 +1,4 @@ -var expressionSymbolsRegex = /[ \+\-\*%\?:<>=!\|&\(\)\[\]]/; +var expressionSymbolsRegex = /[ \+\-\*%\?:<>=!\|&\(\)\[\]^~]/; export module bindingConstants { export var sourceProperty = "sourceProperty"; diff --git a/ui/core/bindable.ts b/ui/core/bindable.ts index 071b9183d..a5065671a 100644 --- a/ui/core/bindable.ts +++ b/ui/core/bindable.ts @@ -21,7 +21,6 @@ function onBindingContextChanged(data: dependencyObservable.PropertyChangeData) } var contextKey = "context"; -var resourcesKey = "resources"; export class Bindable extends dependencyObservable.DependencyObservable implements definition.Bindable { @@ -203,13 +202,18 @@ export class Binding { return; } if (this.options.twoWay) { - if (this._isExpression(this.options.expression)) { + if (this.options.expression) { var changedModel = {}; - if (this.options.sourceProperty === bindingBuilder.bindingConstants.bindingValueKey) { - changedModel[bindingBuilder.bindingConstants.bindingValueKey] = value; + changedModel[bindingBuilder.bindingConstants.bindingValueKey] = value; + var sourcePropertyName = ""; + if (this.sourceOptions) { + sourcePropertyName = this.sourceOptions.property; } - else { - changedModel[this.options.sourceProperty] = value; + else if (typeof this.options.sourceProperty === "string" && this.options.sourceProperty.indexOf(".") === -1) { + sourcePropertyName = this.options.sourceProperty; + } + if (sourcePropertyName !== "") { + changedModel[sourcePropertyName] = value; } var expressionValue = this._getExpressionValue(this.options.expression, true, changedModel); if (expressionValue instanceof Error) { @@ -225,25 +229,20 @@ export class Binding { } } - private _isExpression(expression: string): boolean { - if (expression) { - var result = expression.indexOf(" ") !== -1; - return result; - } - else { - return false; - } - } - private _getExpressionValue(expression: string, isBackConvert: boolean, changedModel: any): any { try { var exp = polymerExpressions.PolymerExpressions.getExpression(expression); if (exp) { var context = this.source && this.source.get && this.source.get() || global; var model = {}; - model[contextKey] = context; - model[resourcesKey] = appModule.resources; - return exp.getValue(model, isBackConvert, changedModel); + for (var prop in appModule.resources) { + if (appModule.resources.hasOwnProperty(prop) && !context.hasOwnProperty(prop)) { + context[prop] = appModule.resources[prop]; + } + } + + model[contextKey] = context; + return exp.getValue(model, isBackConvert, changedModel); } return new Error(expression + " is not a valid expression."); } @@ -254,7 +253,7 @@ export class Binding { } public onSourcePropertyChanged(data: observable.PropertyChangeData) { - if (this._isExpression(this.options.expression)) { + if (this.options.expression) { var expressionValue = this._getExpressionValue(this.options.expression, false, undefined); if (expressionValue instanceof Error) { trace.write((expressionValue).message, trace.categories.Binding, trace.messageType.error); @@ -268,11 +267,9 @@ export class Binding { } private getSourceProperty() { - if (this._isExpression(this.options.expression)) { + if (this.options.expression) { var changedModel = {}; - if (this.options.sourceProperty === bindingBuilder.bindingConstants.bindingValueKey) { - changedModel[bindingBuilder.bindingConstants.bindingValueKey] = this.source.get(); - } + changedModel[bindingBuilder.bindingConstants.bindingValueKey] = this.source.get(); var expressionValue = this._getExpressionValue(this.options.expression, false, changedModel); if (expressionValue instanceof Error) { trace.write((expressionValue).message, trace.categories.Binding, trace.messageType.error); @@ -339,7 +336,7 @@ export class Binding { return options; } - if (!this._isExpression(property) && types.isString(property) && property.indexOf(".") !== -1) { + if (types.isString(property) && property.indexOf(".") !== -1) { var properties = property.split("."); var i: number;