Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create higher order components in Angular 2

Tags:

angular

Higher Order Components (HOC) is a pattern common among React community. See this article if you don't know what's a HOC

Do they make sense in Angular 2? How to make a HOC? Any examples?

like image 708
Alex JM Avatar asked Oct 15 '16 15:10

Alex JM


People also ask

What is higher-order components in angular?

A higher-order component (HOC) is an advanced technique for reusing component logic. Concretely, a higher-order component is a function that takes a component and returns a new component.

What is higher-order component in Example?

Higher-Order Components are not part of the React API. They are the pattern that emerges from React's compositional nature. The component transforms props into UI, and a higher-order component converts a component into another component. The examples of HOCs are Redux's connect and Relay's createContainer.

What is @component in angular?

Components are the most basic UI building block of an Angular app. An Angular app contains a tree of Angular components. Angular components are a subset of directives, always associated with a template. Unlike other directives, only one component can be instantiated for a given element in a template.

What is NgComponentOutlet?

NgComponentOutletlinkInstantiates a Component type and inserts its Host View into the current View. NgComponentOutlet provides a declarative approach for dynamic component creation.


2 Answers

Use NgComponentOutlet

Simple case

@Component({selector: 'hello-world', template: 'Hello World!'})
class HelloWorld {
}

@Component({
  selector: 'ng-component-outlet-simple-example',
  template: `<ng-container *ngComponentOutlet="myComponent"></ng-container>`
})
class NgTemplateOutletSimpleExample {
  // This field is necessary to expose HelloWorld to the template.
  myComponent= HelloWorld;
}

Advanced cases including providing Injector and Content are available in official documentation

like image 139
Alexey Petushkov Avatar answered Sep 20 '22 07:09

Alexey Petushkov


I am also very interested in something similar to HOC (Recompose like in Angular 2). I recently was trying to create an analog to mapToProps HOC' Recompose for Angular - mapToInputs using Angular structural directive. I am looking for a better approach.

  @Component({
    selector: 'user-list',
    template: `
       <h2>{{status}} users</h2> 
       <div *ngFor="let item of data">{{item}}</div>
    `
  })
  export class UserList {
    @Input() data: Array<any>;
    @Input() status: string;
  }

  @Directive({selector: '[mapInputs]'})
  export class MapInputs {
    component;

    @Input() set mapInputsComponent(component) {
     this.component = component;
    }

    @Input() set mapInputs(fn) {
      this.vc.clear();
      let factory = this.componentFactoryResolver.resolveComponentFactory(this.component);
      let componetRef =  this.vc.createComponent(factory);

      let inputs = fn();
      console.log(inputs);
      Object.entries(inputs).forEach(([key, value]) => {
        componetRef.instance[key] = value;
      });
    }

    constructor(private vc: ViewContainerRef, 
          private componentFactoryResolver: ComponentFactoryResolver) {
    }
  }

  @Component({
    selector: 'my-app',
    template: `
      <div>
        <button (click)="doubledata()">Doubel Data</button>
        <div *mapInputs="filterBy.bind(null, {data:data, status:'active'}); component: component"></div>
        <div *mapInputs="filterBy.bind(null, {data:data, status:'passive'}); component: component"></div>
        <div *mapInputs="filterBy.bind(null,  {data:data, status:'blocked'}); component: component"></div>
      </div>
    `,
  })
  export class App {
    name: string;
    component = UserList;
    data = ['active', 'active', 'passive', 'blocked', 'blocked'];
    filterBy = (context) => {
       return {
          status: context.status,
          data: context.data.filter(el => el ===  context.status);
       };
    }

    doubledata(){
      this.data = this.data.concat(this.data);
    }

    constructor() {
      this.name = `Angular! v${VERSION.full}`
    }
  }
like image 38
Julia Passynkova Avatar answered Sep 21 '22 07:09

Julia Passynkova