📜 ⬆️ ⬇️

Creating Angular 2+ components with the ability to switch themes

Hello.

So, let's say we are writing a site on which we need to realize the ability to dynamically switch appearance settings, or, more simply, themes. The theme (theme) will be called a set of properties that determine the appearance of the components (and indeed the whole site).
Suppose we have a one-page application on Angular, and let it be sooo many components, and one of them is ButtonComponent (let's connect the styles from button.component.css to the component), by the example of which we consider the whole mechanism. And you need to realize the ability to switch between two themes: “dark” and “light”, which in our country will differ only in colors (and in general you can put anything in the theme, sizes there, fonts, backgrounds, etc. - all than can be controlled from css).

The original “light” styles looked like this:

.my-button { padding: 10px; font-size: 14px; color: midnightblue; border: 1px solid mdnightblue; background: white; cursor: pointer; } my-button:disabled { pointer-events: none; cursor: default; color: grey; border: 1px solid grey; } 

And for "dark" like this:
')
 .my-button { padding: 10px; font-size: 14px; color: lightblue; border: 1px solid lightblue; background: midnightblue; cursor: pointer; } .my-button:disabled { pointer-events: none; cursor: default; background: grey; color: lightgrey; border: 1px solid lightgrey; } 

Select the common part and save it in a separate file. Let it be there, in the folder with our component, and called button-core.component.css. We will also create one file for each theme and name them, respectively, button-light.component.css and button-dark.component.css. It is already clear what will be in them, but for the sake of completeness I will give the code (who does not want to see it - safely scroll)

button-core.css:

 .my-button { padding: 10px; font-size: 14px; cursor: pointer; } .my-button:disabled { pointer-events: none; cursor: default; } 

button-light.css:

 .my-button { color: midnightblue; border: 1px solid mdnightblue; background: white; } my-button:disabled { color: grey; border: 1px solid grey; } 

button-dark.css:

 .my-button { color: lightblue; border: 1px solid lightblue; background: midnightblue; } .my-button:disabled { background: grey; color: lightgrey; border: 1px solid lightgrey; } 

And in the end, button.component.css itself will look like this:

 @import 'button-core.css' @import 'button-light.css' @import 'button-dark.css' 

Note that you first need to connect the general settings for all themes, then the file with the default theme, and then all the rest.

And now let's see how we can switch from one topic to another, including from the code.

For this we need a selector: host-context (). What is he doing? This selector is looking for a specific css - class, running through all the parents of the element, right up to the root. And if he meets this class, then he applies the described changes. And better we digress from our button a little and consider its work with an example. So let us have two nested components: parent-component and child-component. Their styles are isolated from each other, thanks to Angular, which is good, but we want to sometimes change the look of the child-component depending, say, on whether the cursor hovers over the parent-component (hover event). You could, of course, remove encapsulation with ViewEncapsulation: none, or enter the Input-variable in the child-component for these purposes, but it is much easier and more correct to do this:

 :host-context(.parent-component:hover) .child-component { background: lightcoral; } 

Let's return to our knomke. It is possible to put some style (: host-context (.some-style)) as a marker for the host context, which is what we need to do. Now the light theme files will look like this:

button-light.css:

 :host-context(.light-theme) .my-button { color: midnightblue; border: 1px solid mdnightblue; background: white; } :host-context(.light-theme) my-button:disabled { color: grey; border: 1px solid grey; } 

For dark-theme is similar.

What did we get? Now, we only need one of the parent elements of our button to set a light-theme or dark-theme class, how it will change its appearance by connecting the appropriate classes from our files. Most often, the theme is applied directly to the entire application, which means that the theme should be switched on the root element, for example, on the external div from the app-component (well, or the component that you prescribe in the bootstrap of your application). You can put a theme flag in it and hang it on the external element

[ngClass]="{'light-theme': theme === 'light', 'dark-theme': theme === 'dark'}".

Well, what else to tell further, it seems, everything is clear.

Here is such a simple way to create themes without using css - preprocessors. The method is not perfect, because suggests a lot of copy-paste. With sass preprocessors, the more concise the creation of themes is possible. However, this method also has the right to life.

Thank you all for your attention, I hope someone this will be useful. Based on the article , all the ideas, in general, from there.

Source: https://habr.com/ru/post/333716/


All Articles