3

スコープ変数を使用すると、ng-show を問題なく動作させることができます。

(htmlファイルからの抜粋:)

<li ng-show="hasBattery">
  <span>Battery</span>
  <dl>
    <dt>Type</dt>
    <dd>{{phone.battery.type}}</dd>
  </dl>
</li>

次のコントローラ コードを使用すると、正常に動作します。

phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', '$http',
  function($scope, $routeParams, $http) {

    function loadData() {
      // fyi, the ?date nonsense below is to avoid browser cacheing of the json file 
      $http.get('phones/' + $routeParams.phoneId + '.json' + '?' + 
                new Date().getTime()).success(function(data) {
        $scope.phone = data; 
        $scope.hasBattery = !$scope.isEmpty($scope.phone.battery.type);
        // should i call some form of $scope.$apply() here? when i do,
        // i get a digest already in progress error. ng-show seems to 
        // update fine without a call to $apply
      });
    };

    $scope.isEmpty = function(str) {
      var retVal = (typeof(str) === undefined || !str || 0 === str.length);
      alert("isempty: returning " + retVal);
      return retVal;
    };

    $scope.hasBattery = false;
    loadData();
  }
]);

私が言ったように、それはうまくいきます。phone.battery.type が未定義または空白のページを表示すると、ng-show は div を正しく非表示にします。phone.battery.type が空でない文字列であるページを表示すると、ng-show は正しく div を表示します。すべて良い。

これが私の質問です: $scope.hasBattery を仲介者として使用する代わりに、 !isEmpty(...) 呼び出しを ng-show 式で直接使用すると、機能しません。

そのバージョンの私のコードは次のとおりです。

<li ng-show="{{!isEmpty(phone.battery.type)}}">
  <span>Battery</span>
  <dl>
    <dt>Type</dt>
    <dd>{{phone.battery.type}}</dd>
  </dl>
</li>

hasBattery を取り外したコントローラー:

phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', '$http',
  function($scope, $routeParams, $http) {

    function loadData() {
      $http.get('phones/' + $routeParams.phoneId + '.json' + '?' + new Date().getTime()).success(function(data) {
        $scope.phone = data; 
        // no longer do any evaluation of isEmpty here.
        // as before, I'm not calling $scope.$apply() at all
      });
    };

    // same code as before
    $scope.isEmpty = function(str) {
      var retVal = (typeof(str) === undefined || !str || 0 === str.length);
      alert("isempty: returning " + retVal);
      return retVal;
    };

    loadData();
  }
]);

ng-show で表示したい phone.battery.type が空でない文字列であるページをロードすると、div が表示されません。データのロード後に isEmpty が実際に呼び出され、false を正しく返していることがわかります (ng-show の式 !isEmpty(...) が true になるように)。しかし、Angular はこの式の値に対して何もしていないようです!

警告ダイアログ ボックスは、isEmpty が呼び出され、正しく false を返していることを示しています .

何が起こっているのか分かりますか?SO の他の場所で見たように、これは $scope.$apply の問題だと思いますが、式は最新のデータを使用して評価されているようです。

4

1 に答える 1

0

{{ }} 表記は、Angularが中括弧内の式を 1 回だけ評価して使用することを意味しているようです。

昨年かそこらで Angular がブレースの扱いを変更したか、私が使用しているこのブログ エントリが間違っているようです: http://www.whitneyland.com/2013/02/why-does-angularjs-sometimes- use-single-braces-sometimes-double-braces-and-sometimes-no-braces.html

コメント投稿者の Cyril DD、Razah、Mohammad Sepahvand さん、{{ }} を削除すると問題が解決することを指摘していただきありがとうございます。

Angularが式を 2 回以上評価しているように見えることに、私はまだ非常に驚いています。

Angular は、何もしないことがわかっている式を評価するのはなぜですか?

于 2014-09-22T15:15:07.233 に答える