2

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:

  • Set in angular-cli a scss per customer, build and execute script js to modify the html link to css "href = 'assets / {customer} .bundle.css'". It works for global styles, but variables in subcomponents are not updated.

  • Use pure css to declare scope variables: root {--color-primary: gray; } and exploit them in the sub-components .test {color: var (- color-primary)}. Make a JS script that will update all the global variables according to the client. It works, but no equivalent in SCSS? strange

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

3
  • you mean if you define any variable in main.css that is not working in individual components? Commented May 28, 2018 at 16:34
  • yes when I update these variables, it is not reflected in the components in runtime Commented May 29, 2018 at 8:06
  • can you set your viewencapsulation to Emulated Commented May 29, 2018 at 11:43

3 Answers 3

2

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">

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

0

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.

2 Comments

I also tried mixins, but it doesn't allow me to switch theme in runtime. Colors of each components are defined in compile time
You need to define viwencapsulation in your component

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.