Search code examples
angularstring-interpolationproperty-binding

Angular string interpolation within a style property not working


Really hung up on this for a while.... shouldn't this work?

style="background-image:url('{{product.imageUrl}}')"

I couldn't reproduce in stack snippet, or Codepen because its angular specific.

I've tried suggestions from this thread to no avail:

https://github.com/angular/angular/issues/8745 https://github.com/angular/angular/issues/8491 https://github.com/angular/angular/issues/8514

It might be because I don't understand where I would put the 'safe' pipe in this situation. Thanks.

template context:

<div *ngIf="product.title"
    class="card">
    <!-- <img *ngIf="product.imageUrl"
        class="card-img-top"
        [src]="product.imageUrl"
        alt="{{product.title}}"> -->

    <div *ngIf="product.imageUrl"
        class="card-img-top scale-img"
        style="background-image:url('{{product.imageUrl}}')"></div>

    <div class="card-body">
        <h5 class="card-title">{{product.title}}</h5>
        <p class="card-text">{{product.price | currency}}</p>


        <div *ngIf="showActions && Cart"
            class="card-footer">


            <button [routerLink]="['/products/', product.$key]"
                class="btn btn-details btn-secondary btn-block">Details</button>


            <button *ngIf="Cart.getQuantity(product) === 0; else updateQuantity"
                (click)="addToCart()"
                class="btn btn-secondary btn-block">Add to Cart</button>

            <ng-template #updateQuantity>
                <product-quantity [product]="product"
                    [cart]="Cart"></product-quantity>
            </ng-template>
        </div>

    </div>

</div>

Solution

  • Usually we solve it by creating custom pipe like:

    html

    [style.backgroundImage]="product.imageUrl | safeStyle"
    

    ts

    @Pipe({
      name: 'safeStyle'
    })
    export class SafeStylePipe {
      constructor(private sanitizer: DomSanitizer) {}
    
      transform(val: string) {
        return this.sanitizer.bypassSecurityTrustStyle(`url('${val}')`);
      }
    }
    

    ===========================================================================

    I don't want to muddy this succinct answer but if you are still having trouble:

    I was getting a "safeStyle not found" error, so I extracted the pipe.

    1. Make another folder called 'pipes'
    2. Make file. I called 'safe-style.ts'
    3. Put this code within (editor wanted me to use PipeTransform):

      import { PipeTransform, Pipe } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser';

      @Pipe({ name: 'safeStyle' }) export class SafeStylePipe implements PipeTransform { constructor(private sanitizer: DomSanitizer) { }

      transform(val: string) { return this.sanitizer.bypassSecurityTrustStyle(url('${val}')); } }

    4. Comment out the @Pipe code and delete the pipe imports you put within the component.

    5. Import into component:

      import { SafeStylePipe } from '../pipes/safe-style';

    6. Declare your pipe in the app module and import it.

      import { SafeStylePipe } from './pipes/safe-style';
      

      ... declarations: [ SafeStylePipe, ]

    7. Should work but if you are still getting that error. I replaced (see template context)...

      <p class="card-text">{{product.price | currency}}</p>
      

    with

        <p class="card-text">{{product.price | safeStyle}}</p>
    

    and somehow that made the error go away then I just changed it back to currency. I think this is a bug. But hey it works now.

    Ng-run Example