angularjs: ng-src tương đương với hình nền: url (]


150

Trong angularjs, bạn có thẻ ng-src có mục đích là bạn sẽ không nhận được lỗi cho một url không hợp lệ trước khi angularjs đánh giá các biến được đặt ở giữa {{}}.

Vấn đề là tôi sử dụng khá nhiều DIV với một background-imagebộ thành url. Tôi làm điều này vì thuộc tính CSS3 tuyệt vời background-sizegiúp cắt hình ảnh với kích thước chính xác của DIV.

Vấn đề duy nhất là tôi nhận được rất nhiều lỗi vì lý do chính xác giống như họ đã tạo thẻ ng-src: Tôi có một số biến trong url và trình duyệt cho rằng hình ảnh không tồn tại.

Tôi nhận ra rằng có khả năng viết một cách thô thiển {{"style='background-image:url(myVariableUrl)'"}}, nhưng điều này có vẻ 'bẩn'.

Tôi đã tìm kiếm rất nhiều và không thể tìm ra cách phù hợp để làm điều này. Ứng dụng của tôi đang trở nên lộn xộn vì tất cả các lỗi này.

Câu trả lời:


200

ngSrclà một lệnh gốc, vì vậy có vẻ như bạn muốn một lệnh tương tự sửa đổi background-imagephong cách div của bạn .

Bạn có thể viết chỉ thị của riêng bạn mà làm chính xác những gì bạn muốn. Ví dụ

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

Mà bạn sẽ gọi như thế này

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

JSFiddle với những chú mèo dễ thương như một phần thưởng: http://jsfiddle.net/jaimem/aSjwk/1/


67
Chỉ thị rất hay; vấn đề duy nhất là nó không hỗ trợ nội suy. Tôi có thể sẽ sửa đổi nó như vậy: jsfiddle.net/BinaryMuse/aSjwk/2
Michelle Tilley

1
Cảm ơn bạn, đó không phải là vấn đề mà không có nội suy, nó có mèo con!
Visgean Sk Bacheloru 23/07/13

Bất kỳ vấn đề bảo mật nào với điều này nếu bạn đang tải từ các nguồn không đáng tin cậy?
Aakil Fernandes

điều này hoạt động, nhưng chỉ khi url hình ảnh của bạn đã được xác định, hãy sử dụng @mythz answer stackoverflow.com/a/15537359/1479680 để có một url có thể phục hồi tốt hơn
Magico

229

Cái này làm việc cho tôi

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

22
Tôi nghĩ rằng đây nên là câu trả lời được chấp nhận. Không cần thêm chỉ thị tùy chỉnh.
Jakob Løkke Madsen

2
Tôi đã thêm một câu trả lời tương tự như câu hỏi đó, chỉ sử dụng phép nội suy
wiherek

1
Nó bẩn hơn, theo nghĩa là một lệnh phù hợp với tất cả, ở mọi nơi bạn cần một nền tảng năng động. Các câu hỏi đề cập đến nó cảm thấy ít tái sử dụng.
Christian Bonato

Không hoạt động trong Angular 1.5.8, nó vẫn cố tải hình ảnh mà imgURLkhông được đặt và thử lại khi imgURLđược đặt.
leroydev

Điều này không chính xác, nếu bạn có bất kỳ biến đặc biệt nào như @% trong URL của mình, nó sẽ bị hỏng.
efwjames

69

Câu trả lời trên không hỗ trợ phép nội suy có thể quan sát được (và khiến tôi mất rất nhiều thời gian để cố gắng gỡ lỗi). Các liên kết jsFiddle trong @BrandonTilley bình luận là câu trả lời mà làm việc cho tôi, mà tôi sẽ lại bài vào đây để bảo quản:

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

Ví dụ sử dụng bộ điều khiển và mẫu

Điều khiển:

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

Bản mẫu :

Sử dụng trong mẫu như vậy:

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

hoặc như vậy:

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

40

Cũng có thể làm một cái gì đó như thế này với ng-style:

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

mà sẽ không tìm nạp một hình ảnh không tồn tại.


2
@sqren cũng thấy điều này nếu bạn đang sử dụng phiên bản Angular mới hơn (1.1.5 trở lên): stackoverflow.com/a/12151492/1218080 . Hỗ trợ cho một nhà điều hành ternary thực tế trong lượt xem đã được thêm vào.
nguyên tắc ba chiều

nối chuỗi đơn giản như thế này làm việc cho tôi trên đối tượng phạm vi, thay vì nội suy.
Shardul

25

Tương tự như câu trả lời của hooblei, chỉ với phép nội suy:

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

1
Nó không hoạt động ở đây : <span ng-style="{'background-image': 'url(/styles/images/profile.png)'}" style="background-image: url("");"></span>. Cách tiếp cận @hooblei làm việc.
Marcos Lima

Nhận kết quả tương tự :(
Kushal Jayswal

9

chỉ là vấn đề của hương vị nhưng nếu bạn thích truy cập vào biến hoặc chức năng trực tiếp như thế này:

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

thay vì nội suy như thế này:

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

sau đó bạn có thể định nghĩa chỉ thị một chút khác nhau scope.$watchsẽ làm $parsevới thuộc tính

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ó nhiều nền tảng hơn về vấn đề này ở đây: AngularJS: Sự khác biệt giữa phương pháp $ obs và $ watch


2

@jaime câu trả lời của bạn là tốt. Nhưng nếu trang của bạn có $ http.get thì bạn đã sử dụng ng-if

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

trong nhà máy

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

trong khu vực điều khiển

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

và chế độ xem nếu bạn sử dụng ng-if như bên dưới thì bạn sẽ có được hình ảnh bằng cách nội suy nếu không, bạn không thể có được hình ảnh vì chỉ thị nhận giá trị trước yêu cầu HTTP.

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

1

Tôi đã tìm thấy với 1,5 thành phần trừu tượng hóa kiểu dáng từ DOM để hoạt động tốt nhất trong tình huống không đồng bộ của tôi.

Thí dụ:

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

Và trong bộ điều khiển, một cái gì đó thích điều này:

this.$onChanges = onChanges;

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

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

0

Vì bạn đã đề cập ng-srcvà dường như bạn muốn trang kết thúc hiển thị trước khi tải hình ảnh của mình, bạn có thể sửa đổi câu trả lời của jaime để chạy lệnh gốc sau khi trình duyệt kết thúc kết xuất.

Bài đăng blog này giải thích điều này khá tốt; về cơ bản, bạn chèn $timeouttrình bao bọc cho window.setTimeouttrước hàm gọi lại trong đó bạn thực hiện các sửa đổi đó cho CSS.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.