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.