diff --git a/packages/core/src/debug/debug_node.ts b/packages/core/src/debug/debug_node.ts index 722009eb21..7e2a3210ee 100644 --- a/packages/core/src/debug/debug_node.ts +++ b/packages/core/src/debug/debug_node.ts @@ -538,23 +538,26 @@ function collectPropertyBindings( let bindingIndex = getFirstBindingIndex(tNode.propertyMetadataStartIndex, tData); while (bindingIndex < tNode.propertyMetadataEndIndex) { - let value = ''; + let value: any; let propMetadata = tData[bindingIndex] as string; while (!isPropMetadataString(propMetadata)) { // This is the first value for an interpolation. We need to build up // the full interpolation by combining runtime values in LView with // the static interstitial values stored in TData. - value += renderStringify(lView[bindingIndex]) + tData[bindingIndex]; + value = (value || '') + renderStringify(lView[bindingIndex]) + tData[bindingIndex]; propMetadata = tData[++bindingIndex] as string; } - value += lView[bindingIndex]; + value = value === undefined ? lView[bindingIndex] : value += lView[bindingIndex]; // Property metadata string has 3 parts: property name, prefix, and suffix const metadataParts = propMetadata.split(INTERPOLATION_DELIMITER); const propertyName = metadataParts[0]; // Attr bindings don't have property names and should be skipped if (propertyName) { - // Wrap value with prefix and suffix (will be '' for normal bindings) - properties[propertyName] = metadataParts[1] + value + metadataParts[2]; + // Wrap value with prefix and suffix (will be '' for normal bindings), if they're defined. + // Avoid wrapping for normal bindings so that the value doesn't get cast to a string. + properties[propertyName] = (metadataParts[1] && metadataParts[2]) ? + metadataParts[1] + value + metadataParts[2] : + value; } bindingIndex++; } diff --git a/packages/core/test/debug/debug_node_spec.ts b/packages/core/test/debug/debug_node_spec.ts index 22acf260ba..150c20c60a 100644 --- a/packages/core/test/debug/debug_node_spec.ts +++ b/packages/core/test/debug/debug_node_spec.ts @@ -195,6 +195,20 @@ class TestCmptWithViewContainerRef { constructor(private vcref: ViewContainerRef) {} } +@Component({ + template: ` + +` +}) +class TestCmptWithPropBindings { + disabled = true; + tabIndex = 1337; + title = 'hello'; +} + { describe('debug element', () => { let fixture: ComponentFixture; @@ -218,6 +232,7 @@ class TestCmptWithViewContainerRef { HostClassBindingCmp, TestCmptWithViewContainerRef, SimpleContentComp, + TestCmptWithPropBindings, ], providers: [Logger], schemas: [NO_ERRORS_SCHEMA], @@ -566,6 +581,14 @@ class TestCmptWithViewContainerRef { expect(debugElement.properties.className).toBeFalsy(); }); + it('should preserve the type of the property values', () => { + const fixture = TestBed.createComponent(TestCmptWithPropBindings); + fixture.detectChanges(); + + const button = fixture.debugElement.query(By.css('button')); + expect(button.properties).toEqual({disabled: true, tabIndex: 1337, title: 'hello'}); + }); + describe('componentInstance on DebugNode', () => { it('should return component associated with a node if a node is a component host', () => {