angularjs: ng-src équivalent en arrière-plan-image: url(…)

dans angularjs vous avez le étiquette ng-src qui a le but que vous ne recevrez pas une erreur pour une url invalide avant angularjs obtient d'évaluer les variables placées entre {{ et }} .

le problème est que j'utilise beaucoup de DIV avec un background-image défini à une url. Je fais cela en raison de l'excellente propriété CSS3 background-size qui cultive l'image à la taille exacte de la DIV.

Le seul problème est que je reçois beaucoup d'erreurs pour la même raison qu'ils ont créé une balise ng-src: j'ai quelques variables dans l'url et le navigateur pense que l'image n'existe pas.

je me rends compte qu'il y a une possibilité d'écrire un brut {{"style='background-image:url(myVariableUrl)'"}} , mais cela semble 'sale'.

j'ai beaucoup cherché et ne peut pas trouver la bonne façon de le faire. Mon application est en désordre à cause de toutes ces erreurs.

148
demandé sur Chris Seymour 2012-12-09 00:36:50

9 réponses

ngSrc est une directive native, il semble donc que vous vouliez une directive similaire qui modifie le style background-image de votre div.

Vous pouvez écrire votre propre directive qui fait exactement ce que vous voulez. Par exemple

app.directive('backImg', function(){
    return function(scope, element, attrs){
        var url = attrs.backImg;
        element.css({
            'background-image': 'url(' + url +')',
            'background-size' : 'cover'
        });
    };
});​

que vous invoqueriez comme ceci

<div back-img="<some-image-url>" ></div>

JSFiddle avec des chats mignons comme un bonus: http://jsfiddle.net/jaimem/aSjwk/1/

197
répondu jaime 2012-12-08 21:51:12

celui-ci travaille pour moi

<li ng-style="{'background-image':'url(/static/'+imgURL+')'}">...</li>
226
répondu hooblei 2013-05-13 01:37:51

la réponse ci-dessus ne supporte pas l'interpolation observable (et me coûte beaucoup de temps à essayer de déboguer). Le jsfiddle link in @BrandonTilley commentaire était la réponse qui a fonctionné pour moi, que je vais re-post ici pour la conservation:

app.directive('backImg', function(){
    return function(scope, element, attrs){
        attrs.$observe('backImg', function(value) {
            element.css({
                'background-image': 'url(' + value +')',
                'background-size' : 'cover'
            });
        });
    };
});

exemple utilisant le contrôleur et le gabarit

contrôleur:

$scope.someID = ...;
/* 
The advantage of using directive will also work inside an ng-repeat :
someID can be inside an array of ID's 
*/

$scope.arrayOfIDs = [0,1,2,3];

modèle:

utiliser dans le modèle comme suit:

<div back-img="img/service-sliders/{{someID}}/1.jpg"></div>

ou similaire:

<div ng-repeat="someID in arrayOfIDs" back-img="img/service-sliders/{{someID}}/1.jpg"></div>
68
répondu mythz 2016-05-10 19:31:22

il est aussi possible de faire quelque chose comme ça avec ng-style :

ng-style="image_path != '' && {'background-image':'url('+image_path+')'}"

qui ne tenterait pas de récupérer une image non existante.

40
répondu holographic-principle 2013-06-03 16:52:37

semblable à la réponse de hooblei, juste par interpolation:

<li ng-style="{'background-image': 'url({{ image.source }})'}">...</li>
24
répondu wiherek 2014-08-20 20:57:11

juste une question de goût, mais si vous préférez accéder à la variable ou à la fonction directement comme ceci:

<div id="playlist-icon" back-img="playlist.icon">

au lieu d'interpoler comme ceci:

<div id="playlist-icon" back-img="{{playlist.icon}}">

alors vous pouvez définir la directive un peu différemment avec scope.$watch qui fera $parse sur le attribut

angular.module('myApp', [])
.directive('bgImage', function(){

    return function(scope, element, attrs) {
        scope.$watch(attrs.bgImage, function(value) {
            element.css({
                'background-image': 'url(' + value +')',
                'background-size' : 'cover'
            });
        });
    };
})

Il ya plus de fond sur ce ici: AngularJS: différence entre le $ observer et $ watch méthodes

9
répondu kristok 2017-05-23 12:34:39

@jaime votre réponse est très bien. Mais si votre page a le $http.obtenir alors vous devez utiliser ng-si

app.directive('backImg', function(){
    return function($scope, $element, $attrs){
        var url = $attrs.backImg;
        $element.css({
            'background-image': 'url(' + url + ')',
            'background-size': 'cover'
        });
    }
});

à l'usine

app.factory('dataFactory', function($http){
    var factory = {};
    factory.getAboutData = function(){
        return $http.get("api/about-data.json");
    };
    return factory;
});

dans la zone du contrôleur

app.controller('aboutCtrl', function($scope, $http, dataFactory){
    $scope.aboutData = [];
    dataFactory.getAboutData().then(function(response){
        // get full home data
        $scope.aboutData = response.data;
        // banner data
        $scope.banner = {
            "image": $scope.aboutData.bannerImage,
            "text": $scope.aboutData.bannerText
        };
    });
});

et la vue si vous utilisez le ng-si comme ci-dessous, vous obtiendrez l'image par interpolation sinon, vous ne pouvez pas obtenir l'image car la directive obtient la valeur avant la requête HTTP.

<div class="stat-banner"  ng-if="banner.image" background-image-directive="{{banner.image}}">
2
répondu Subhojit Mondal 2017-03-13 04:59:20

j'ai trouvé avec 1.5 composants qui Abstraction le style du DOM pour mieux fonctionner dans ma situation async.

exemple:

<div ng-style="{ 'background': $ctrl.backgroundUrl }"></div>

et dans le contrôleur, quelque chose comme ceci:

this.$onChanges = onChanges;

function onChanges(changes) {
    if (changes.value.currentValue){
        $ctrl.backgroundUrl = setBackgroundUrl(changes.value.currentValue);
    }
}

function setBackgroundUrl(value){
    return 'url(' + value.imgUrl + ')';
}
1
répondu Pat Migliaccio 2017-02-23 14:43:56

puisque vous avez mentionné ng-src et qu'il semble que vous vouliez que la page termine le rendu avant de charger votre image, vous pouvez modifier la réponse de jaime pour exécuter la directive native après le navigateur termine le rendu.

ce billet de blog explique assez bien cela; essentiellement, vous insérez le $timeout wrapper pour window.setTimeout avant la fonction de rappel dans laquelle vous faites ces modifications à la feuille de style CSS.

0
répondu aralar 2015-01-15 04:49:04