span doesn't apply css style when entered via innerHTML
Asked Answered
A

2

5

I have and Angular app, and as part of it I show query result in a div (has ID of JSONContainer).

I wanted to highlight the specific query inside the result, so I used a pipe that searchs the results, and replaces the FIELD:VALUE in the text with:

<span class="highlightSpan">FIELD:VALUE</span>.

I added the following css to the component:

div#JSONContainer span.highlightSpan{
    background-color: rgba(28, 243, 28, 0.5) !important;
    color:red !important;
    padding: 1px;
    margin:1px;
}

I tried adding the same style under .highlightSpan as well, with the same results.

I insert this span and the rest of the text via innerHTML in the containing component, using the 'data' variable, that stores the entire JSON, and 'query' variable that stores the query:

    <div class="col-xs-12" id="JSONContainer"
        [innerHTML]="data | textHighlight:query">
    </div>

(I'm not using string interpolation because the data var is json shaped which I styled using html code,like html br tag, and string interpolation shows only text).

When I point my mouse to the relevent span in google dev tools, I see that the span with the class was created:

span

But the css style is not applyed, and its not even showing in google dev tools:

enter image description here

EDIT: I know it dosen't show (I erased it from the img), but the span is located in the div#JSONContainr, as described.

EDIT 2: Here is the relevant tree:

enter image description here

Why is this happening?

How to make the css style apply?

Thanks!

Avron answered 24/10, 2018 at 13:6 Comment(7)
Is that span actually located inside div#JSONContainer inside the final DOM? We can’t tell that from your screenshot, only that the immediate parent is something different.Tuinal
Can you provide example HTML that is generated?Bedard
Doesn't look like your span is inside div#JSONContainer or you have multiple #JSONContainer (duplicated id's)Township
where's your id #JSONContainer located?Skylight
Hi everyone, I earased the html tree from the google dev screenshot, for privacy reasons, but the span is in the jsonContainer, as described. Also, I don't think that any other style apply, because google dev dosen't show the hightlight style overruled, it doesn't show them at all @Justinas.Avron
Can you try by adding css properties "display: inline-block"? Sometimes its omit with inline element.Asymptomatic
@Hanif, I tried, no effect. Again, it seems that no style is applied.Avron
S
15

This happens because you are adding the span element dynamically and it is not part of your component, therefore the span element is not decorated with component style isolation. When you explore your components rendered html then you see that each element has attribute like _ngcontent-c2 but your span doesn't, so it is not part of that component styling.

You can change your css to:

::ng-deep div#JSONContainer span.highlightSpan

to style descendants of your component (other components or elements added dynamically). Or you can add the styling to your global style so it is not part of that component isolation.

I have created stackblitz demo to simulate your situation.

You can read more about angular view encapsulation.

Stook answered 24/10, 2018 at 13:31 Comment(7)
try ::ng-deep div#JSONContainer .span.highlightSpanStook
I tried, still not it. I don't understand why the style doesn't even appear in google dev tools.Avron
Updated demo to be closer to your situation. What version of angular are you using? When ::ng-deep doesn't work for you then move the styling to global styles.cssStook
I use angular 6. What do you mean adding to global css? with what syntax?Avron
:: ng deep work at last, just needed to fix the typo and remove the dot before "span". Thanks!Avron
cool, didn't notice that dot either, edited answer. the demo was without the dot though ;). With global styles i meant that you could move div#JSONContainer span.highlightSpan to styles.css and it would work, just maybe the selector could be simpler, like .highlightStook
For me, using the ::ng-deep solution worked very wellGrajeda
N
1

In your PIPE you have to import

import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

Add to constructor

  constructor(private sanitizer: DomSanitizer) {
  }

In transform function return

this.sanitizer.bypassSecurityTrustHtml('YOUR HTML');
Nevins answered 24/10, 2018 at 13:12 Comment(3)
Hi. I get and error that tells me that bypassSecurity function is only used when there are <script> tags, and I don't have one in my text. Plus, I don't like the idea that I open my app to XSS attacks.Avron
Other reason if your css style is in the component, try to move it in global css file.Nevins
The above comment (using the global css file, ex. styles.scss) is absolutely the best solution. You don't need to bypass the dom sanitizer, there is no need to set encapsulation: ViewEncapsulation to None in the component decorator and you can still use [innerHtml|="article" to render the html received from your cms. You can add a <div class="cms-article-content"> wrapper around the rendered html to select specific css.Prenomen

© 2022 - 2024 — McMap. All rights reserved.