web-dev-qa-db-fra.com

AngularJS - le style ng ne met pas à jour la propriété d'arrière-plan css

J'ai un service qui renvoie l'URL de l'image, et il est appelé à l'aide du code suivant:

angular.forEach(results, function (item) {
     item.img = "/images/searchItem.jpg";
     $http.post("https://my.api.com/?id=" + item.id).success(
           function (url) {
               item.img = url;
           });
});

à mon avis, j'avais une image avec l'attribut ng-src, qui fonctionnait parfaitement comme ceci:

<img  ng-src="{{item.img}}">

Ensuite, j'ai décidé d'utiliser plutôt background-image sur un SPAN:

<span ng-style="{'background':'transparent url({{item.img}})'}"></span>

maintenant le flux ne fonctionne que lors de la première exécution, après quoi je peux voir (dans la console) le code HTML suivant

<span ng-style="{'background':'transparent url(http://expertsimages.liveperson.com/images/rating/rate10.gif)'}" style="background-image: url(https://fb.lp-chat.com/images/searchItem.jpg); background-color: transparent; background-position: initial initial; background-repeat: initial initial;"></span>

ce qui indique que la variable a été mise à jour, cependant le html est toujours à son état initial.

J'ai essayé d'appeler apply/digest en cas de succès, mais j'ai eu une erreur $ digest déjà en cours (ce qui a du sens). Le truc, c'est qu'après un résumé normal (par exemple sur d'autres changements d'interface utilisateur) le style est appliqué et je vois la bonne image.

Qu'est-ce que j'oublie ici?

Mise à jour: J'ai créé un violon JS qui illustre ce problème ... ressemble à un bogue dans angular pour moi.

46
Shlomi Schwartz

J'ai aussi rencontré ça. Au lieu d'évaluer avec {{ }}, Utilisez la concaténation chaîne + valeur.

Cela fonctionnera:

<span ng-style="{'background':'transparent url(' + item.img + ')'}"></span>)

Voici une version de travail de votre violon

86
cleversprocket

Cela ne fonctionne pas parce que angular évalue le contenu d'un seul crochet une seule fois et ne localise pas la variable que vous souhaitez lier à l'intérieur de cette chaîne.

Vous pouvez cependant créer votre propre directive en tant que telle:

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

puis utilisez-le dans votre modèle comme ceci:

<div ng-if="vis" class="container" back-img="{{imgSrc}}"></div>

J'ai mis à jour votre violon et il semble bien fonctionner http://jsfiddle.net/dS4pB/3/

12
GillesC

Lorsque vous mettez actuellement à jour votre variable d'étendue, enveloppez-la dans un $timeout appel à Poussez les mises à jour sur votre portée et par la suite sur votre vue, cela fera passer la mise à jour à la prochaine digest en évitant le condensé déjà en cours conflit:

    $timeout(function(){
        $scope.var = value;
    });

Ce fil de question peut vous donner quelques informations utiles concernant apply vs timeout etc

6
SW4

vous êtes probablement confronté au même problème que j'ai rencontré récemment et résolu en utilisant ng-bind.

vérifiez la réponse expliquée dans cette question:

AngularJS: Pourquoi ng-bind est meilleur que {{}} en angulaire?

une fois que j'ai utilisé ng-bind, mon innerhtml a été correctement mis à jour.

1
user429035