18

我在 AngularJS 中有一个简单的应用程序。我想在发出 AJAX 请求时动态显示消息。不幸的是它总是处于隐藏状态,我不知道为什么。

HTML:

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

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

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

截屏

4

7 回答 7

23

它不起作用的可能原因是因为您正在子范围内创建一个的范围属性,而不是message像您预期的那样覆盖 MercerListController 范围中的属性。

// 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;

要解决此问题,请确保通过引用模型上的属性而不是作用域上的属性进行绑定。

HTML

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

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

控制器

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

    });
});

解释

之所以可行,是因为模型my是使用范围继承规则解析的。也就是说,如果my在当前作用域中不存在,则my在父作用域中搜索,直到找到它,或者搜索停止在 $rootScope。一旦找到模型,该message属性就会被覆盖。

于 2014-07-26T12:05:19.397 回答
9

显示/隐藏逻辑是错误的......改变它:ng-hide="message"

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

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

ng-hide 需要变量什么时候隐藏,ng-show 需要变量什么时候显示,所以条件ng-show="message" & ng-hide="!message"是一样的。

尝试这样做:

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

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

仅用于测试...将您的 http 类更改为:

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

            $scope.message   = true;
    }).error(function($data) {
            $scope.message   = false;
    });
于 2014-07-26T08:54:05.427 回答
1
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
于 2016-06-09T11:04:58.530 回答
1

所以,在花时间解决一个 2 岁的问题之后,我会在这里放一些东西。

$scope.apply()是不必要的,并且可能会触发一个错误,说明应用已经在进行中。如果你做得对,你应该很少,或者永远不要调用这个函数。它的主要用途是如果您使用第三方库,则该角度无法监视更改或查看它们的作用,并且您需要手动触发摘要周期。

我建议初始化变量,所以你的控制器看起来像这样(我也将 http 请求提取到服务,并用于then处理响应和错误,因为.success()已被弃用):

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

你可以在这里找到一个工作小提琴:https ://jsfiddle.net/vnjbzf3o/4/

于 2016-09-14T21:26:57.140 回答
1

$scope.$digest() 函数遍历 $scope 对象中的所有监视,以及它的子 $scope 对象(如果有的话)。当 $digest() 遍历手表时,它会为每个手表调用 value 函数。如果 value 函数返回的值与上次调用它时返回的值不同,则调用该 watch 的侦听器函数。

只要 AngularJS 认为有必要,就会调用 $digest() 函数。例如,在执行了按钮单击处理程序之后,或者在 AJAX 调用返回之后(在执行完 done()/fail() 回调函数之后)。

您可能会遇到一些极端情况,AngularJS 不会为您调用 $digest() 函数。您通常会通过注意到数据绑定不会更新显示的值来检测到这一点。在这种情况下,调用 $scope.$digest() 它应该可以工作。或者,您也许可以使用 $scope.$apply()

你可以这样做:

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();
        });
    }
});
于 2018-10-25T10:57:10.487 回答
0

首先,对 $scope.$apply() 的调用是不必要的。

如果show div 从未显示,则表示$scope.message = true;未执行。如果它没有被执行,那意味着你的 AJAX 请求要么不成功,要么$data.status === 'success'永远不会是真的。

调试你的代码,或者添加 console.log() 跟踪来检查你的变量的值,看看什么被执行,什么没有被执行。标准调试工作。

另外,不要在数据变量前面加上 $。$ 通常保留给 Angular 提供的服务。

于 2014-07-26T08:54:27.090 回答
-2

你不需要这一切。只需执行 $scope.$parent.$message = true。正如前面的评论所说,因为您在子范围内,并且原始绑定与父范围变量。但是我相信它的愚蠢语言对父变量和子变量没有共同的记忆。它对我有用,不需要提及 ng-controller。如此疯狂的语言,我为此浪费了一天的时间。然而,感谢所有宝贵的反馈。

于 2016-08-10T15:19:38.223 回答