web-dev-qa-db-fra.com

Pourquoi ce ng-show ng-hide ne fonctionne pas

J'ai une application simple dans AngularJS. Je souhaite afficher les messages de manière dynamique lorsqu'une demande AJAX est effectuée. Malheureusement, il est toujours caché et je ne comprends pas pourquoi.

HTML:

<div ng-show="message">
    <h2>show</h2>
</div>

<div ng-hide="!message">
    <h2>Hide</h2>
</div>

Contrôleur AngularJS:

function merchantListController($scope, $http, $rootScope, $location, global) {
    $http({
        method: 'POST',
        url: global.base_url + '/merchant/list',
    }).success(function($data) {
        if ($data.status === 'success') {
            $scope.merchants = $data.data;

            $scope.$apply(function(){
                $scope.message = true;
            });
        }
    });
}

screenshot

16
Namal

Cela ne fonctionne probablement pas parce que vous créez une propriéténewscope dans une portée enfant, au lieu de remplacer la propriété message dans la portée de merchantListController comme vous le souhaitiez.

// The following assignment will create a 'message' variable 
// in the child scope which is a copy of the scope variable   
// in parent scope - effectively breaking two-way model binding.
$scope.message = true;

Pour résoudre ce problème, assurez-vous de lier by reference à une propriété de votre modèle plutôt qu'à une propriété de l'étendue.

HTML

<div ng-show="my.message">
   <h2>show</h2>
</div>

<div ng-hide="!my.message">
   <h2>Hide</h2>
</div>

Manette

function merchantListController($scope, $http, $rootScope, $location, global) {

   // Initialize my model - this is important!
   $scope.my = { message: false };

   $http({
        method: 'POST',
        url: global.base_url + '/merchant/list',
    }).success(function($data) {

        if ($data.status === 'success') {
            $scope.merchants = $data.data;

            // modify the 'message' property on the model
            $scope.my.message   = true;
        }

    });
});

Explication

Cela fonctionne parce que le modèle my est en cours de résolution à l'aide de règles d'héritage de portée. En d’autres termes, si my n’existe pas dans l’étendue actuelle, recherchez my dans l’étendue parent jusqu’à ce qu’il soit trouvé ou que la recherche s’arrête à $ rootScope. Une fois le modèle trouvé, la propriété message est écrasée. 

22
pixelbits

La logique afficher/masquer est incorrecte ... changez-la comme suit: ng-hide = "message"

    <div ng-show="message">
       <h2>show</h2>
    </div>

   <div ng-hide="message">
       <h2>Hide</h2>
   </div>

ng-hide a besoin de variables quand se cacher, ng-show en a besoin quand montrer, donc la condition ng-show = "message" & ng-hide = "! message" sont les mêmes. 

Essayez de faire ceci:

    <div ng-show="message">
       <h2>show</h2>
    </div>

   <div ng-show="!message">
       <h2>Hide</h2>
   </div>

Juste pour tester ... changez votre classe http en ceci:

$http({
    method: 'POST',
    url: global.base_url + '/merchant/list',
}).success(function($data) {

            $scope.message   = true;
    }).error(function($data) {
            $scope.message   = false;
    });
8
harishr
Because you did a mistake...

ng-show="message" and ng-hide="!message" both points to the same value..

Correct it as..
<div **ng-show="message"**>
    <h2>show</h2>
</div>

<div **ng-hide="message"**>
    <h2>Hide</h2>
</div>

//or you can do in your way as...

<div **ng-show="message"**>
    <h2>show</h2>
</div>

<div **ng-show="!message"**>
    <h2>Hide</h2>
</div
1
Bunker Boy

Donc, après avoir passé du temps sur une question vieille de 2 ans, je vais mettre quelque chose ici.

$scope.apply() n'est pas nécessaire et provoquerait probablement une erreur indiquant que l'application est déjà en cours. Si vous le faites bien, vous devriez très rarement, ou jamais appeler cette fonction. Son utilisation principale serait si vous utilisiez des bibliothèques tierces, qu'angular ne pouvait pas surveiller les modifications, ni voir ce qu'elles faisaient, et que vous deviez déclencher le cycle de résumé manuellement.

Je conseillerais d'initialiser les variables afin que votre contrôleur ressemble à ceci (j'ai également extrait la requête http d'un service et utilisé then pour gérer les réponses et les erreurs, puisque .success() est obsolète):

function merchantService($http) {
    function post() {
    return $http.get('localhost');
    //Just a dummy $http request, instead of yours.
    //return $http.post(global.base_url + '/merchant/list');
  }

    /*  this is rather implicit, but if you are doing a service like this, 
        you can keep the functions "private" and export an object, that  
        contains the functions you wish to make "public" */

    return {
      post: post
  };
}

function merchantListController($scope, merchantService) {
    /* Initialize the variable, so ng-show and ng-hide 
       have something to work with in the beginning
       rather then just being undefined. */

    $scope.message = false;

    // call the post from the function
    merchantService.post()
  .then(function (response) {

    /* The first then() will hold the response
       if the request was OK */

    console.log(response);
    $scope.merchants = response.data;

    /* Since this then() will be triggered on a successful request
       we are safe to say $scope.message should now be true. */

    $scope.message = true;
  })
  .then(function (error) {

    // The second one is for the failed request.

    console.error(error);
  });
}

var app = angular.module('myApp', []);
app.controller('merchantListController', merchantListController);
app.factory('merchantService', merchantService);

Vous pouvez trouver un violon qui fonctionne ici: https://jsfiddle.net/vnjbzf3o/4/

1
Alex Szabó

La fonction $ scope. $ Digest () parcourt toutes les surveillances de l'objet $ scope et ses objets enfant $ scope (s'il en a). Lorsque $ digest () itère sur les montres, il appelle la fonction de valeur pour chaque montre. Si la valeur renvoyée par la fonction value est différente de la valeur renvoyée la dernière fois qu'elle a été appelée, la fonction d'écoute de cette surveillance est appelée.

La fonction $ digest () est appelée chaque fois que AngularJS le juge nécessaire. Par exemple, après l'exécution d'un gestionnaire de clic de bouton ou après le retour d'un appel AJAX (après l'exécution de la fonction de rappel done ()/fail ()).

Vous pouvez rencontrer certains cas où AngularJS n'appelle pas la fonction $ digest () pour vous. Vous le détecterez généralement en remarquant que les liaisons de données n'améliorent pas les valeurs affichées. Dans ce cas, appelez $ scope. $ Digest () et cela devrait fonctionner. Ou, vous pouvez peut-être utiliser $ scope. $ Apply ()

Vous pouvez faire comme ça: 

HTML 

<div ng-hide="message"> <h2>show</h2> <div>

<div ng-hide="!message"> <h2>Hide</h2> </div>

JS

$scope.message = true;


function merchantListController($scope, $http, $rootScope, $location, global) {
$http({
    method: 'POST',
    url: global.base_url + '/merchant/list',
}).success(function($data) {
    if ($data.status === 'success') {
        $scope.merchants = $data.data;

        $scope.$apply(function(){
            $scope.message = false;
            $scope.$digest();
        });
    }
});
1
Amit Kumar

Tout d'abord, l'appel à $ scope. $ Apply () est inutile. 

Si la variable show n'est jamais affichée, cela signifie que $scope.message = true; n'est pas exécuté. S'il n'est pas exécuté, cela signifie que votre demande AJAX n'aboutit pas ou que $data.status === 'success' n'est jamais vrai.

Déboguez votre code ou ajoutez des traces console.log () pour examiner les valeurs de vos variables et voir ce qui est exécuté et ce qui ne l’est pas. Travail de débogage standard.

Aussi, ne préfixez pas votre variable de données avec un $. Le $ est normalement réservé aux services fournis par Angular.

0
JB Nizet