32040


Angularを使用して、アコーディオン展開出来るリストを作成しています。  
以下の様な静的なリストでは実現できています。

[code]

    <ons-list-header ng-click="flag = !flag">TITLE</ons-list-header>
    　　<ons-list-item ng-show="flag">item1</ons-list-item>
    　　<ons-list-item ng-show="flag">item2</ons-list-item>
    <ons-list-header ng-click="flag2 = !flag2">TITLE</ons-list-header>
    　　<ons-list-item ng-show="flag2">item1</ons-list-item>
    　　<ons-list-item ng-show="flag2">item2</ons-list-item>
    
[/code]

これを、ng-repeatで動的に作成しようとすると、上手く行きません。  
配列には、[部署、氏名、年齢、性別]が入っています。  
配列を繰り返す中で、部署が同一だった場合、部署が乗ったヘッダーを作成し、クリックした際に展開して表示するにはどうしたらいいでしょうか？

[code]

    <ons-list>
        <div ng-repeat="item in items">
            <ons-list-header ng-click="flag = !flag" ng-if="items[$index - 1].Busho != item.Busho">{{item.Busho}}</ons-list-header>
                <ons-list-item ng-show="flag">{{item.Name}}</ons-list-item>
        </div>
    </ons-list>
    
[/code]

ためしに上記で作成しました。  
全て部署名のリストが完成しました。  
クリックすると全部展開されるとおもいきや、全く反応しません。

よろしくお願いします。


CC BY-SA 3.0
2017-01-20T12:27:46.547
32028
2017-01-21T08:11:57.563
19752
question
javascript monaca angularjs
neRepeatで繰り返すなかで、アコーディオンを作成する


そのままの配列を使用して作成しようとすると難しくなりそうです。  
一度配列を以下のように表示しやすく変換してみると良いかもしれません。

以下のような配列があるとして、部署名をキーとして抜き出した新しい配列を作成する。

[code]

    $scope.items = [
      {Busho: "A部署", Name: "Aさん", Old: 28, Sex: "男性"},
      {Busho: "A部署", Name: "Bさん", Old: 56, Sex: "男性"},
      {Busho: "A部署", Name: "Cさん", Old: 24, Sex: "女性"},
      {Busho: "B部署", Name: "Dさん", Old: 32, Sex: "女性"},
      {Busho: "B部署", Name: "Eさん", Old: 44, Sex: "男性"},
    ]
    
    // 変換処理（本題からは逸れるため変換処理は記載しません。）
    $scope.bushoArray = convertBushoArray($scope.items);
    
    // 変換後の配列
    //  $scope.bushoArray = [
    //    {key: "A部署", array: [
    //      {Busho: "A部署", Name: "Aさん", Old: 28, Sex: "男性"},
    //      {Busho: "A部署", Name: "Bさん", Old: 56, Sex: "男性"},
    //      {Busho: "A部署", Name: "Cさん", Old: 24, Sex: "女性"},
    //    ]},
    //    {key: "B部署", array: [
    //      {Busho: "B部署", Name: "Dさん", Old: 32, Sex: "女性"},
    //      {Busho: "B部署", Name: "Eさん", Old: 44, Sex: "男性"},
    //    ]},
    //  ]
    
[/code]

htmlは以下のような感じでしょうか。  
動作確認しておりませんので、そのままでは動かないかもしれませんが参考になれば。

[code]

    <ons-list>
      <div ng-repeat="bushoItem in bushoArray">
        <ons-list-header ng-click="bushoItem.show = !bushoItem.show" >{{bushoItem.key}}</ons-list-header>
          <ons-list-item ng-show="bushoItem.show" ng-repeat="item in bushoItem.array">{{item.Name}}</ons-list-item>
      </div>
    </ons-list>
    
[/code]

補足:  
変換処理はfilterとして作成すればもっと見やすくなると思います。  
filterの作成方法についても本題とは異なるため記載しませんが、必要あれば別の質問としてあげてください。


CC BY-SA 3.0
2017-01-21T00:52:11.893
32033
2017-01-21T01:01:54.810
2017-01-21T01:01:54.810
20272
20272
32028
answer


`ng-repeat`ごとに`scope`が生成されるため、`ng-
click`の`flag`への代入はそれぞれの`scope`のプロパティとして処理されるようです。

[Ng-click doesn't work inside ng-
repeat](https://stackoverflow.com/questions/16736804/ng-click-doesnt-work-
inside-ng-repeat)

ちなみに、下記のコードを実行すると、各行単位で`flag`が動作していることがわかります。

[code]

    <ons-list>
        <div ng-repeat="item in items">
            <ons-list-header ng-click="flag = !flag">{{item.Busho}} {{flag}}</ons-list-header>
            <ons-list-item ng-show="flag">{{item.Name}}</ons-list-item>
        </div>
    </ons-list>
    
[/code]

次に、掲載したコードのような形で`ons-list`内で`div`タグを使用すると、`Onsen
UI`の`CSS`の関係で表示に問題を抱える場合があります。

データが部署ごとに並んでいることが前提で、コントローラ内で`ons-list-header`,`ons-list-item`を生成すれば、`ng-
repeat`や`CSS`の問題を解決することができます。

**HTML**

[code]

    <ons-list id="list">
    </ons-list>
    
[/code]

**JavaScript**

[code]

    $scope.items = [    // データ
        { Busho: "A部署", Name: "Aさん", Old: 28, Sex: "男性" },
        { Busho: "A部署", Name: "Bさん", Old: 56, Sex: "男性" },
        { Busho: "A部署", Name: "Cさん", Old: 24, Sex: "女性" },
        { Busho: "B部署", Name: "Dさん", Old: 32, Sex: "女性" },
        { Busho: "B部署", Name: "Eさん", Old: 44, Sex: "男性" }
    ];
    $scope.flag = [];   // 部署フラグ
    
    var bushoId = 0;        // 部署ID
    var bushoName = "";     // 部署名
    var elem = document.getElementById("list");
    for (var i = 0; i < $scope.items.length; i++) {
        // 部署が一致しない場合
        if (bushoName != $scope.items[i].Busho) {
            // 部署フラグ設定
            $scope.flag.push(false);
            // 部署ID取得
            bushoId = $scope.flag.length - 1;
            // 部署名取得
            bushoName = $scope.items[i].Busho;
            // ons-list-header追加
            var header = document.createElement("ons-list-header");
            header.setAttribute("ng-click", "flag[" + bushoId + "] = !flag[" + bushoId + "]");
            header.innerHTML = bushoName;
            elem.appendChild(header);
        }
        // ons-list-item追加
        var item = document.createElement("ons-list-item");
        item.setAttribute("ng-if", "flag[" + bushoId + "]");
        item.innerHTML = $scope.items[i].Name;
        elem.appendChild(item);
    }
    ons.compile(elem);
    
[/code]


CC BY-SA 3.0
2017-01-21T08:02:13.797
32040
2017-01-21T08:11:57.563
2017-05-23T12:38:55.307
-1
9566
32028
answer