Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2/TypeScript: @Input/@output or input/output?

While doing a course on Udemy we have been allowing components to be passed data dy using the @Input() decorator in the component class.

While reading through ngBook-2 I have found that there is another approach by using the input property inside an @Component decorator.

THIS similar question on SO, One person answered:

One advantage of using inputs is that users of the class only need to look at the configuration object passed to the @Component decorator to find the input (and output) properties.

and look through documentation state that:

Whether you use inputs/outputs or @Input/@Output the result is the same so choosing which one to use is largely a stylistic decision.

Really, the most useful information about this is mostly conflicting depending on where you look.

Inside @Component

 @Component({
  selector: 'product-image',
  inputs: ['product'],
  template: `
  <img class="product-image" [src]="product.imageUrl">
})

class ProductImage {
  product: Product;
}

Inside Class

@Component({
  selector: 'product-image',
  template: `
  <img class="product-image" [src]="product.imageUrl">
})

class ProductImage {
  @Input() product: Product;
}

Things I would like to know

  • What one would be more of "best practice" usage?
  • When would you use one over the other?
  • Are there any differences at all?
like image 649
ShadowCore Avatar asked Dec 25 '16 04:12

ShadowCore


People also ask

For what do you use input and output in Angular?

@Input() and @Output() give a child component a way to communicate with its parent component. @Input() lets a parent component update data in the child component. Conversely, @Output() lets the child send data to a parent component.

What is @input and @output in Angular 2?

The above pattern — passing data in through an “input” property and sending data out through an “output” event — is the primary way to share data between Angular 2 components.

What is input () in Angular?

Decorator that marks a class field as an input property and supplies configuration metadata. The input property is bound to a DOM property in the template. During change detection, Angular automatically updates the data property with the DOM property's value.

What is the difference between @ViewChild and @input?

While Angular inputs/outputs should be used when sharing data to and from child components, ViewChild should be used when trying to utilize properties and methods of the child component directly in the parent component.


2 Answers

One of the cool thing that I know you can do with decorators but I'm not if it's possible with the other way, is aliasing the variable:

export class MyComponent {

 @Output('select') $onSelect = new EventEmitter<any>(); // this is aliased

 @Output() finish  = new EventEmitter<any>(); // not aliased

 sendUp(){
    this.$onSelect.emit('selected'); 

    this.finish.emit('done');
 }
}

and then from outside :

 <my-component (select)="doSomething($event)"></my-component>

The other one is setting a default value, you can set default value in both ways but decorators seem more convenient and less code.

@Component({ 
  selector:'my-component'
})
export class MyComponent {
  @Input() id = 'default-id';     

  ngOnInit(){

    console.log('id is : ',this.id); // will output default-id if you don't pass anything when using the component
  }
}

So in this case , if the consumer doesn't pass the id as an input, you still have default-id ;

 <my-component></my-component>;

Where as , if you wanted to do this with inputs array , you'd do :

@Component({ 
  selector:'my-component',
  inputs:['id']
})
export class MyComponent {
  private id = 'default-id';     

  ngOnInit(){

    console.log('id is : ',this.id); // will output default-id if you don't pass anything when using the component
  }
}

The result is the same , but if you notice , in this case you have to put id both in inputs array and define it inside the class.

EDIT:

Apparently aliasing with outputs[] is also possible, like bellow :

@Component({
  selector: 'my-component',
  template: `
   <button (click)="sendUp()">Send up</button>
  `,
  outputs: ['$onSelect: select']
})
export class ChildComponent {
  $onSelect = new EventEmitter<any>(); // this is aliased

  sendUp() {
    this.$onSelect.emit('selected');
  }
}

But again you have to define it in two places , on in the array and one in the class , so I'd still prefer the decorators.

like image 181
Milad Avatar answered Sep 28 '22 12:09

Milad


Angular 2 Style Guide

According to the official Angular 2 style guide, STYLE 05-12 says

Do use @Input and @Output instead of the inputs and outputs properties of the @Directive and @Component decorators

The benefit is that (from the guide):

  • It is easier and more readable to identify which properties in a class are inputs or outputs.
  • If you ever need to rename the property or event name associated with @Input or @Output, you can modify it a single place.
  • The metadata declaration attached to the directive is shorter and thus more readable.
  • Placing the decorator on the same line makes for shorter code and still easily identifies the property as an input or output.

I've personally used this style and really appreciate it helping keep the code DRY.

like image 41
adriancarriger Avatar answered Sep 28 '22 10:09

adriancarriger