angularjs: ng-src эквивалент для background-image: url (…)

150

В angularjs у вас есть тег ng-src , цель которого состоит в том, чтобы вы не получили ошибку для недействительного URL-адреса до того, как angularjs оценит переменные, расположенные между {{и }}.

Проблема в том, что я использую довольно много DIV с background-imageустановленным на URL. Я делаю это из-за превосходного свойства CSS3, background-sizeкоторое обрезает изображение до точного размера DIV.

Единственная проблема заключается в том, что я получаю много ошибок по той же причине, по которой они создали тег ng-src: у меня есть несколько переменных в URL, и браузер считает, что изображение не существует.

Я понимаю, что есть возможность написать грубое {{"style='background-image:url(myVariableUrl)'"}}, но это кажется «грязным».

Я много искал и не могу найти правильный способ сделать это. Мое приложение становится беспорядком из-за всех этих ошибок.

Джаспер Шульте
источник

Ответы:

200

ngSrcэто нативная директива, так что, похоже, вы хотите подобную директиву, которая изменяет background-imageстиль вашего div .

Вы можете написать свою собственную директиву, которая делает именно то, что вы хотите. Например

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

Который вы бы призвали, как это

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

JSFiddle с милыми кошками в качестве бонуса: http://jsfiddle.net/jaimem/aSjwk/1/

Хайме
источник
67
Очень хорошая директива; Единственная проблема заключается в том, что он не поддерживает интерполяцию. Я, вероятно, изменил
Мишель Тилли
1
Спасибо, не важно, что без интерполяции, у него есть котята!
Visgean Skeloru
Есть ли проблемы с безопасностью, если вы загружаете из ненадежных источников?
Аакил Фернандес
это работает, но только если URL вашего изображения уже определен, используйте @mythz answer stackoverflow.com/a/15537359/1479680, чтобы получить лучший наблюдаемый URL
Magico
229

Этот работает для меня

<li ng-style="{'background-image':'url(/static/'+imgURL+')'}">...</li>
hooblei
источник
22
Я думаю, что это должен быть принятый ответ. Там нет необходимости добавлять пользовательские директивы.
Якоб Лёкке Мадсен
2
Я добавил ответ, похожий на этот, просто используя интерполяцию
wiherek
1
Это грязнее, в том смысле, что директива подходит всем, везде, где вам нужен динамический фон. Упомянутый вопрос это чувствовал меньше повторного использования.
Кристиан Бонато
Не работает в Angular 1.5.8, он все еще пытается загрузить изображение с imgURLне установленным и повторяет попытку, когда imgURLбудет установлено.
leroydev
Это неверно, если в вашем URL есть какие-то специальные переменные, такие как @%, он сломается.
efwjames,
69

Приведенный выше ответ не поддерживает наблюдаемую интерполяцию (и затрачивает много времени на отладку). Ссылка jsFiddle в @BrandonTilley комментарий был ответ , который работал на меня, что я снова пост здесь для сохранения:

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

Пример использования контроллера и шаблона

Контроллер:

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

Шаблон:

Используйте в шаблоне так:

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

или так:

<div ng-repeat="someID in arrayOfIDs" back-img="img/service-sliders/{{someID}}/1.jpg"></div>
mythz
источник
40

Также возможно сделать что-то подобное с ng-style:

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

который не будет пытаться получить несуществующее изображение.

Голографический принцип,
источник
2
@sqren также видит это, если вы используете более новую версию Angular (1.1.5 и выше): stackoverflow.com/a/12151492/1218080 . Добавлена ​​поддержка фактического троичного оператора в представлениях.
голографический принцип
простая конкатенация строк, подобная этой, работала для меня на объекте области вместо интерполяции.
Шардул
25

Подобно ответу Хублея, только с интерполяцией:

<li ng-style="{'background-image': 'url({{ image.source }})'}">...</li>
wiherek
источник
1
Он не работает здесь: <span ng-style="{'background-image': 'url(/styles/images/profile.png)'}" style="background-image: url("");"></span>. Подход @hooblei сработал.
Маркос Лима
Получаю
9

просто дело вкуса, но если вы предпочитаете обращаться к переменной или функции напрямую, как это:

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

вместо интерполяции вот так:

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

тогда вы можете определить директиву немного по-другому, с scope.$watchкоторой будете обращаться $parseк атрибуту

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

здесь есть больше предыстории: AngularJS: Разница между методами $ наблюдений и $ наблюдений

kristok
источник
2

@ Возможно, ваш ответ в порядке. Но если на вашей странице есть $ http.get, вы должны использовать ng-if

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

на заводе

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

в области контроллера

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

и представление, если вы используете ng-if, как показано ниже, тогда вы получите изображение путем интерполяции, иначе вы не сможете получить изображение, потому что директива получает значение до HTTP-запроса.

<div class="stat-banner"  ng-if="banner.image" background-image-directive="{{banner.image}}">
Субходжит Мондал
источник
1

Я обнаружил, что с 1.5 компонентами абстрагирование стиля от DOM работает лучше всего в моей асинхронной ситуации.

Пример:

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

А в контроллере что-то нравится так:

this.$onChanges = onChanges;

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

function setBackgroundUrl(value){
    return 'url(' + value.imgUrl + ')';
}
Пэт Мильяччио
источник
0

Так как вы упомянули, ng-srcи кажется, что вы хотите, чтобы страница завершила рендеринг перед загрузкой вашего изображения, вы можете изменить ответ jaime, чтобы запускать нативную директиву после того, как браузер завершит рендеринг.

Этот пост в блоге объясняет это довольно хорошо; по существу, вы вставляете $timeoutобертку для window.setTimeoutперед функцией обратного вызова , в котором вы делаете эти изменения в CSS.

Aralar
источник