anglejs: ng-src äquivalent für Hintergrundbild: url (…)


150

In anglejs haben Sie das Tag ng-src, das den Zweck hat, dass Sie keinen Fehler für eine ungültige URL erhalten, bevor angularjs die zwischen {{und platzierten Variablen auswerten kann }}.

Das Problem ist, dass ich einige DIVs mit einem background-imageSatz auf eine URL verwende. Ich mache das wegen der hervorragenden CSS3-Eigenschaft, background-sizedie das Bild auf die exakte Größe des DIV zuschneidet.

Das einzige Problem ist, dass ich viele Fehler erhalte, genau aus dem gleichen Grund, aus dem sie ein ng-src-Tag erstellt haben: Ich habe einige Variablen in der URL und der Browser glaubt, dass das Bild nicht existiert.

Mir ist klar, dass es eine Möglichkeit gibt, ein Rohöl zu schreiben {{"style='background-image:url(myVariableUrl)'"}}, aber das scheint "schmutzig" zu sein.

Ich habe viel gesucht und kann nicht den richtigen Weg finden, dies zu tun. Meine App wird aufgrund all dieser Fehler zu einem Chaos.

Antworten:


200

ngSrcist eine native Direktive, daher möchten Sie anscheinend eine ähnliche Direktive, die den background-imageStil Ihres Divs ändert .

Sie könnten Ihre eigene Direktive schreiben, die genau das tut, was Sie wollen. Beispielsweise

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

Was Sie so aufrufen würden

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

JSFiddle mit süßen Katzen als Bonus: http://jsfiddle.net/jaimem/aSjwk/1/


67
Sehr schöne Anweisung; Das einzige Problem ist, dass es keine Interpolation unterstützt. Ich würde es wahrscheinlich so ändern: jsfiddle.net/BinaryMuse/aSjwk/2
Michelle Tilley

1
Danke, es spielt keine Rolle, dass es ohne Interpolation ist, es hat Kätzchen!
Visgean Skeloru

Gibt es Sicherheitsprobleme, wenn Sie aus nicht vertrauenswürdigen Quellen laden?
Aakil Fernandes

Dies funktioniert, aber nur, wenn Ihre Bild-URL bereits definiert ist, verwenden Sie @mythz answer stackoverflow.com/a/15537359/1479680 , um eine besser beobachtbare URL zu erhalten
Magico

229

Dieser arbeitet für mich

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

22
Ich denke, das sollte die akzeptierte Antwort sein. Es ist nicht erforderlich, eine benutzerdefinierte Direktive hinzuzufügen.
Jakob Løkke Madsen

2
Ich habe eine ähnliche Antwort hinzugefügt, nur mit Interpolation
wiherek

1
Es ist schmutziger in dem Sinne, dass eine Richtlinie für alle geeignet ist, überall dort, wo Sie einen dynamischen Hintergrund benötigen. Die erwähnte Frage fühlte sich weniger wiederverwendbar an.
Christian Bonato

Funktioniert nicht in Angular 1.5.8, versucht dennoch, das Bild mit imgURLnicht gesetzt zu laden und versucht es erneut, wenn es imgURLgesetzt wird.
Leroydev

Dies ist falsch, wenn Ihre URL spezielle Variablen wie @% enthält, wird diese unterbrochen.
Efwjames

69

Die obige Antwort unterstützt keine beobachtbare Interpolation (und kostet mich viel Zeit beim Debuggen). Der jsFiddle-Link im Kommentar von @BrandonTilley war die Antwort, die für mich funktioniert hat. Ich werde sie hier zur Aufbewahrung erneut veröffentlichen:

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

Beispiel mit Controller und Vorlage

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

Vorlage :

Verwenden Sie in Vorlage wie folgt:

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

oder so:

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

40

Es ist auch möglich, so etwas zu tun mit ng-style:

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

die nicht versuchen würde, ein nicht vorhandenes Bild abzurufen.


2
@sqren sieht dies auch, wenn Sie eine neuere Version von Angular (1.1.5 und höher) verwenden: stackoverflow.com/a/12151492/1218080 . Unterstützung für einen tatsächlichen ternären Operator in Ansichten wurde hinzugefügt.
Holographisches Prinzip

Eine einfache Verkettung von Zeichenfolgen wie diese funktionierte für mich beim Bereichsobjekt anstelle der Interpolation.
Shardul

25

Ähnlich wie bei Hooblei, nur mit Interpolation:

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

1
Hier hat es nicht funktioniert : <span ng-style="{'background-image': 'url(/styles/images/profile.png)'}" style="background-image: url("");"></span>. @ Hooblei Ansatz funktioniert.
Marcos Lima

Gleiches Ergebnis erhalten :(
Kushal Jayswal

9

Nur eine Frage des Geschmacks, aber wenn Sie lieber direkt auf die Variable oder Funktion zugreifen möchten:

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

anstatt so zu interpolieren:

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

Dann können Sie die Direktive etwas anders definieren, scope.$watchwas $parsefür das Attribut gilt

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

Hier gibt es mehr Hintergrundinformationen: AngularJS: Unterschied zwischen den Methoden $ watch und $ watch


2

@jaime deine Antwort ist in Ordnung. Wenn Ihre Seite jedoch $ http.get enthält, müssen Sie ng-if verwenden

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

in der Fabrik

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

im Controller-Bereich

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

und die Ansicht, wenn Sie das ng-if wie unten verwenden, erhalten Sie das Bild durch Interpolation. Andernfalls können Sie das Bild nicht erhalten, da die Direktive den Wert vor der HTTP-Anforderung erhält.

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

1

Ich habe mit 1,5 Komponenten festgestellt, dass das Abstrahieren des Stils vom DOM in meiner asynchronen Situation am besten funktioniert.

Beispiel:

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

Und in der Steuerung sieht so etwas aus:

this.$onChanges = onChanges;

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

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

0

Da Sie dies erwähnt haben ng-srcund es so aussieht, als ob Sie möchten, dass die Seite vor dem Laden Ihres Bildes vollständig gerendert wird, können Sie die Antwort von jaime so ändern, dass die native Direktive ausgeführt wird, nachdem der Browser das Rendern beendet hat.

Dieser Blog-Beitrag erklärt dies ziemlich gut; Im Wesentlichen fügen Sie den $timeoutWrapper für window.setTimeoutvor der Rückruffunktion ein, in der Sie diese Änderungen am CSS vornehmen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.