angularjs: equivalente di ng-src per l'immagine di sfondo: url (...)


150

In angularjs hai il tag ng-src che ha lo scopo di non ricevere un errore per un URL non valido prima che angularjs riesca a valutare le variabili tra {{e }}.

Il problema è che uso parecchi DIV con un background-imageset su un url. Lo faccio a causa dell'eccellente proprietà CSS3 background-sizeche ritaglia l'immagine alla dimensione esatta del DIV.

L'unico problema è che ricevo molti errori per lo stesso motivo per cui hanno creato un tag ng-src: ho alcune variabili nell'URL e il browser pensa che l'immagine non esista.

Mi rendo conto che esiste la possibilità di scrivere un greggio {{"style='background-image:url(myVariableUrl)'"}}, ma questo sembra "sporco".

Ho cercato molto e non riesco a trovare il modo giusto per farlo. La mia app sta diventando un disastro a causa di tutti questi errori.

Risposte:


200

ngSrcè una direttiva nativa, quindi sembra che tu voglia una direttiva simile che modifica lo background-imagestile del tuo div .

Potresti scrivere la tua direttiva che fa esattamente quello che vuoi. Per esempio

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

Che invocheresti in questo modo

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

JSFiddle con simpatici gatti come bonus: http://jsfiddle.net/jaimem/aSjwk/1/


67
Direttiva molto bella; l'unico problema è che non supporta l'interpolazione. Probabilmente lo modificherei così: jsfiddle.net/BinaryMuse/aSjwk/2
Michelle Tilley il

1
Grazie, non importa che sia senza interpolazione, ha dei cuccioli!
Visgean Skeloru,

Eventuali problemi di sicurezza con questo se si sta caricando da fonti non attendibili?
Aakil Fernandes,

Questo funziona, ma solo se il vostro URL immagine è già definita, uso @mythz risposta stackoverflow.com/a/15537359/1479680 ad avere un URL più obeservable
Magico

229

Questo funziona per me

<li ng-style="{'background-image':'url(/static/'+imgURL+')'}">...</li>

22
Penso che questa dovrebbe essere la risposta accettata. Non è necessario aggiungere una direttiva personalizzata.
Jakob Løkke Madsen,

2
Ho aggiunto una risposta simile a quella, usando solo l'interpolazione
wiherek

1
È più sporco, nel senso che una direttiva si adatta a tutti, ovunque sia necessario uno sfondo dinamico. La domanda menzionava che sembrava meno riutilizzabile.
Christian Bonato,

Non funziona in Angular 1.5.8, tenta comunque di caricare l'immagine imgURLsenza impostazione e riprova quando imgURLviene impostato.
leroydev,

Ciò non è corretto, se nel tuo URL sono presenti variabili speciali come @%, si interromperà.
efwjames,

69

La risposta sopra non supporta l'interpolazione osservabile (e mi costa molto tempo cercando di eseguire il debug). Il link jsFiddle nel commento di @BrandonTilley è stata la risposta che ha funzionato per me, che ripubblicherò qui per la conservazione:

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

Esempio con controller e modello

Controller:

$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];

Modello :

Utilizzare nel modello in questo modo:

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

o così:

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

40

È anche possibile fare qualcosa del genere con ng-style:

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

che non tenterebbe di recuperare un'immagine inesistente.


2
@sqren lo vedi anche se stai usando una versione più recente di Angular (1.1.5 e successive): stackoverflow.com/a/12151492/1218080 . È stato aggiunto il supporto per un vero operatore ternario nelle viste.
principio olografico

la concatenazione di stringhe semplice come questa ha funzionato per me sull'oggetto scope, anziché sull'interpolazione.
Shardul,

25

Simile alla risposta di hooblei, solo con interpolazione:

<li ng-style="{'background-image': 'url({{ image.source }})'}">...</li>

1
Non ha funzionato qui: <span ng-style="{'background-image': 'url(/styles/images/profile.png)'}" style="background-image: url("");"></span>. L'approccio di @hooblei ha funzionato.
Marcos Lima,

Ottenere lo stesso risultato :(
Kushal Jayswal,

9

solo una questione di gusti ma se preferisci accedere alla variabile o alla funzione direttamente in questo modo:

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

invece di interpolare in questo modo:

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

quindi puoi definire la direttiva in modo leggermente diverso con quello scope.$watchche farà $parsesull'attributo

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'
            });
        });
    };
})

c'è più sfondo su questo qui: AngularJS: differenza tra i metodi $ osservano e $ osservano


2

@jaime la tua risposta va bene. Ma se la tua pagina ha $ http.get allora devi usare ng-if

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

in fabbrica

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

nell'area del controller

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
        };
    });
});

e la vista se usi ng-if come sotto allora otterrai l'immagine per interpolazione altrimenti, non puoi ottenere l'immagine perché la direttiva ottiene il valore prima della richiesta HTTP.

<div class="stat-banner"  ng-if="banner.image" background-image-directive="{{banner.image}}">

1

Ho trovato con 1,5 componenti che astrarre lo stile dal DOM per funzionare al meglio nella mia situazione asincrona.

Esempio:

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

E nel controller, qualcosa di simile a questo:

this.$onChanges = onChanges;

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

function setBackgroundUrl(value){
    return 'url(' + value.imgUrl + ')';
}

0

Dal momento che lei ha citato ng-srce sembra come se si desidera che la pagina per terminare il rendering prima di caricare la vostra immagine, è possibile modificare la risposta di Jaime per eseguire la direttiva originaria dopo le finiture del browser di rendering.

Questo post sul blog lo spiega abbastanza bene; in sostanza, si inserisce $timeoutl'involucro per window.setTimeoutprima che la funzione di callback in cui si fanno queste modifiche al CSS.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.