bmurauer
bmurauer

Reputation: 1259

Expose and use customizable variables in Angular library

I have made an Angular library containing one component myComponent. I can successfully build it and use it in my main application. I want to add the functionality of customizing some of the scss variables that are used in myComponent by the consuming main application. I could not find any exhaustive guides on this topic. What I have so far:

Is it possible to get the desired behavior?

Upvotes: 4

Views: 1574

Answers (3)

bmurauer
bmurauer

Reputation: 1259

using CSS3 variables, I have enough control over the parameters that i want to offer. The resulting structure is as follows:

mylib
  ng-package.json
  scss
    mytheme.scss
  src
    public-api.ts
    lib 
      my.component.ts   <- standalone component
      my.component.scss

ng-package.json:

{
  "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
  "dest": "../../../dist/mylib",
  "lib": {
    "entryFile": "src/public-api.ts",
    "styleIncludePaths": [
      "scss"
    ]
  },
  "assets": [
    "scss/*"
  ]
}

theme.scss:

:root {
  --some-size-variable: 3px;
  --some-color-variable: #22aaff;
}

public-api.ts:

export * from './lib/my.component';

my.component.ts:

@Component({
  standalone: true,
  template: '',
  styleUrls: ['my.component.scss'],
})
export class MyComponent {
  // lots of Angular goodness
}

my.component.scss:

@import 'mytheme';  // <-- this import is possible without relative path due
                    //     to the "styleIncludePaths" in ng-package.json.

:host {
  border-radius: var(--some-size-variable);
  color: var(--some-color-variable);
}

Then, in the consuming application, the variables can be overwritten in a global scss file:

@import '~mylib/scss/mytheme'; 

$main-color-of-consuming-application: #ff0000;

:root {
  --some-size-variable: 4px;
  --some-color-variable: #{$main-color-of-consuming-application};
}

Upvotes: 3

paddotk
paddotk

Reputation: 1440

What I have done in my library for things like this, is adding a provider component. This is a component that you can put at the top of your application, and by adding inputs to it (maybe from a local libVars.js or something) you can set the variables in the ngOnInit of the provider.

// provider.component
const root: any = document.querySelector(':root');
root.style.setProperty(`--primary-color`, this.myColorVar);
// app.component.html
<provider myColorVar="red">
  // app contents
</provider>

Additionally, if you use SCSS, you can assign this dynamically set variable to an SCSS variable like

// style.scss
$myVar: --my-var;

Upvotes: 1

Lucas Moreira
Lucas Moreira

Reputation: 506

You can turn off view encapsulation in your component. That way the styles applied are going to act as a global css file, that is probably the reason why the relationship to the theme file is not being kept

Alternatively you can pass the variables you need in an input to the component, which has the bonus of being explicit in the syntax when you use the component

Upvotes: 1

Related Questions