为什么这个ng-show ng-hide无效

时间:2014-07-26 08:48:05

标签: angularjs ng-show ng-hide

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

screenshot

7 个答案:

答案 0 :(得分:22)

它不起作用的可能原因是您在子范围内创建 范围属性,而不是覆盖merchantListController中的message属性范围如你所料。

// 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属性。

答案 1 :(得分:8)

显示/隐藏逻辑错误...更改为: ng-hide =&#34;消息&#34;

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

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

ng-hide需要变量何时隐藏,ng-show需要何时显示,因此条件 ng-show =&#34; message&#34; &安培; ng-hide =&#34;!message&#34; 是一样的。

尝试这样做:

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

答案 2 :(得分: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

答案 3 :(得分: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/

答案 4 :(得分:1)

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

只要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();
        });
    }
});

答案 5 :(得分:0)

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

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

调试代码,或添加console.log()跟踪以检查变量的值,并查看执行的内容和不执行的内容。标准调试工作。

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

答案 6 :(得分:-2)

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