diff --git a/packages/language-service/src/completions.ts b/packages/language-service/src/completions.ts index 3412abffef..87b00c364b 100644 --- a/packages/language-service/src/completions.ts +++ b/packages/language-service/src/completions.ts @@ -173,8 +173,9 @@ function getAttributeInfosForElement( matcher.match(elementSelector, selector => { let directive = selectorMap.get(selector); if (directive) { - attrs.push(...Object.keys(directive.inputs).map(name => ({name, input: true}))); - attrs.push(...Object.keys(directive.outputs).map(name => ({name, output: true}))); + const {inputs, outputs} = directive; + attrs.push(...Object.keys(inputs).map(name => ({name: inputs[name], input: true}))); + attrs.push(...Object.keys(outputs).map(name => ({name: outputs[name], output: true}))); } }); diff --git a/packages/language-service/test/completions_spec.ts b/packages/language-service/test/completions_spec.ts index 84f5281b73..6b4dda17c9 100644 --- a/packages/language-service/test/completions_spec.ts +++ b/packages/language-service/test/completions_spec.ts @@ -187,6 +187,27 @@ export class MyComponent { contains('/app/my.component.ts', 'tree', 'children'); }); + it('should work with input and output', () => { + addCode( + ` + @Component({ + selector: 'foo-component', + template: \` +
+
+ \`, + }) + export class FooComponent { + text: string; + value: number; + } + `, + (fileName) => { + contains(fileName, 'stringMarker', '[model]', '(model)'); + contains(fileName, 'numberMarker', '[inputAlias]', '(outputAlias)'); + }); + }); + function addCode(code: string, cb: (fileName: string, content?: string) => void) { const fileName = '/app/app.component.ts'; const originalContent = mockHost.getFileContent(fileName); diff --git a/packages/language-service/test/test_data.ts b/packages/language-service/test/test_data.ts index b4eb785ef1..55c6255298 100644 --- a/packages/language-service/test/test_data.ts +++ b/packages/language-service/test/test_data.ts @@ -44,7 +44,7 @@ import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; import { CaseIncompleteOpen, CaseMissingClosing, CaseUnknown, Pipes, TemplateReference, NoValueAttribute, - AttributeBinding, StringModel,PropertyBinding, EventBinding, TwoWayBinding, EmptyInterpolation, + AttributeBinding, StringModel, NumberModel, PropertyBinding, EventBinding, TwoWayBinding, EmptyInterpolation, ForOfEmpty, ForLetIEqual, ForOfLetEmpty, ForUsingComponent, References, TestComponent} from './parsing-cases'; import { WrongFieldReference, WrongSubFieldReference, PrivateReference, ExpectNumericType, LowercasePipe } from './expression-cases'; import { UnknownPeople, UnknownEven, UnknownTrackBy } from './ng-for-cases'; @@ -53,7 +53,7 @@ import { ShowIf } from './ng-if-cases'; @NgModule({ imports: [CommonModule, FormsModule], declarations: [AppComponent, CaseIncompleteOpen, CaseMissingClosing, CaseUnknown, Pipes, TemplateReference, NoValueAttribute, - AttributeBinding, StringModel, PropertyBinding, EventBinding, TwoWayBinding, EmptyInterpolation, ForOfEmpty, ForOfLetEmpty, + AttributeBinding, StringModel, NumberModel, PropertyBinding, EventBinding, TwoWayBinding, EmptyInterpolation, ForOfEmpty, ForOfLetEmpty, ForLetIEqual, ForUsingComponent, References, TestComponent, WrongFieldReference, WrongSubFieldReference, PrivateReference, ExpectNumericType, UnknownPeople, UnknownEven, UnknownTrackBy, ShowIf, LowercasePipe] }) @@ -113,6 +113,12 @@ export class StringModel { @Output() modelChanged: EventEmitter; } +@Directive({selector: '[number-model]'}) +export class NumberModel { + @Input('inputAlias') model: number; + @Output('outputAlias') modelChanged: EventEmitter; +} + interface Person { name: string; age: number