大田区から発信するゆるゆる日記

主にITエンジニアに関する備忘録日記。たまに趣味も。何か不備があればコメント頂けると幸いです。Twitterアカウント https://twitter.com/ryuzan03

【Angular】Excelやスプレッドシートのような表を作ってみた⑤【要素(div/input)切り替え(スタイルバインディング)編】

※下記の内容に不備がありましたら、コメント頂けると幸いです。また、下記の内容をご使用頂ける場合は自己責任でお願いします。

【目次】

 

概要

この度、作りたかった表が完成したので、その作業内容を数回に分けて記事にしていきます。

Excelスプレッドシートの足元にも及びません←

 

今回はその記事の第5回目です。

 

少し複雑なデータ構造をループで表示させて、さらにそのデータを個別に変更する処理の方法を知りたい方にオススメの記事です。

 

第1回 mat-table編

第2回 mat-icon編

第3回 デザイン修正編

第4回 mat-button-toggle-group編

・第5回 要素(div/input)切り替え(スタイルバインディング)編

第6回 テキスト修正時のフォント色変更(クラス付与)編

 

完成形

Excel スプレッドシート

 

実装した機能(?)紹介

・ネストがあるデータを表形式で表示

・mat-icon使用

・表1列目固定

・横スクロール

・リスト表示切り替え

・要素(div/input)の切り替え

・テキスト修正後、クラス追加(赤字切り替え)

 

 

要素(div/input)切り替え(スタイルバインディング)編

テーマ

今回はdiv要素とinput要素の表示をスタイルバインディングを使って切り替えていきたいと思います。

display バインディング

 

前提

前回記事の続きになります。

URL

 

型定義は省いています。

 

データ構成です。

今回はデータにユニークキーを増やしています。

data = { column: [ "Camera", "Name", "Gender", "Hobby" ],
left_column: [ "FirstName", "Hobby2"],
right_column: [ "LastName", "Hobby3"],
person: [{
info: { info1: "loud", info2: "big" },
+ details: { "ユニークキー":"abc1", Name: "Taro", Gender: "1", Hobby: "", FirstName: "Taro", LastName: "Tanaka", Hobby2: "", Hobby3: "" }
},
{
+ info: { info1: "", info2: "" },
details: { "ユニークキー":"abc2", Name: "Hanako", Gender: "2", Hobby: "", FirstName: "Hanako", LastName: "Yamada", Hobby2: "", Hobby3: "" }
}]
}

 

なぜindexを使わない?

同じ列名を表示させるテーブルをいくつも表示させる場合に対応させるためです。列名とindexだけでデータを探しても、一意にはならないため複数のデータが見つかってしまいます。

 

person毎にユニークキーを設定しておけば、列名とユニークキーでデータを探すことができるので、indexを使いませんでした。

 

なぜngIfディレクティブを使わない?

今回の備忘録シリーズの中では詳しく触れていないのですが、描画時に前回修正があった場合もテキストを赤字に変更する機能を付けています。

 

テキストを赤字に変更する流れは、

DBからデータ取得→修正の有無確認→修正があった場合はクラス付与

になります。

 

しかし、ngIfディレクティブは要素自体を表示させないため、上記のクラス付与において最初は非表示にさせているinput要素を検索することができず、クラス付与ができなくなるので、今回はngIfディレクティブを使用していません。

 

コード

component.html

<div class="person-table">
・・・・・・
+ <input type='text' [(ngModel)]='person[column]' [style.display]="isVisible[person['ユニークキー'] + column] ? 'inline-block' : 'none'" (blur)="toggleVisible(person['ユニークキー'], column)">
+ <div [style.display]="!isVisible[person['ユニークキー'] + column] ? 'block' : 'none'" (dblclick)="toggleVisible(person['ユニークキー'], column)">
+ {{ person[column] }}
+ </div>
・・・・・・
</div>

<div class="right-person-table">
・・・・・・
+ <input type='text' [(ngModel)]='person[column]' [style.display]="isVisible[person['ユニークキー'] + column] ? 'inline-block' : 'none'" (blur)="toggleVisible(person['ユニークキー'], column)">
+ <div [style.display]="!isVisible[person['ユニークキー'] + column] ? 'block' : 'none'" (dblclick)="toggleVisible(person['ユニークキー'], column)>
+ {{ person[column] }}
+ </div>
・・・・・・
</div>

 

component.ts

+ import { Component, OnInit } from '@angular/core';

export class PersonComponent implements OnInit {

+ isVisible: {};

・・・・・・・・・・

+ ngOnInit() {
+ const value = this.data.person.map(p => {
+ const uniqueKey = p.details['ユニークキー'];
+ Object.keys(p.details).map(column => {
+ const isVisibleKey = uniqueKey + column;
+ this.isVisible = { [isVisibleKey]: false };
+ })
+ });
+ }

・・・・・・・・・・

+ toggleVisible(uniqueKey, column) {
+ const isVisibleKey = uniqueKey + column;
+ this.isVisible = {
+ [isVisibleKey]: !this.isVisible[isVisibleKey]
+ };
+ }

}

 

ポイント

ポイントはpersonのユニークキーとカラム名で作ったKeyとtrue/false判定ができるValueを持ったオブジェクト(isVisible)を作ることです。

 

html側でisVisbleの変更を感知(スタイルバインディング)し、要素(div/input)の表示の切り替えを行ってくれます。

 

また、今回はデータの修正を同時に複数を行わない仕様です。なので、isVisibleオブジェクトで全てのデータの真偽値判定をするプロパティを持っておく必要はなく、データを上書きしていく仕様で問題ありません。

 

 

今後に向けて

次回がラストです。

テキストを修正した時に、クラスを付与してテキストを赤くする機能を実装していきます。

 

 

参考

素晴らしい記事に感謝いたします。

Angular Material UI component library(mat-table)

Angular Material UI component library(mat-button-toggle)