npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ng-preset

v2.0.0

Published

> Preset library to help make your Angular components customizable

Downloads

7

Readme

NgPreset

Preset library to help make your Angular components customizable

Travis CI Coverage Maintainability Npm Npm Downloads Licence semantic-release

Ever wanted to build your component highly customizable but wondered how?

Seek no more with the Preset approach!

It allows you to expose essential parts of your components as templates and let others create custom presets for it - extendig your component without ever touching it.

You can create default preset only and ship it with your component but those who consume can choose to use other preset or even create their own.

While creating new preset you can choose to just override one template while keeping other template default.

Also you can combine multiple presets and they will all apply the last one taking precedence.

Install

If you are component developer:

$ npm install --save-dev ng-preset

Or if you are component consumer:

$ npm install --save ng-preset

Developing component with preset

Define a preset interface

First decide which parts of your component you want to make extendable via presets (suppose it's header, content and footer).

Once decided - create an abstract class that will represent this requirement as a preset:

// my-preset.ts
import { PresetType } from 'ng-preset';

export abstract class MyPreset extends PresetType {
  headerTpl: TemplateRef<any>;
  contentTpl: TemplateRef<any>;
  footerTpl: TemplateRef<any>;
}

NOTE: that each property you define should be of type TemplateRef, because that is what will be stamped inside of your component. And it is required to extend your class from PresetType for further validations.

You can also optionally provide some context information that a template will receive once instantiated as a generic argument but here we will just set them to any.

Get preset in component

Now in your component you can get preset component:

// my.component.ts
import { Preset } from 'ng-preset';
import { MyPreset } from './my-preset';

@Component({...})
export class MyComponent {
  @Preset() presetComp: MyPreset;
}

Stamp preset templates in your component

Once you get preset component you can now render it in your template:

// my.component.html
<header>
  <ng-container [ngTemplateOutlet]="presetComp.headerTpl"></ng-container>
</header>
<article>
  <ng-container [ngTemplateOutlet]="presetComp.contentTpl"></ng-container>
</article>
<footer>
  <ng-container [ngTemplateOutlet]="presetComp.footerTpl"></ng-container>
</footer>

That's all you need for the component!

Now you also probably want to provide some default preset for it, so go ahead and create new component.

Default preset component

Create new component that will just implement interface you defined in Define a preset interface section

// my-preset-default.component.ts
import { MyPreset } from '../my-preset';

@Component({
  ...
  template: `
    <ng-template #headerTpl>Header default preset</ng-template>
    <ng-template #contentTpl>Content default preset</ng-template>
    <ng-template #footerTpl>Footer default preset</ng-template>
  `
})
export class MyPresetDefaultComponent extends MyPreset {
  @ViewChild('headerTpl') headerTpl: TemplateRef<any>;
  @ViewChild('contentTpl') contentTpl: TemplateRef<any>;
  @ViewChild('footerTpl') footerTpl: TemplateRef<any>;
}

NOTE: Make sure you extend your preset class so that it can ba validated later.

That is all you need to have in your preset component!

Now it's time to glue them together in the module.

Create just component module

Create a module with just your component on it's own:

// my-component.module.ts
import { MyComponent } from './my.component';

@NgModule({
  ...
  declarations: [MyComponent],
  exports: [MyComponent],
})
export class MyComponentModule { }

Do not forget to export your component here.

With this module we can then create 2 more modules that will allow presets.

Module with default preset

This module is the default module and should contain default preset in it already setup and ready to roll:

// my.module.ts
import { PresetDefaultModule } from 'ng-preset';

import { MyComponent } from './my.component';
import { MyComponentModule } from './my-component.module';
import { MyPresetDefaultComponent } from './my-preset-default.component';

@NgModule({
  ...
  imports: [
    MyComponentModule,
    PresetDefaultModule.forComponent(MyComponent, MyPresetDefaultComponent),
  ],
  exports: [MyComponentModule],
  declarations: [MyPresetDefaultComponent],
})

NOTE: that we have to declare preset component here and also pass it to the imported PresetDefaultModule.withPreset module.

But what if the user have another preset for your component?

Custom module

Create another module that will allow user to pass it's own preset component.

// my-custom.module.ts
import { PresetModule, providePresetFor } from 'ng-preset';

import { MyPreset } from './my-preset';
import { MyComponent } from './my.component';
import { MyComponentModule } from './my-component.module';

@NgModule({
  ...
  imports: [
    MyComponentModule,
    PresetModule.forComponent(MyComponent),
  ],
  exports: [MyComponentModule],
})
export class MyCustomModule {
  static withPreset(presetType: Type<MyPreset>): ModuleWithProviders {
    return providePresetFor(MyCustomModule, presetType);
  }
}

NOTE: here it is important to pass generic argument because then users will be checked and warned by Typescript compiler that the preset does not match.

We are having 2 separate modules because if user provides it's own preset - we do not want him to pay the cost of carrying unused default presert.
It will be simply eliminated at the build time from the bundle.

Consuming component with preset

Default module

Most users will consume component with default preset in which case nothing special will be needed, just import the module:

// app.module.ts
import { MyModule } from '@me/my-module'; // Some library

@NgModule({
  ...
  imports: [MyModule]
})
export class AppModule { }

Custom module

And when you have some preset that you want to use with component just import custom version of module:

// app.module.ts
import { MyCustomModule } from '@me/my-module'; // Some library
import { MyPresetComponent } from '@me/my-preset'; // Some preset library

@NgModule({
  ...
  imports: [
    MyCustomModule.withPreset(MyPresetComponent)
  ]
})

That's it!

The component will be customized from now on!

Demo App server

Run ng serve for a dev server. Navigate to http://localhost:4200/. The app will automatically reload if you change any of the source files.

Build

Run npm run build and dist filder will be generated.

Running unit tests

Run npm test to execute the unit tests via Jest.

Licence

MIT © Alex Malkevich