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;
});
}
});
}
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.
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;
});
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
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/
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();
});
}
});
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.