diff --git a/CrossPlatformModules.csproj b/CrossPlatformModules.csproj index 20dee7b20..f227ba18d 100644 --- a/CrossPlatformModules.csproj +++ b/CrossPlatformModules.csproj @@ -608,6 +608,9 @@ Designer + + Designer + @@ -1564,7 +1567,7 @@ False - + \ No newline at end of file diff --git a/apps/tests/xml-declaration/mymodulewithxml/my-control-no-js.xml b/apps/tests/xml-declaration/mymodulewithxml/my-control-no-js.xml new file mode 100644 index 000000000..c1567a25c --- /dev/null +++ b/apps/tests/xml-declaration/mymodulewithxml/my-control-no-js.xml @@ -0,0 +1,3 @@ + + diff --git a/apps/tests/xml-declaration/xml-declaration-tests.ts b/apps/tests/xml-declaration/xml-declaration-tests.ts index 82d3afc00..cdb9a4f65 100644 --- a/apps/tests/xml-declaration/xml-declaration-tests.ts +++ b/apps/tests/xml-declaration/xml-declaration-tests.ts @@ -17,27 +17,27 @@ import listViewModule = require("ui/list-view"); import helper = require("../ui/helper"); import viewModule = require("ui/core/view"); -export var test_load_IsDefined = function () { +export function test_load_IsDefined() { TKUnit.assert(types.isFunction(builder.load), "ui/builder should have load method!"); }; -export var test_parse_IsDefined = function () { +export function test_parse_IsDefined() { TKUnit.assert(types.isFunction(builder.parse), "ui/builder should have parse method!"); }; -export var test_load_ShouldNotCrashWithInvalidFileName = function () { +export function test_load_ShouldNotCrashWithInvalidFileName() { var v = builder.load(fs.path.join(__dirname, "mainPage1.xml")); TKUnit.assert(types.isUndefined(v), "Expected result: undefined; Actual result: " + v + ";"); }; -export var test_load_ShouldNotCrashWithoutExports = function () { +export function test_load_ShouldNotCrashWithoutExports() { var v = builder.load(fs.path.join(__dirname, "mainPage.xml")); TKUnit.assert(v instanceof view.View, "Expected result: View; Actual result: " + v + ";"); }; -export var test_parse_ShouldNotCrashWithoutExports = function () { +export function test_parse_ShouldNotCrashWithoutExports() { var fileAccess = new fileSystemAccess.FileSystemAccess(); var v: view.View; @@ -48,7 +48,7 @@ export var test_parse_ShouldNotCrashWithoutExports = function () { TKUnit.assert(v instanceof view.View, "Expected result: View; Actual result: " + v + ";"); }; -export var test_parse_ShouldNotCrashWithInvalidXml = function () { +export function test_parse_ShouldNotCrashWithInvalidXml() { var fileAccess = new fileSystemAccess.FileSystemAccess(); var v: view.View; @@ -59,7 +59,7 @@ export var test_parse_ShouldNotCrashWithInvalidXml = function () { TKUnit.assert(types.isUndefined(v), "Expected result: undefined; Actual result: " + v + ";"); }; -export var test_parse_ShouldFindEventHandlersInExports = function () { +export function test_parse_ShouldFindEventHandlersInExports() { var loaded; var page = builder.parse("", { myLoaded: args => { @@ -71,7 +71,7 @@ export var test_parse_ShouldFindEventHandlersInExports = function () { TKUnit.assert(loaded, "Parse should find event handlers in exports."); }; -export var test_parse_ShouldSetGridAttachedProperties = function () { +export function test_parse_ShouldSetGridAttachedProperties() { var p = builder.parse(""); var grid = p.content; var child = grid.getChildAt(0); @@ -89,7 +89,7 @@ export var test_parse_ShouldSetGridAttachedProperties = function () { TKUnit.assert(rowSpan === 3, "Expected result for grid row span: 3; Actual result: " + rowSpan + ";"); }; -export var test_parse_ShouldSetCanvasAttachedProperties = function () { +export function test_parse_ShouldSetCanvasAttachedProperties() { var p = builder.parse(""); var grid = p.content; var child = grid.getChildAt(0); @@ -101,34 +101,34 @@ export var test_parse_ShouldSetCanvasAttachedProperties = function () { TKUnit.assert(top === 2, "Expected result for canvas top: 2; Actual result: " + top + ";"); }; -export var test_parse_ShouldParseNumberProperties = function () { +export function test_parse_ShouldParseNumberProperties() { var p = builder.parse(""); TKUnit.assert(p.width === 100, "Expected result: 100; Actual result: " + p.width + "; type: " + typeof (p.width)); }; -export var test_parse_ShouldParseBooleanProperties = function () { +export function test_parse_ShouldParseBooleanProperties() { var p = builder.parse(""); var sw = p.content; TKUnit.assert(sw.checked === true, "Expected result: true; Actual result: " + sw.checked + "; type: " + typeof (sw.checked)); }; -export var test_parse_ShouldParseBooleanPropertiesIgnoreCase = function () { +export function test_parse_ShouldParseBooleanPropertiesIgnoreCase() { var p = builder.parse(""); var sw = p.content; TKUnit.assert(sw.checked === false, "Expected result: false; Actual result: " + sw.checked + "; type: " + typeof (sw.checked)); }; -export var test_parse_ShouldParseBooleanPropertiesIgnoreCaseInverted = function () { +export function test_parse_ShouldParseBooleanPropertiesIgnoreCaseInverted() { var p = builder.parse(""); var tf = p.content; TKUnit.assert(tf.editable === false, "Expected result: false; Actual result: " + tf.editable + "; type: " + typeof (tf.editable)); }; -export var test_parse_ShouldParseBindings = function () { +export function test_parse_ShouldParseBindings() { var p = builder.parse(""); p.bindingContext = { myProp: true }; var sw = p.content; @@ -136,7 +136,7 @@ export var test_parse_ShouldParseBindings = function () { TKUnit.assert(sw.checked === true, "Expected result: true; Actual result: " + sw.checked + "; type: " + typeof (sw.checked)); }; -export var test_parse_ShouldParseBindingsWithObservable = function () { +export function test_parse_ShouldParseBindingsWithObservable() { var p = builder.parse(""); var obj = new observable.Observable(); obj.set("myProp", true); @@ -150,7 +150,7 @@ export var test_parse_ShouldParseBindingsWithObservable = function () { TKUnit.assert(sw.checked === false, "Expected result: false; Actual result: " + sw.checked + "; type: " + typeof (sw.checked)); }; -export var test_parse_ShouldParseSubProperties = function () { +export function test_parse_ShouldParseSubProperties() { var p = builder.parse(""); var obj = new observable.Observable(); obj.set("myProp", true); @@ -160,14 +160,14 @@ export var test_parse_ShouldParseSubProperties = function () { TKUnit.assert(sw.visibility === "collapsed", "Expected result: collapsed; Actual result: " + sw.visibility + "; type: " + typeof (sw.visibility)); }; -export var test_parse_ShouldParseCustomComponentWithoutXml = function () { +export function test_parse_ShouldParseCustomComponentWithoutXml() { var p = builder.parse(''); var ctrl = p.content; TKUnit.assert(ctrl instanceof myCustomControlWithoutXml.MyControl, "Expected result: custom control is defined!; Actual result: " + ctrl); }; -export var test_parse_ShouldParseCustomComponentWitXml = function () { +export function test_parse_ShouldParseCustomComponentWitXml() { var p = builder.parse(''); var panel = p.content; var lbl = panel.getChildAt(0); @@ -175,11 +175,40 @@ export var test_parse_ShouldParseCustomComponentWitXml = function () { TKUnit.assert(lbl.text === "mymodulewithxml", "Expected result: 'mymodulewithxml'; Actual result: " + lbl); }; -export var test_parse_ShouldParseCustomComponentWitXmlWithAttributes = function () { +export function test_parse_ShouldParseCustomComponentWitXml_WithAttributes() { var p = builder.parse(''); var panel = p.content; - TKUnit.assert(panel.visibility === "collapsed", "Expected result: 'collapsed'; Actual result: " + panel.visibility); + TKUnit.assertEqual(panel.visibility, "collapsed", "panel.visibility"); +}; + +export function test_parse_ShouldParseCustomComponentWitXml_WithCustomAttributes() { + var p = builder.parse(''); + var panel = p.content; + + TKUnit.assertEqual(panel["myProperty"], "myValue", "customControl.myProperty"); +}; + +export function test_parse_ShouldParseCustomComponentWitXmlNoJS() { + var p = builder.parse(''); + var panel = p.content; + var lbl = panel.getChildAt(0); + + TKUnit.assert(lbl.text === "mymodulewithxml", "Expected result: 'mymodulewithxml'; Actual result: " + lbl); +}; + +export function test_parse_ShouldParseCustomComponentWitXmlNoJS_WithAttributes() { + var p = builder.parse(''); + var panel = p.content; + + TKUnit.assertEqual(panel.visibility, "collapsed", "panel.visibility"); +}; + +export function test_parse_ShouldParseCustomComponentWitXmlNoJS_WithCustomAttributes() { + var p = builder.parse(''); + var panel = p.content; + + TKUnit.assertEqual(panel["myProperty"], "myValue", "customControl.myProperty"); }; export function test_parse_ShouldParseCustomComponentWithoutXmlInListViewTemplate() { diff --git a/ui/builder/component-builder.ts b/ui/builder/component-builder.ts index b6d189b74..ee0f9fb07 100644 --- a/ui/builder/component-builder.ts +++ b/ui/builder/component-builder.ts @@ -103,8 +103,11 @@ export function getComponentModule(elementName: string, namespace: string, attri } export function setPropertyValue(instance: view.View, instanceModule: Object, exports: Object, propertyName: string, propertyValue: string) { + // Note: instanceModule can be null if we are loading custom compnenet with no code-behind. + var isEvent: boolean = instanceModule && isKnownEvent(propertyName, instanceModule[instance.typeName]); + if (isBinding(propertyValue) && instance.bind) { - if (isKnownEvent(propertyName, instanceModule[instance.typeName])) { + if (isEvent) { attachEventBinding(instance, propertyName, propertyValue); } else { var bindOptions = bindingBuilder.getBindingOptions(propertyName, getBindingExpressionFromAttribute(propertyValue)); @@ -115,7 +118,7 @@ export function setPropertyValue(instance: view.View, instanceModule: Object, ex twoWay: bindOptions[bindingBuilder.bindingConstants.twoWay] }, bindOptions[bindingBuilder.bindingConstants.source]); } - } else if (isKnownEvent(propertyName, instanceModule[instance.typeName])) { + } else if (isEvent) { // Get the event handler from page module exports. var handler = exports && exports[propertyValue];