6971


Angularjs1.3.0

下記のようなlist配列をループで回した際に、div要素をng-clickすることで  
元々非表示になっているspan要素を表示させたいと考えています。  
またクリックされた要素自体はng-hideにより非表示にします。  
本家のstackoverflowに参考になりそうなコードがあったので組み込んでみましたが、そちらは表示されているものを非表示にするといった処理のため希望と異なっていました。

下記のコードを実行すると、クリックされたdiv自体は非表示になるのですが、非表示状態のspanは表示されません。  
どのようにしたらよいでしょうか？

[code]

    <div ng-repeat="(index, value) in list">
        <div ng-hide="showDetails" ng-click="showDetails = ! showDetails">タップすると消えます</div>
        <span ng-hide="true" ng-show="!showDetails">非表示TEST index:{{$index}}</span>
    </div>
    
[/code]

* * *

提示いただいたコードで無事目的の結果が出ました。  
ありがとうございました。

なお、1つ気になった点ですが、こちらに投稿するためにシンプルなコードを載せたのですが、本来の開発中のコードは下記のようにng-
ifディレクティブを使って条件によってDOMの存在自体を制御していたのですが、この場合だとdiv要素が消えたときにspan要素が表示されないです。

[code]

    var app=angular.module("app",[]);
        app.controller("AppCtrl", function($scope){
          $scope.list = [1,2,3,4];
          $scope.view_flag = true;
        });
[/code]

[code]

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
    <div ng-app="app" ng-controller="AppCtrl">
      <div ng-repeat="(index, value) in list">
        <div ng-if="view_flag" ng-hide="showDetails" ng-click="showDetails = ! showDetails">
          タップすると消えます
        </div>
        <span ng-if="view_flag" ng-hide="!showDetails" ng-show="!showDetails">非表示TEST index:{{$index}}</span>
      </div>
    </div>
[/code]

ng-showと併用するとクリックイベント発生させたdiv要素が消えた瞬間に表示させたいspan要素も消えてしまう現象が起きました。  
これが今回はまっていた原因なのですが「ng-if」と「ng-show,ng-hide」の組み合わせで起きているので、そもそもng-
ifによるDOM要素自体の作成・削除がng-showなどによる単なるshow,hideの切り替えと合っていないのでしょうか。

根本的な理解が出来ておらず申し訳ありません。


CC BY-SA 3.0
2015-02-23T10:22:14.803
6964
2015-02-24T15:25:39.640
2015-02-24T15:25:39.640
30
7852
question
javascript angularjs
AngularJSでng-repeat時に、ng-clickしたらhideされている要素を表示したい


span タグの `ng-hide` が true で固定されているために表示されないのだと思います。  
以下の様にすれば span タグを表示状態にすることができます。

このサンプルでは、`ng-hide` が true
であることが直接的な原因だと言うために、元のコードをあまり変えない形でサンプルを示していますが、この回答のコメントでもでている様に ng-hide と
ng-show を同時に使わずに、scope や ng-init などで変数を用意する、undefined を考慮した式にする (
`!!showDetails` で強引に論理値化するとか、冗長だが単純に `(showDetails === undefined) |
showDetails == false` するなど ）といった形にした方がすっきりすると思います。

[code]

    var app=angular.module("app",[]);
    app.controller("AppCtrl", function($scope){
      
      $scope.list = [1,2,3,4];  
      
      });
[/code]

[code]

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
    <div ng-app="app" ng-controller="AppCtrl">
    
    <div ng-repeat="(index, value) in list">
        <div ng-hide="showDetails" ng-click="showDetails = ! showDetails">タップすると消えます</div>
        <span ng-hide="!showDetails" ng-show="!showDetails">非表示TEST index:{{$index}}</span>
    </div>
    </div>
[/code]

* * *

以下の様なディレクティブにしてしまってもいいかもしれません。  
ディレクティブの `transclude` を true にしてあり、テンプレートの span に `ng-transclude`
を指定しているので、`sample` ディレクティブの内容が、テンプレートの span タグの箇所に展開されています。

[code]

    var app=angular.module("app",[]);
    app.controller("AppCtrl", function($scope){
      
      $scope.list = [1,2,3,4];  
      
      });
    
    app.directive("sample", function(){
        return {
          restrict: 'E',
          transclude: true,
          scope: { hide: '='},
          template: '<div ng-hide="hide" ng-click="hide=!hide">タップすると消えます</div><span ng-hide="!hide" ng-transclude></span>'
        };
      });
[/code]

[code]

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
    <div ng-app="app" ng-controller="AppCtrl">
    
    <div ng-repeat="(index, value) in list">
        <sample hide="false">非表示TEST index:{{$index}}</sample>
    </div>
    </div>
[/code]

* * *

# 追記：ng-if を使ったときに ng-click が上手く動かない問題について

追加で質問された `ng-if` を使うと上手くいかない問題ですが、たしか `ng-if` はそれ自身がスコープを作ってしまうため、div と span の
`showDetails` が別ものになってしまっているはずです。`ng-repeat` の各要素で `showDetails`
が独立しているのと同じですね。

なので、 `ng-init` などで共通にアクセスできるオブジェクトを用意するなどの方法をとるといいでしょう。  
例えば以下がサンプルとなります。

[code]

    var app=angular.module("app",[]);
        app.controller("AppCtrl", function($scope){
          $scope.list = [1,2,3,4];
          $scope.view_flag = true;
        });
[/code]

[code]

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
    <div ng-app="app" ng-controller="AppCtrl">
        <div ng-repeat="(index, value) in list" ng-init="myattr={view_flag: true, showDetails: false}">
            <div ng-if="myattr.view_flag" ng-show="!myattr.showDetails" ng-click="myattr.showDetails = !myattr.showDetails">
                タップすると消えます
            </div>
            <span ng-if="myattr.view_flag" ng-show="myattr.showDetails">非表示TEST index:{{$index}}</span>
        </div>
    </div>
[/code]


CC BY-SA 3.0
2015-02-23T12:15:14.650
6971
2015-02-24T13:27:12.213
2015-02-24T13:27:12.213
728
728
6964
answer