Adding style tags dynamically to a component and then encapsulating the styles again (using Angular)

Currently, I am in the process of upgrading from AngularJS to Angular. Our app is currently a hybrid one being bundled up with webpack instead of just angular cli. Due to this setup, we have encountered issues where our css or scss files are not correctly bundling up and accessible from our upgraded components in styleUrls.

To work around this issue, we have resorted to adding styles in the template using tags. An example of some of the required styles include:

const styles = `
    tr.leader td,
    tr.leader td .personPopup {
        color: ${this.config.LeaderTextColor};
    }

    tr.leader td {
        background-color: ${this.config.LeaderBackgroundColor};
    }

    tr.current-user td,
    tr.current-user td .personPopup {
        color: ${this.config.TableRowCurrentUserTextColor};
    }
`

Users can set colors on the front end which are then loaded through our config for a personalized experience.

However, I have not been able to find a way to include these styles in a style tag within the template while still accessing angular variables like {{config.TableRowCurrentUserTextColor}}. The values do not resolve correctly.

As a workaround, I have managed to achieve this by creating a style tag in the component and appending it into the component during ngOnInit:

const myWidget = document.getElementById(this.widgetId) as HTMLElement;
myWidget.appendChild(styles);

While this method allows me to access my component config variable, it does not properly encapsulate the styles with Emulated view encapsulation. This results in styles potentially leaking out and affecting other components.

Is there any solution to directly access these component variables from style tags in the template? Thus far, I have not found a viable option that works. Alternatively, is there a way to trigger the component to re-encapsulate itself and re-evaluate the styles post-appending them?

Answer №1

To achieve encapsulation, simply enclose the parent class class-wrapper-123 around all your styles as a prefix and ensure that your component is enclosed within a div with the same class. This method will prevent the styles from seeping upwards or downwards in the component hierarchy.

Utilize the > selector to target specific elements without affecting any child components. It may require some effort, but hopefully, your applications will soon transition from hybrid to conventional!

const styles = `
    .class-wrapper-123 > tr.leader > td,
    tr.leader > td > .personPopup {
        color: ${this.config.LeaderTextColor};
    }

    .class-wrapper-123 > tr.leader > td {
        background-color: ${this.config.LeaderBackgroundColor};
    }

    .class-wrapper-123 > tr.current-user > td,
    .class-wrapper-123 > tr.current-user  > td > .personPopup {
        color: ${this.config.TableRowCurrentUserTextColor};
    } `

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using Vue and vue-multiselect to create interactive options based on the selected language

I'm currently developing a Vue website with multilingual support. The chosen language is stored in a Vuex store and accessed through the computed property lang, like so: lang(){ return this.$store.state.lang } I use this lang property in v-if cond ...

Error: Attempting to access the properties `line_items.amount`, `line_items.currency`, `line_items.name`, `line_items.description`, or `line_items` is not allowed

Hi there, I'm currently working on creating an Amazon-inspired platform and I've encountered an error while trying to integrate Stripe with the project. Can anyone provide some assistance? You can refer to the video tutorial I'm using by fol ...

When testing, Redux form onSubmit returns an empty object for values

Is it possible to pass values to the onSubmit handler in order to test the append function? Currently, it always seems to be an empty object. Test Example: const store = createStore(combineReducers({ form: formReducer })); const setup = (newProps) => ...

Required Ionic form field alert

Currently, I am developing a new app using ionic 3 and I am facing an issue with making inputs mandatory in my ionic-alert controller. Despite going through the ionic-component documentation and api documentation, I couldn't find a solution on how to ...

The final thumbnail fails to appear in the visible display (react-responsive-carousel)

I am currently facing an issue with displaying a series of images using react-responsive-carousel. When the images exceed a certain size causing the thumbnail section to become scrollable, the last thumbnail is always out of view. Although I have impleme ...

When an array object is modified in Vue, it will automatically trigger the get method to validate any

One of the challenges I am facing is related to a button component that has a specific structure: <template> <button class="o-chip border-radius" :class="{ 'background-color-blue': theValue.isSelected, ...

I can't figure out why the option value is being displayed as "2: Object" when printing it. Can someone please clarify

Hey there! Currently, I have a UI built using Angular 5 and TypeScript. In one of my components, I have a reactive form with a select box form control in the view. What I'm trying to achieve is that whenever a different option is selected from the sel ...

Tips on eliminating the background of a div nested within another div

<div class="white"> <div class="transparent"> ---- </div> <div class="content"> ---- </div> </div> I am working with a parent div .white that has a white background color. Inside this parent div, there are mul ...

Is it possible to align two buttons side by side on a webpage using only HTML and CSS?

Can you help me figure out how to align two buttons next to each other with some space between them using only css and html? If you take a look at my html code and css code, you'll see that the two buttons are not aligned properly. * { margin: 0 ...

Allow the javascript callback function to complete before proceeding

Utilizing the Google Storage API, I am saving a file in a GCP bucket within an asynchronous function. My objective is to wait until I receive an error or success callback before proceeding with the subsequent lines of code. However, I am encountering the i ...

Getting started with Preact.js: Setting up an auto re-run server similar to React.js

Is there a way to set up a development server for Preact similar to how React operates with npm start? Currently, when I use the same command with Preact, it launches a static server and requires manual restart each time I make changes to my project. Here ...

Leverage the power of rxjs to categorize and organize JSON data within an

I am in need of reformatting my data to work with nested ngFor loops. My desired format is as follows: this.groupedCities = [ { label: 'Germany', value: 'de', items: [ {label: 'Berlin', value: 'Berlin ...

What is the reason behind classList returning 'undefined' unless getElementById is explicitly used?

Why is it that I can't seem to select multiple elements with the same class (using querySelector, querySelectorAll, getElementsByClassName, etc) and use classList to check if just one div contains a specific class? I've come across tutorials tha ...

Step-by-step guide on implementing a real-time data array counter in React js

I am attempting to create a function that continuously generates new data arrays with an increasing counter. Each second, a new array should be added with the next number in sequence. data={[ { x: 1, y: 1 }, { x: 2, y: 2 }, ...

Line numbers in Vue Codemirror

Currently, I'm working on integrating codemirror into my Vue.js application using a library found at https://github.com/surmon-china/vue-codemirror. The issue I'm facing is that even after importing and utilizing the codemirro component, everythi ...

Steps for making a vertical ion-range control

enter image description hereHello there, I'm trying to create a vertical ion-range instead of a horizontal one in capacitor 4. While I successfully created a horizontal range by following the instructions on https://ionicframework.com/docs/api/range, ...

Encountering a Jquery TypeError while trying to update the content on

I am currently working on a project where I aim to create a Java Spring application that functions as follows: upon receiving a GET request, the application sends an HTML page with a form. When the form button is clicked, a POST request containing XML cont ...

Filtering arrays of objects dynamically using Typescript

I am looking to create a dynamic filter for an array of objects where I can search every key's value without specifying the key itself. The goal is to return the matched objects, similar to how the angular material table filters all columns. [ { ...

Leveraging the power of jQuery to capture and recycle a dynamically generated date

Using a jQuery plugin, a list of dates is generated. Implementing moment.js works perfectly fine as shown in this fiddle (http://jsfiddle.net/UJ9z4/). However, when attempting to apply it to the live file with the plugin running, an undefined error is enc ...

Tips for refreshing the <img> tag using a user image

I am currently designing a bootstrap webpage and trying to implement a feature where the user can input an image, which will then be displayed in a preview modal along with some text provided by the user. The modal is functioning correctly. Here is the co ...