26

It has been weeks now, that I search for a solution. I created (with ng generate library) a library with the UI in for new webprojects here at work... in fact every component in that "template library" has the ViewEncapsulation.None set... I know it's not the way we should use Angular, but it would allow us to reuse all the hard work that has been done in previous years.

I want to "pack" the stylesheets (.css files) into the library in a way that when somebody does an "npm install templatelib" he/she'll get all the styles and fonts automatically included in their application, no need to manually copy the styles and fonts in their src/app.

I want to give my users an atomic unit in a way somebody just needs to set a template-lib-tag in their app.component.html and they're all set... then they would only need to add the content components they want to show/use inside the templates design.

I've tried pretty much everything I could find to "pack" the assets, but I either get errors stating that the Data path "" should NOT have additional properties(styles). when I try to add assets or styles to the angular.json... or it doesn't do what I want it to do resulting in errors that it can't find the assets during ng serve.

Am I too much demanding of Angular Libraries ? Or is a library filled with components and their CSS not an atomic unit that I can plug into any other Angular app ?

What am I doing wrong/misunderstanding, and how should we "pack" assets into our library so they travel along when installing the package.

Thanks for clarifying in advance.

Shubham Verma
  • 8,783
  • 6
  • 58
  • 79
Michael Bruyninckx
  • 738
  • 1
  • 8
  • 16
  • I get the same "data path" error when I try to add an assets clause to the angular-cli options JSON. For now I'm just appending `cp -a /path/to/source/. /path/to/dist` to my build command in `package.json` – CaitlinW Jul 09 '18 at 15:59
  • Why you don't go through running multiple apps withing one project? https://github.com/angular/angular-cli/wiki/stories-multiple-apps – molikh Jul 12 '18 at 08:06
  • I'm running 10 apps in one project all share one library file ( so all once loaded and cached for all apps ) and if any change needed in one component ( like a bug in phone input component ) all will change with one build and so ... . but I should write an article about it if you need to know all about what I did ( long story ). I hope i can help you if got any question. – molikh Jul 12 '18 at 08:10
  • This question description is not very readable – Hayden Jul 13 '18 at 05:54
  • 1
    How are you referencing the style sheets in your `angular.json` file? I have successfully been able to add style sheets from node modules in apps by referencing the files directly in the `angular.json` file via syntax like `'node_modules/package/path/to/style/sheet.css'` (we have a corporate style guide with css, images, fonts, and js files packaged and distributed via an internal npm repo). Additionally, I created an Angular CLI schematic that takes care of adding all of these files to the `angular.json` file. – Daniel W Strimpel Jul 13 '18 at 19:49
  • check my answer here https://stackoverflow.com/a/59265830/2713029 – Shubham Takode Dec 10 '19 at 11:08

1 Answers1

8

You were already on the right track with your solution with ViewEncapsulation.None. You can make a container component in the library that includes all the styles you need globally. Then use the component as the root tag in your application as you suggest in your post. The styles are then automatically included to the whole page.

Here is how a sample component looks like:

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'lib-assetlib',
  template: '<ng-content></ng-content>',
  styleUrls: ['assetlib.component.css', 'libstyles.css'],
  encapsulation: ViewEncapsulation.None
})
export class AssetlibComponent {
}

You can import many css files in the styleUrls as you see in my sample. Then you just add this as the root tag in your app.component template and the styles are applied globally to the whole page. No need to reference anything in the angular.json.

Example app component:

<lib-assetlib>
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
  <h1>
    Welcome to {{ title }}!
  </h1>
  <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>
<h2>Here are some links to help you start: </h2>
<ul>
  <li>
    <h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
  </li>
  <li>
    <h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
  </li>
  <li>
    <h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
  </li>
</ul>
<i class="fas fa-stroopwafel"></i> <!--This uses a style that comes from the library-->
</lib-assetlib>
Aleš Doganoc
  • 11,568
  • 24
  • 40
  • Could this be enhanced to share scss e.g. allow mixins to be shared? – Matthew Sep 02 '18 at 05:32
  • 1
    No because the scss gets processed when you build the library if you put it in styleUrls of the component. You can do that only by adding the scss files with the mixins in the library as assets and then import them in the component scss files where you want to use the mixins from the node_modules/[yourlibraryname] folder. – Aleš Doganoc Sep 03 '18 at 22:06
  • 1
    I'm using this method - thanks for the inspiration. But I'm struggling as my library needs to use specific fonts ... How can I include those fonts in the Library? (They are in-house fonts so would prefer to package them up rather than specifying a URL) – Maxxx Oct 29 '18 at 00:16
  • You can include a font as a base64 string in the CSS. See this [post](https://stackoverflow.com/questions/26867893/converting-and-rendering-web-fonts-to-base64-keep-original-look). So all you need to do is convert your fonts to base64 and put them inside the CSS styles of the component. – Aleš Doganoc Oct 30 '18 at 22:41