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', () => {