Skip to content

Wrapper libraries: ReactWrapperComponent

Ben Grynhaus edited this page Mar 17, 2019 · 1 revision

An abstract class which provides a lot of help in regards to authoring wrapper libraries' components.

The full API documentation is in the code (wrapper-component.ts), but essentially, all wrapper components should extend it. Here are some of the more important stuff it handles for you as a wrapper component author:

  1. Pass down all attributes to the underlying React components
    • Note that this does not cover Inputs, since those are not plain strings and cannot be attached to the DOM [as-is]
  2. Allow automatically setting the display of the wrapper component, based on the root node of the wrapper React element (e.g. if you render an <Expander> which then renders a <div>, the display of your wrapper component would be set to block at runtime) - see WrapperComponentOptions
  3. Allow passing in arbitrary events that React can handle automatically
  4. [Much] Easier creation and handling of render props - see createRenderPropHandler and createInputJsxRenderer
    1. Automatic change detection for render props containing templates (by passing in an NgZone in WrapperComponentOptions)

Render props

Render props as a concept does not translate directly to Angular. The closest concept to it is an <ng-template> (the main difference between the two being that the later also has change detection via the implicit context its defined and use in - i.e. the template closure or component).

To still allow Angular apps to use the concepts they know inside React components, we created the InputRendererOptions type:

export type InputRendererOptions<TContext extends object> =
  | TemplateRef<TContext>
  | ((context: TContext) => HTMLElement)
  | ComponentRef<TContext>
  | RenderComponentOptions<TContext>;

export interface RenderComponentOptions<TContext extends object> {
  readonly componentType: Type<TContext>;
  readonly factoryResolver: ComponentFactoryResolver;
  readonly injector: Injector;
}

This allows passing any number of types as what will be then translated over to render props.

For more info on how these are then used see the inline code documentation, as well as the "Helper components" pages (ReactContent, ReactTemplate, Disguise).

Restrictions

When extend-ing from this component, there are a few restrictions being added, to make the lives of everyone easier and enforcing the message that these are just wrapper components, and shouldn't have their own styling, take their own space in the DOM etc.

  • Passing in the class attribute is forbidden. Use contentClass instead, which leverages classnames to allow both the familiar class syntax as well as one that's more like NgClass' one.
  • Passing in the style attribute is forbidden. Use contentStyle instead, which allows using both the familiar style string-based syntax, as well as one that's more like NgStyle (leveraging stylenames).

Caveats

As mentioned above, wrapper components should not have styling of their own. Ideally, they'd all be set with display: contents on themselves, removing them from the document flow. However, browser support for this is partial, and to not break Edge and IE we don't use it at the moment. See #102 for more info and follow up on that.