Input and outputs, how to work with them to follow the naming convention of the Angular 2's styleguide?
Before I knew any better I used to have my directive defined like this:
...
inputs: [
'onOutside'
]
...
export class ClickOutsideDirective {
@Output() onOutside: EventEmitter<any> = new EventEmitter();
}
But then I read the styleguide and it said that you should not prefix your outputs with on
since Angular 2 supports the on-
syntax in the templates.
So I'm trying to change it to something like:
@Input() outsideClick: any;
@Output() outsideClick: EventEmitter<any> = new EventEmitter();
However, I'm finding it difficult to separate the @Input
name from the Output
name if you aren't allowed to use the on
prefix.
Before you could name both the @Input
and @Output
the same thing but if declaring both within the exported class then this no longer works since an error will be thrown.
If I name the @Input
to outside
and the @Output
to outsideClick
, it doesn't really make sense since both of them are the same thing. outside
is the function I want to execute when calling outsideClick
.
Also, outsideClick
won't know what to execute if outside
isn't name the same thing anymore, or am I missing something?
How should I approach naming the @Input
and @Output
variables here so that it still works and makes as much sense as it did in the first example?
EDIT:
Usage example:
<div clickOutside [exceptions]="['.toggler']" (outside)="doSomethingOnOutsideClick()"></div>
Input and outputs, how to work with them to follow the naming convention of the Angular 2's styleguide?
Before I knew any better I used to have my directive defined like this:
...
inputs: [
'onOutside'
]
...
export class ClickOutsideDirective {
@Output() onOutside: EventEmitter<any> = new EventEmitter();
}
But then I read the styleguide and it said that you should not prefix your outputs with on
since Angular 2 supports the on-
syntax in the templates.
So I'm trying to change it to something like:
@Input() outsideClick: any;
@Output() outsideClick: EventEmitter<any> = new EventEmitter();
However, I'm finding it difficult to separate the @Input
name from the Output
name if you aren't allowed to use the on
prefix.
Before you could name both the @Input
and @Output
the same thing but if declaring both within the exported class then this no longer works since an error will be thrown.
If I name the @Input
to outside
and the @Output
to outsideClick
, it doesn't really make sense since both of them are the same thing. outside
is the function I want to execute when calling outsideClick
.
Also, outsideClick
won't know what to execute if outside
isn't name the same thing anymore, or am I missing something?
How should I approach naming the @Input
and @Output
variables here so that it still works and makes as much sense as it did in the first example?
EDIT:
Usage example:
<div clickOutside [exceptions]="['.toggler']" (outside)="doSomethingOnOutsideClick()"></div>
Share
Improve this question
edited Feb 4, 2023 at 13:07
Top-Master
8,7455 gold badges49 silver badges86 bronze badges
asked Oct 8, 2016 at 8:27
ChrillewoodzChrillewoodz
28.3k23 gold badges99 silver badges186 bronze badges
2 Answers
Reset to default 19Definitely don't use on
. In JavaScript events also don't start with on
. Only the event handlers do. There is no onClick
event in JS. The event name is click
and if you assign a function to onClick
this function will be called when the click
event was received.
If you have inputs and outputs that belong together name them
@Input() name:any;
@Output() nameChange: EventEmitter<any> = new EventEmitter();;
This allows the short hand for Angular2 "two-way binding"
[(name)]="someProp"
If you use @Input()
and @Output()
(preferred way) then you don't need inputs: []
and outputs: []
. These are two ways to do the same thing and if you use both one is redundant.
To match the browser naming scheme what you could do is
(nameChange)="onNameChange($event)"
to have an event handler onNameChange
to be called when the nameChange
event is received.
When the event is not part of an input/output pair you can or should omit the Change
(loggedIn)="onLoggedIn($event)
Actually, the OP made multiple questions, but with same context (hence below has multiple sections).
Usage and/or definition
If you want to support Angular-2 and later-version's "two-way binding",
then pair input with a Change
suffixed output, like:
@Input() password: string;
@Output() passwordChange: EventEmitter<string> = new EventEmitter();
This allows short-hand(s) like:
<app-my-component
[(password)]="myPasswordProp"
>
</app-my-component>
Above I pass default-value to component as input, and take user's changes as output, basically syncing
myPasswordProp
withMyComponent
's internal state.
Naming convention
In Angular-2
+ use "on
" prefix only for event-handlers, never event-emitters.
Note that "
on
" prefix is not allowed for events (and even causes compile error, at least in newer Angular versions).
Even in JavaScript
, there is no onClick
named event, the event name is click
.
The only difference is that JS uses onClick
as name of attribute where we pass event-handler, while Angular forbids that prefix.
Angular at least allows using on
for event-handlers, like:
(passwordChange)="onPasswordChange($event)"
Where the
onPasswordChange
named event-handler is called when thepasswordChange
event is triggered.
But if the event is not part of an input/output pair, we should omit the Change
suffix while defining the output, and use it like:
(loggedIn)="onLoggedIn($event)"
Or further more, to have a prefix like Browser's naming-scheme,
and/or to separate events from other things,
our company did use "by
" prefix instead, like:
(byLogin)="onLogin($event)"
(bySave)="onSave($event)"
Which is far more readable, because it can be part of human-sentences, like:
- "Our App's handler is pending on login to happen, which is triggered by login event(s) of the library."
Or the other way around:
- "The library does by login event(s) trigger our App's handler, which is pending on login to happen."
Readability is one of the reasons why both "on" and "by" prefixes can be used the way they are.
Class-annotation vs Property-annotation
Just because OP mentioned it:
Using
@Input()
and/or@Output()
annotation with member-variable(s) is the preferred way.If you use above, then you don't need to pass
inputs: []
and/oroutputs: []
to class' annotation.Basically, these are two approaches to achive the same thing, and if you use one, the other one is redundant.