Dans angularjs, vous avez le tag ng-src qui a pour but de ne pas recevoir d'erreur pour une URL invalide avant qu'angularjs n'ait à évaluer les variables placées entre {{
et }}
.
Le problème est que j'utilise pas mal de DIV avec un background-image
défini sur une URL. Je le fais en raison de l'excellente propriété CSS3 background-size
qui recadre l'image à la taille exacte de la DIV.
Le seul problème est que je reçois beaucoup d'erreurs pour la même raison, ils ont créé une balise ng-src: j'ai des variables dans l'URL et le navigateur pense que l'image n'existe pas.
Je me rends compte qu'il est possible d'écrire un {{"style='background-image:url(myVariableUrl)'"}}
brut, mais cela semble «sale».
J'ai beaucoup cherché et je ne trouve pas la bonne façon de procéder. Mon application est en train de devenir un gâchis à cause de toutes ces erreurs.
ngSrc
est une directive native, il semble donc que vous souhaitiez une directive similaire modifiant le style background-image
de votre div.
Vous pouvez écrire votre propre directive qui fait exactement ce que vous voulez. Par exemple
app.directive('backImg', function(){
return function(scope, element, attrs){
var url = attrs.backImg;
element.css({
'background-image': 'url(' + url +')',
'background-size' : 'cover'
});
};
});
Que vous invoqueriez comme ceci
<div back-img="<some-image-url>" ></div>
JSFiddle avec des chats mignons en bonus: http://jsfiddle.net/jaimem/aSjwk/1/
Celui-ci fonctionne pour moi
<li ng-style="{'background-image':'url(/static/'+imgURL+')'}">...</li>
La réponse ci-dessus ne prend pas en charge l'interpolation observable (et me coûte beaucoup de temps pour essayer de déboguer). Le commentaire jsFiddle in @BrandonTilley était la réponse qui a bien fonctionné pour moi, et que je vais publier à nouveau ici pour la préservation:
app.directive('backImg', function(){
return function(scope, element, attrs){
attrs.$observe('backImg', function(value) {
element.css({
'background-image': 'url(' + value +')',
'background-size' : 'cover'
});
});
};
});
Exemple utilisant un contrôleur et un modèle
Manette :
$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];
Modèle :
Utilisez dans le modèle comme suit:
<div back-img="img/service-sliders/{{someID}}/1.jpg"></div>
ou comme si:
<div ng-repeat="someID in arrayOfIDs" back-img="img/service-sliders/{{someID}}/1.jpg"></div>
Il est également possible de faire quelque chose comme ceci avec ng-style
:
ng-style="image_path != '' && {'background-image':'url('+image_path+')'}"
qui ne chercherait pas à récupérer une image non existante.
Similaire à la réponse de hooblei, juste avec interpolation:
<li ng-style="{'background-image': 'url({{ image.source }})'}">...</li>
juste une question de goût mais si vous préférez accéder à la variable ou à la fonction directement comme ceci:
<div id="playlist-icon" back-img="playlist.icon">
au lieu d'interpoler comme ceci:
<div id="playlist-icon" back-img="{{playlist.icon}}">
alors vous pouvez définir la directive un peu différemment avec scope.$watch
qui fera $parse
sur l'attribut
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'
});
});
};
})
ici: AngularJS: Différence entre les méthodes $ observe et $ watch
@jaime ta réponse est très bien. Mais si votre page a le $ http.get alors vous avez utiliser ng-if
app.directive('backImg', function(){
return function($scope, $element, $attrs){
var url = $attrs.backImg;
$element.css({
'background-image': 'url(' + url + ')',
'background-size': 'cover'
});
}
});
dans l'usine
app.factory('dataFactory', function($http){
var factory = {};
factory.getAboutData = function(){
return $http.get("api/about-data.json");
};
return factory;
});
dans la zone du contrôleur
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
};
});
});
et la vue si vous utilisez ng-if comme ci-dessous, vous obtiendrez l'image par interpolation, sinon, vous ne pourrez pas obtenir l'image car directive donne la valeur avant la requête HTTP.
<div class="stat-banner" ng-if="banner.image" background-image-directive="{{banner.image}}">
J'ai trouvé avec 1.5 composants que l'abstraction du style dans le DOM était plus efficace dans une situation asynchrone.
Exemple:
<div ng-style="{ 'background': $ctrl.backgroundUrl }"></div>
Et dans le contrôleur, quelque chose aime ça:
this.$onChanges = onChanges;
function onChanges(changes) {
if (changes.value.currentValue){
$ctrl.backgroundUrl = setBackgroundUrl(changes.value.currentValue);
}
}
function setBackgroundUrl(value){
return 'url(' + value.imgUrl + ')';
}
Puisque vous avez mentionné ng-src
et qu'il semble que vous souhaitiez que la page termine le rendu avant de charger votre image, vous pouvez modifier la réponse de jaime pour exécuter la directive native après le navigateur termine le rendu.
Cet article de blog explique cela plutôt bien; En gros, vous insérez le $timeout
wrapper pour window.setTimeout
avant la fonction de rappel dans laquelle vous apportez ces modifications au CSS.