Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - @Input and @Output vs. Injectable Service

I'm asking myself where are the differences between @Input/@Output in parent-/childcomponents and using services which is only once instatiated with dependency Injection@Injectable(). Or are there any differences besides Input/Output can only be used in parent-/child-comp.

Following Example for better visualization:

With @Input:

<parent-comp>
   <child-comp [inputFromParent]="valueFromParent"></child-comp>
</parent-comp>

ChildComponent:

@Component({
  selector: 'child-comp',
  template: ...
})
export class ChildComponent {
  @Input() public inputFromParent: string;
}

With dependency Injection

@Injectable()
export class Service {
   private value: string;

public get value(): string {
   return value;
}

public set value(input): void {
   value = input;
}

}

Now we can set the value in the parent comp. and get the value in the child comp with dependancy injection. ChildComponent:

@Component({
  selector: 'child-comp',
  template: ...
})
export class ChildComponent {
  private value: string;
  constructor(private service: Service) {
  this.value = this.service.getValue;
}

}

Even though the first approach looks simpler, I recognized using 3-4 properties carriyng through parent-/child comp. with @Input/@Output makes the tamplete very confusing and clunky.

like image 965
MarcoLe Avatar asked Jun 25 '18 16:06

MarcoLe


People also ask

What is the difference between @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 the difference between @ViewChild and @output in Angular?

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.

What are the different ways to inject the Angular service?

Constructor injection: Here, it provides the dependencies through a class constructor. Setter injection: The client uses a setter method into which the injector injects the dependency. Interface injection: The dependency provides an injector method that will inject the dependency into any client passed to it.

What is @input and @output in Angular with example?

@Input defines the input property in the component, which the parent component can set. The @output defines the output property (event), which we raise in the child component using the EventEmitter . The parent listens to these events. Applies to: Angular 2 to the latest edition of i.e. Angular 8.


1 Answers

Not exactly a question with a defined answer, but....

@Input and @Output are useful if the communication between a parent and child is just that, between a parent and child. It wouldn't make sense to have a service that maintains singleton data for just 2 components (or however deeply nested grandparent -> parent -> child components are).

They're also useful if your parent needs to react to a change in the child. For example, clicking a button in a child component that calls a function in the parent:

<my-child-component (myOutputEmitter)="reactToChildChange($event)"></my-child-component>

And in parent:

reactToChildChange(data: any) {
  // do something with data
}

If you find yourself passing many @Input properties to a child, and want to tidy up a template, then you can define an interface for the input, and pass it instead. e.g.

export interface MyChildProperties {
   property?: any;
   anotherProperty?: any;
   andAnotherProperty?: any;
}

Then you can pass a definition to your child, which is set from the parent:

childProperties: MyChildProperties = {
    property: 'foo',
    anotherProperty: 'bar',
    andAnotherProperty: 'zoob'
}

Then your child component may have:

@Input properties: MyChildProperties;

and your template becomes:

<my-child-component [properties]="childProperties"></my-child-component>

Your child can access those properties from properties.property, properties.anotherProperty, etc.

Clean, tidy, and your data is now contained to those components that need to communicate.

Services, however, should be used where more than one component needs access to read/write data across your entire application. Consider a UserService for example, where many different components need to be able to access the currently logged in user. In this case, a service is sensible, as its a singleton, so once you have set your logged in user, any components that inject the UserService can access its data and functions.

Similarly, if you were to use a service for reacting to change, then you'd find yourself writing services with observables so that your components could subscribe to changes in the data. Eventemitters already give you this pattern with @Output as shown above.

If it were a simple parent -> child communication, this is unnecessary overhead, and should be avoided.

That said, if you find yourself using services to manage global state, you'd be better off using some form of state management such as ngrx

like image 84
prettyfly Avatar answered Oct 25 '22 05:10

prettyfly