47

I have been struggling to figure out the best way to dynamically change the background-image attribute in a number of Angular 2 components.

In the following example, I am attempting to set the background-image of a div to an @Input value using [ngStyle] directive:

import {Component, Input} from '@angular/core';
import { User } from '../models';

// exporting type aliases to enforce better type safety (https://github.com/ngrx/example-app)
export type UserInput = User;

@Component({
  selector: 'profile-sidenav',
  styles: [ `
    .profile-image {
      background-repeat: no-repeat;
      background-position: 50%;
      border-radius: 50%;
      width: 100px;
      height: 100px;
    }
  `],
  template: `  
    <div class="profile-image" [ngStyle]="{ 'background-image': url({{image}})">
    <h3>{{ username }}</h3>
  `
})

export class ProfileSidenav {
  @Input() user: UserInput;
  blankImage: string = '../assets/.../camera.png';

  // utilizing "getters" to keep templates clean in 'dumb' components (https://github.com/ngrx/example-app) 
  get username() {
    return this.user.username;
  }
  get image() {
    if (!this.user.image) { return this.cameraImage;
    } else { return this.user.image; }
  }

I don't think the issue is with the observable, since username displays and doing something like <img *ngIf="image" src="{{ image }}"> renders the image. I have to access the background-image attribute because apparently that is the best way to make a circular image, but in general would like to know how to do this.

EDIT:

My original [ngStyle] declaration had unnecessary curly brackets (ngStyle is a directive that can take a variable), and was missing string tags around url() and image. The correct way is (as answered below) is:

<div class="profile-image" [ngStyle]="{'background-image': 'url(' + image + ')'}"></div>`.

As stated in the original edit, a solution can also be achieved with the Renderer class in Angular 2. I have yet to do it but think there should be a way with setElementStylesor something like that. I will try to post an example but would love if someone else showed me (and others) how to for the time being.

0xPingo
  • 2,047
  • 4
  • 19
  • 43

6 Answers6

85

I think that you should use something like that:

<div class="profile-image"
     [ngStyle]="{ 'background-image': 'url(' + image + ')'}">

where image is a property of your component.

See this question:

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Thanks for the response! I tried your suggestion (with an extra curly bracket at the end, and the image didn't render :/. Also tried this and had no luck: `
    `
    – 0xPingo Jun 01 '16 at 19:43
  • Does it have to do with how I have `image` defined? Your example (plus the extra curly bracket) does not cause any errors, but the image still does not render :/. I tried putting `blankImage` in there as well (defined locally instead of through an observable), but had the same result. @Thierry – 0xPingo Jun 01 '16 at 20:04
  • You're welcome! Is the `background-image` style applied to your element? You can see this within the Elements tab of Dev tools... – Thierry Templier Jun 01 '16 at 20:05
  • No, the style is not getting applied @Thierry Templier – 0xPingo Jun 01 '16 at 20:06
  • (But is applied when I defined it in the .profile-image css up top) – 0xPingo Jun 01 '16 at 20:07
  • 2
    Nvm, got it to work. The `blankImage` I was referencing had some blank spaces in the path, so that was causing the issue. – 0xPingo Jun 01 '16 at 20:25
  • 1
    tried editing your response to add the extra curly bracket but it wasn't 6 characters (minimum required). Please edit so I can accept! Thanks ! – 0xPingo Jun 01 '16 at 20:27
  • 1
    See also http://stackoverflow.com/questions/37076867/in-rc-1-some-styles-cant-be-added-using-binding-syntax/37233523#37233523 – Günter Zöchbauer Jun 02 '16 at 05:15
43

You don't need to use NgStyle. You can also do this:

[style.background-image]="'url(' + image + ')'"

See more at How to add background-image using ngStyle (angular2)?

Tharindu Lakshan
  • 3,995
  • 6
  • 24
  • 44
redfox05
  • 3,354
  • 1
  • 34
  • 39
3

redfox05's answer works well since there is no space in the image URL, but by a bit change in code we can make it work again:

<div style.background-image="url('{{image}}')"></div>"
2

The main reason is simple, you declared a global variable as blankImage but in the template you called image instead of blankImage.

Your ts code variable blankImage

blankImage: string = '../assets/.../camera.png';

Your template code variable image

<div class="profile-image" [ngStyle]="{'background-image': 'url(' + image + ')'}"></div>
0

I encountered this same issue and came up with a solution that works for image paths which contain spaces.

Within your component's HTML, add the style as follows where _imageBGPath is a property of your component.

Component HTML

<div [style.background-image]="'url(' + _imageBGPath + ')'">
...
</div>

Within your component declaration, add an input property so that we can run encodeURI on the supplied value to account for spaces.

Component Declaration

@Component({
  selector: 'image-display',
  templateUrl: './imageDisplay.component.html',
  styleUrls: ['./ImageDisplay.component.css'],
  providers: []
})
export class ImageDisplayComponent {
  @Input() set imageBGPath(value: string | undefined) {
    if (value != undefined && value != null) {
      this._imageBGPath = encodeURI(value);
    }
  };

  public _imageBGPath: string = "";

  constructor() {
  }
}

Now when you reference your component, you can supply the path to your image. If supplying inline with the component then you need to enclose it with '' so that angular knows this is a string being supplied and not a variable.

<image-display [imageBGPath]="'assets/Image With Spaces.jpg'"></image-display>
Billy Rudasill
  • 105
  • 2
  • 11
-3

that's wrong

I think you should add:

<div class="profile-image" [ngStyle]="{ 'backgroundImage': url({{image}})">

Regards

Amir.S
  • 719
  • 8
  • 15
  • 1
    the RHS part already contains an expression, and you are adding another expression {{image}} into that. This will trigger an error. – Joseph Jojo John Aug 12 '20 at 21:10