Zakaria
Zakaria

Reputation: 108

Global variable in SCSS / SASS with angular components

We are developing a cloud application in angular 5 that will be deployed in a single instance but will be addressed to several customer. The question concerns the management of themes, each customer wants to have his own theme (mainly colors). The architecture (simplified) of the application looks like this:

--src
    --app
    app.component.html
    app.component.scss
    app.component.ts
        -- component1
        comp1.component.html
        comp1.component.scss
        comp1.component.ts
    ...

--scss
    -- current 
        style.scss
        _variables.scsc
    -- customer1
        style.scss
        _variables.scss
    -- customer2
        style.scss
        _variables.scss
    ...

Currently we are deploying by client, so there is no problem, we copy / paste the style in the current before the build.

Each component.scss imports _variables.scss to exploit the variables.

We would like that when a user logs on to the app, we detect the customer and choose the right style, but that the css is generated at compile time.

Is there a way to define global variables that can be modified in runtime and that impacts sub-components?

The solutions I tested:

I do not know if I gave enough detail, thanks for the help.

Upvotes: 2

Views: 3011

Answers (3)

Jacek Lipiec
Jacek Lipiec

Reputation: 432

As there is no proper way to do this; And solution used by Angular theming was not satisfactory to us; we've decided to use custom webpack builder that will compile our style based on the entries we provide. Please note, that we are not using SCSS in angular components explicitly.

"use strict";

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const AutoPrefixer = require("autoprefixer");

module.exports = {
  entry: {
    "modern_style.application": "./src/styles/modern_style.scss",
    "default.application": "./src/styles/default.scss"
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].bundle.css"
    })
  ],
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              ident: "postcss",
              plugins: [AutoPrefixer()],
              sourceMap: true
            }
          },
          {
            loader: "resolve-url-loader"
          },
          {
            loader: "sass-loader",
            options: {
              precision: 8,
              includePaths: [],
              sourceMap: true
            }
          }
        ]
      }
    ]
  }
};

These entry files will have their variables set & customizations applied in each respective entry file, which looks like this:

// Entry file: modern_style.scss
$someVariableToBeUsedOrOverwritten: red;

@import "common/allModulesAreImportedHere"

.customRule{
   //...
}

This generated style, e.g default.bundle.css is then loaded via <link rel="stylesheet" type="text/css" [href]="linkToTheme">

Upvotes: 2

Dmitry
Dmitry

Reputation: 731

There is no way to pass any variables from ts to scss.

All you need is theming. So for each customer you need a global body class whith its own set of variables / classes.

Check out angular material theming docs for example https://material.angular.io/guide/theming#defining-a-custom-theme

Upvotes: 1

Padmapriya Vishnuvardhan
Padmapriya Vishnuvardhan

Reputation: 2166

Mixins will solve your issue.

In the specific customer scss files, you would be holding the specific definition. In the component.scss, you would be using the mixin, which is specific to the customer and it will resolve your issue on both compile and run time.

Upvotes: 0

Related Questions