# fusion-view

> Composition view manager.

Latest version **0.7.9** (published 2019-04-01) · 0 weekly downloads

## Install

```sh
npm install fusion-view
pnpm add fusion-view
yarn add fusion-view
bun add fusion-view
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities.

Warnings: low downloads; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.7.9 |
| Published | 2019-04-01 |
| First published | 2018-03-13 |
| Weekly downloads | 0 |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 1 |
| Unpacked size | 225.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | vizioneerzja |

## Links

- npm: https://www.npmjs.com/package/fusion-view
- npm.io page: https://npm.io/package/fusion-view

## Dependencies (1)

- [tslib](https://npm.io/package/tslib.md) ^1.9.0

## Recent versions

- 0.7.9 (latest) — 2019-04-01
- 0.7.8 — 2019-03-30
- 0.7.7 — 2019-03-30
- 0.7.6 — 2019-03-30
- 0.7.5 — 2019-03-30
- 0.7.4 — 2019-03-30
- 0.7.3 — 2019-03-30
- 0.7.2 — 2018-10-27
- 0.7.1 — 2018-10-25
- 0.7.0 — 2018-10-25
- 0.6.9 — 2018-10-25
- 0.6.7 — 2018-10-24
- 0.6.6 — 2018-10-24
- 0.6.5 — 2018-10-24
- 0.6.4 — 2018-10-24
- … 7 more at https://npm.io/package/fusion-view/versions

## README

# fusion-view

Dynamic component composition for your angular (v6, v7) applications (AOT, lazy modules compatible).


##

[![npm version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=js&type=6&v=0.7.9&x2=0)](https://www.npmjs.com/package/fusion-view)

## Table of contents

- [Installation](#installation)
- [Consuming library](#consuming-library)
- [Using Permissions](#using-permissions)
- [Credits](#credits)
- [License](#license)


## Installation

To install this library, run:

```bash
$ npm i fusion-view --save
```


## Consuming library

You can import library in any Angular application by running:

```bash
$ npm i fusion-view --save
```
___

Create a component that is isolated to a module for itself.
Ensure then component's class is placed inside the entryComponents field of the module.
Ensure the component's module imports all the modules that is required by the component.
```typescript

// Component
@Component({
  selector: 'app-user-card',
  templateUrl: './user-card.component.html',
  styleUrls: ['./user-card.component.scss']
})
export class UserCardComponent implements OnInit {
  @Input() user: User = new User();
}


// Component's Module
@NgModule({
  declarations: [UserCardComponent],
  entryComponents: [UserCardComponent],
  imports: [
    CommonModule,
  ]
})
export class UserCardModule { }
```

###
___

Define the manifest for your dynamic components in a typescript file for eg. component-manifest.ts
```typescript
import {FusionManifest} from 'fusion-view';

export const COMPONENT_MANIFESTS: FusionManifest[] = [
  {
      // Unique string that thee uses to locate this component
      componentId: 'user-card',
      
      // String selector that is found in the component definition
      selector: 'app-user-card',
      
      // Any unique string, this is used internally by the angular router
      path: 'user-card',
      
      // The path of the component's module, relative to the app module's location
      loadChildren: './users/user-card.module#UserCardModule'
  }
];
```

###
___

and then from your Angular `AppModule`:

```typescript
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {provideRoutes} from '@angular/router';

import { AppComponent } from './app.component';

// Import your library
import { FusionModule } from 'ngx-permissions';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,

    // Include the fusion module passing the manifests that was created before
    // as a parameter
     FusionModule.forRoot(COMPONENT_MANIFESTS),
  ],
  providers: [
    // Provide the manifests that was created to the router
    provideRoutes(COMPONENT_MANIFESTS)
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
```

###
###

NB. If you want to specify manifests from multiple files, you can do the following:
> CARDS_MANIFESTS and VIEWS_MANIFESTS are variables located in two different files
```typescript
  // For module Import
  FusionModule.forRoot([
       ...CARDS_MANIFESTS,
       ...VIEWS_MANIFESTS
  ])
  
  // For providing manifests to angular router
  provideRoutes([
      ...CARDS_MANIFESTS,
      ...VIEWS_MANIFESTS
  ])
```

###
___

To create a component dynamically, first ensure the FusionModule is imported into the module you are working with.

```typescript
@NgModule({
  declarations: [EmployeeListComponent],
  entryComponents: [EmployeeListComponent],
  imports: [
    CommonModule,
    FusionModule    // FusionModule imported
  ]
})
export class EmployeesModule { }
```

We want to create the user-card dynamically inside the EmployeeListComponent.
It would look something like this:

<b>user-card.ts</b>
```typescript
@Component({
  selector: 'app-user-card',
  templateUrl: './user-card.component.html',
  styleUrls: ['./user-card.component.scss']
})
export class EmployeeListComponent implements OnInit {
  userList: User[];
}
```
###
###

<b>user-card.html</b><br>
```html
<div class="user-list">
  <div fusion-view 
       componentId="app-user-card"
       *ngFor="let userData of userList;"
       [data]="{ user: userData }"></div>
</div>
```
>You can specify inputs of the component by passing it as a property of a object into the data attribute.
###
###
###
## Using Permissions
Permissions allow you to determine if a component should be created, based on permissions the user current have.
While this library does not provide a built in permission manager, 
fusion-view can hook into various permission managers that already exists. 
For this example, we will be using `ngx-permissions`
<br>
https://github.com/AlexKhymenko/ngx-permissions

___

Above your `AppModule`, we will create the following function:

```typescript
export function permissionChecker(permissionsService: NgxPermissionsService) {
    return (permissions: string[]) => {
      return permissionsService.hasPermission(permissions);
    };
}
```
This exported function returns another function, that accepts the permission list of type string array as its parameter.
The return type of this function can be either a `boolean` or a `Promise<boolean>` which would determine if a component
should be created or not.
###
###
Inside the `AppModule`, you would need to include the function created above as a provider to the Fusion library.
```typescript
providers: [
    {
        provide: FUSION_PERMISSION_CHECKER,
        useFactory: permissionChecker,
        deps: [NgxPermissionsService]
    },
],
```

___
Next you would need to update the manifest of the component you want to apply permissions to.
Add the property permissions to the manifest, this accepts a string array of the permissions needed to create
this component.
```typescript
export const COMPONENT_MANIFESTS: FusionManifest[] = [
  {
      componentId: 'user-card',
      selector: 'app-user-card',
      path: 'user-card',
      loadChildren: './users/user-card.module#UserCardModule',
      permissions: ['CAN_VIEW_USER']
  }
];
```
> If you do not specify the permissions property, or assign an empty array, fusion-view will by default render the
component
___

And that's pretty much it. Once the permission library tells fusion-view that the user has the necessary permissions,
the component would be created, otherwise the component would not be created.



## Credits
This project was inspired by the following articles
<br>
https://blog.angularindepth.com/dynamically-loading-components-with-angular-cli-92a3c69bcd28
<br>
https://blog.angularindepth.com/here-is-what-you-need-to-know-about-dynamic-components-in-angular-ac1e96167f9e


## License

MIT ©

---
_Source: https://npm.io/package/fusion-view · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
