Skip to content

Commit

Permalink
feat(Events): allow a different local vs public name
Browse files Browse the repository at this point in the history
  • Loading branch information
vicb committed Jun 4, 2015
1 parent 53694eb commit 4848416
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 16 deletions.
22 changes: 21 additions & 1 deletion modules/angular2/src/core/annotations_impl/annotations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ export class Directive extends Injectable {
* events: ['statusChange']
* })
* class TaskComponent {
* statusChange:EventEmitter;
* statusChange: EventEmitter;
*
* constructor() {
* this.statusChange = new EventEmitter();
Expand All @@ -561,6 +561,26 @@ export class Directive extends Injectable {
* }
* }
* ```
*
* Use `propertyName: eventName` when the event emitter property name is different from the name
* of the emitted event:
*
* @Component({
* events: ['status: statusChange']
* })
* class TaskComponent {
* status: EventEmitter;
*
* constructor() {
* this.status = new EventEmitter();
* }
*
* onComplete() {
* this.status.next('completed');
* }
* }
* ```
*
*/
events: List<string>;

Expand Down
19 changes: 16 additions & 3 deletions modules/angular2/src/core/compiler/element_injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
Type,
BaseException,
stringify,
CONST_EXPR
CONST_EXPR,
StringWrapper
} from 'angular2/src/facade/lang';
import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
import {List, ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
Expand Down Expand Up @@ -380,8 +381,20 @@ export class BindingData {
createEventEmitterAccessors() {
if (!(this.binding instanceof DirectiveBinding)) return [];
var db = <DirectiveBinding>this.binding;
return ListWrapper.map(db.eventEmitters, eventName => new EventEmitterAccessor(
eventName, reflector.getter(eventName)));
return ListWrapper.map(db.eventEmitters, eventConfig => {
let localName;
let publicName;
var colonIdx = eventConfig.indexOf(':');
if (colonIdx > -1) {
// long format: 'localName: publicName'
localName = StringWrapper.substring(eventConfig, 0, colonIdx).trim();
publicName = StringWrapper.substring(eventConfig, colonIdx + 1).trim();
} else {
// short format: 'name' when localName and publicName are the same
localName = publicName = eventConfig;
}
return new EventEmitterAccessor(publicName, reflector.getter(localName))
});
}

createHostActionAccessors() {
Expand Down
12 changes: 12 additions & 0 deletions modules/angular2/test/core/compiler/element_injector_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,18 @@ export function main() {
expect(accessor.getter(new HasEventEmitter())).toEqual('emitter');
});

it('should allow a different internal vs public name', () => {
var binding = DirectiveBinding.createFromType(HasEventEmitter,
new dirAnn.Directive({events: ['emitter: publicEmitter']}));

var inj = createPei(null, 0, [binding]);
expect(inj.eventEmitterAccessors.length).toEqual(1);

var accessor = inj.eventEmitterAccessors[0][0];
expect(accessor.eventName).toEqual('publicEmitter');
expect(accessor.getter(new HasEventEmitter())).toEqual('emitter');
});

it('should return a list of hostAction accessors', () => {
var binding = DirectiveBinding.createFromType(
HasEventEmitter, new dirAnn.Directive({hostActions: {'hostActionName': 'onAction'}}));
Expand Down
52 changes: 40 additions & 12 deletions modules/angular2/test/core/compiler/integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,32 @@ export function main() {
});
}));

it('should support EventEmitter with local names',
inject([TestBed, AsyncTestCompleter], (tb, async) => {
tb.overrideView(MyComp, new viewAnn.View({
template: '<div emitter listener></div>',
directives: [DirectiveEmitingEvent, DirectiveListeningEvent]
}));

tb.createView(MyComp, {context: ctx})
.then((view) => {

var injector = view.rawView.elementInjectors[0];

var emitter = injector.get(DirectiveEmitingEvent);
var listener = injector.get(DirectiveListeningEvent);

expect(listener.publicEventMsg).toEqual('');

ObservableWrapper.subscribe(emitter.localEvent, (_) => {
expect(listener.publicEventMsg).toEqual('fired !');
async.done();
});

emitter.fireLocalEvent('fired !');
});
}));

it('should support [()] syntax', inject([TestBed, AsyncTestCompleter], (tb, async) => {
tb.overrideView(MyComp, new viewAnn.View({
template: '<div [(control)]="ctxProp" two-way></div>',
Expand Down Expand Up @@ -1379,18 +1405,16 @@ class DoublePipeFactory {
create(cdRef) { return new DoublePipe(); }
}

@Directive({selector: '[emitter]', events: ['event']})
@Directive({selector: '[emitter]', events: ['event', 'localEvent: publicEvent']})
@Injectable()
class DirectiveEmitingEvent {
msg: string;
event: EventEmitter;

constructor() {
this.msg = '';
this.event = new EventEmitter();
}
msg: string = '';
event: EventEmitter = new EventEmitter();
localEvent: EventEmitter = new EventEmitter();

fireEvent(msg: string) { ObservableWrapper.callNext(this.event, msg); }

fireLocalEvent(msg: string) { ObservableWrapper.callNext(this.localEvent, msg); }
}

@Directive({selector: '[update-host-attributes]', hostAttributes: {'role': 'button'}})
Expand Down Expand Up @@ -1419,14 +1443,18 @@ class DirectiveUpdatingHostActions {
triggerSetAttr(attrValue) { ObservableWrapper.callNext(this.setAttr, {'attrValue': attrValue}); }
}

@Directive({selector: '[listener]', hostListeners: {'event': 'onEvent($event)'}})
@Directive({
selector: '[listener]',
hostListeners: {'event': 'onEvent($event)', 'publicEvent': 'onPublicEvent($event)'}
})
@Injectable()
class DirectiveListeningEvent {
msg: string;

constructor() { this.msg = ''; }
msg: string = '';
publicEventMsg: string = '';

onEvent(msg: string) { this.msg = msg; }

onPublicEvent(msg: string) { this.publicEventMsg = msg; }
}

@Directive({
Expand Down

0 comments on commit 4848416

Please sign in to comment.