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

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

今日のワード(9/11)

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

概要

学んだワードを書き留めていく。

特定商取引法(特定商取引に関する法律)

訪問販売や通信販売などのトラブルが生じやすい取引において、購入者が受ける被害を防止するために事業者が守るべき義務を定めた法律。

  • 氏名等の明示の義務付け
  • 不当な勧誘行為の禁止
  • 虚偽・誇大な広告の禁止
  • クーリング・オフ制度の適用

訪問販売・通信販売・電話勧誘販売連鎖販売取引特定継続的役務提供業務提供誘引販売取引・訪問購入の7つの取引について記載がある。

セキュリティバイデザイン

情報セキュリティを企画・設計段階から確保するための方策。

  • 手戻りが少ない
  • 低コスト
  • 保守性の向上

NISCによると、IoTシステムについてはセキュリティバイデザイン思想で設計・構築・運用することを推奨している。

スプーリング

プリンタなどの低速な入出力装置に対するデータの転送を外部記憶装置(磁気ディスク装置など)を介して実行する機能のこと。

コアコンピタンス経営

他社にはマネのできない、企業独自のノウハウや技術などの強みを核とした経営を行うこと。

投機実行

分岐判断の結果が出る前に分岐先を予測して命令を先行実行していく方式。分岐の予測が正しければ先行実行していた命令で処理継続ができるので、予測の精度が高いほど性能向上が期待できる。

CPUの高速化のために使用されるパイプライン処理で使われる技術。

今日のワード(9/9)

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

概要

学んだワードを書き留めていく。

SOA

Service-Oriented Architecture(サービス指向アーキテクチャ)

アプリケーションをコンポーネント化する手法の一つ。

業務上の一処理に相当するソフトウェアで実現されている昨日や部品を独立したサービスとし、それらを組み合わせ連携させることで全体のシステムを構築する手法、またはそれ自体のこと。

Webサービスやシステム構築の考え方として利用できる。

コンパイラ

人間が書いた(理解できる)ソースコードを一括して機械語に変換するプログラムのこと。

ソースコード→字句解析→構文解析→意味解析→最適化→目的プログラム

関係演算

関係データベースのデータ操作において、ある特定の条件に従い、新しい表を作り出すこと。または関係データベースの集合の操作を体系化したもの。

典型的なものは、射影、選択、結合、商。

関係データベースの操作を内容を表現するために使用できる。

ビットパターン

ビットの1と0の羅列のこと。

今後に向けて

不定期開催。

参考

素晴らしい記事に感謝致します。
SOAとは何だろう?---目次 | 日経クロステック(xTECH)

今日のワード(7/10)

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

概要

学んだワードを書き留めていく。
今日はここ。
インターフェース | TypeScript 日本語ハンドブック | js STUDIO

リテラル

「文字通り」「字義通り」を意味する語。ラテン語のlittera(文字)に由来する。

ソースコードに定められているデータ型の書式で直に記載した値やその書式自体のことをリテラルと呼ぶ。

文字列リテラルやオブジェクトリテラルなどのように使われる。

シグネチャ

シグネチャ(signature)は、署名を意味する。

メソッドや関数の名前や引数の数、型の順序、戻り値の型などの組み合わせのことで、そのメソッドや関数が唯一無二であることを示すものです。プログラミング言語によって、その組み合わせは異なる。

例えば名前が同じメソッドをいくつか定義した際に、シグネチャによってコンパイルなどで明確に識別することができる。

インデックスシグネチャやコールスシグネチャ、コンストラクシグネチャなどのように使われる。

コールバック

コールバック(callback)は、直訳すると「呼び出し返す」を意味する。

プログラム中である関数などを呼び出す際に、途中で他の関数などを指定して実行すること。

途中で実行されるものが関数だった場合(コールバックされる関数)は、コールバック関数と呼んだりする。

メンバ

メンバ(member)とは、構成員や構成要素、一部分、部材などの意味を持つ英単語。

オブジェクト指向プログラミングでは、クラスやオブジェクト、インスタンスの持つ変数や関数などの要素をメンバと呼ぶことがある。

オブジェクトが持つ関数を「メンバ関数」、変数を「メンバ変数」と呼んだりするが、プログラミング言語によっては、関数(メンバ関数)を「メソッド」、変数(メンバ変数)を「プロパティ」と呼ぶことがある。

今後に向けて

学んで書いても、日々使わないと覚えられないジレンマ。

次はここから。
クラス | TypeScript 日本語ハンドブック | js STUDIO

参考

素晴らしい記事に感謝致します。
TypeScript プログラミング - オブジェクト型 - オブジェクト型リテラル

【Typescript/交差型/分割代入】分からなかったコードの解説

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

【目次】

概要

前回の記事で悩んだコードについて解説していきます。

const { tab } = event.composedPath().find((ele: any) =>
ele.tagName === 'ION-TAB-BUTTON') as EventTarget & { tab: string };

【Ionic/Angular】ion-tabsでページ遷移時に前データが残る場合の対処法【When used with Angular's router】 - 大田区から発信するゆるゆる日記


コード解説

疑問点

左辺の書き方でどうなるのかが分かりませんでした。

const { tab }


まずは代入する側の解説

event.composedPath().find((ele: any) =>
ele.tagName === 'ION-TAB-BUTTON') as EventTarget

eventはテンプレート側からクリックイベントで取得したものです。
composedPathはイベントから取得したノードを順番に含む配列を取得しています。
そして、取得したいtagNameを配列から取得し、as EventTargetで型キャスト(型アサーション)を行っています。

& { tab: string };

先ほどのEventTargetで定義ができていないtabプロパティを定義します(交差型)


左辺の解説

const { tab }

これは分割代入構文です。
右辺にある配列やオブジェクトから値を取り出して、左辺の変数に代入(変数宣言)します。

スプレッド構文と一緒に使うとさらに幸せになりそうです。
【JavaScript】スプレッド構文の便利な使い方まとめ - Qiita


今後に向けて

スプレッド構文や分割代入構文を使って、オブジェクトの部分更新を行う記事を書きたいと思います。


参考

素晴らしい記事に感謝致します。
Event.composedPath() - Web APIs | MDN
EventTarget - Web API | MDN Type Assertion(型アサーション) - TypeScript Deep Dive 日本語版 TypeScriptの型入門 - Qiita
分割代入 - JavaScript | MDN

【Ionic/Angular】ion-tabsでページ遷移時に前データが残る場合の対処法【When used with Angular's router】

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

【目次】

概要

今回の記事はIonicのIssuesに投稿されている内容ですが、私の解釈で大丈夫か不安です(理由は後ほど説明します) Allow to reset tab navigation stack on changing tabs. · Issue #17761 · ionic-team/ionic-framework · GitHub
現在、開発中のアプリはion-tabsでページ遷移を実現しています。また、各tab内でもページ遷移も行うことができます。

この場合、以下の手順でページ遷移を行うと、元ページには前のコンポーネントが残っていると思います。

tab1内でページ遷移→tab2に移動→tab1に移動
➡️tab1にはページ遷移後のコンポーネントが残ったまま


理想とする仕様は、tab1に戻ったらtab1の最初のページが表示されることです。今回はこの仕様を実現するための記事を書いていきます。

ion-tabsでページ遷移後に、前のページの情報が残ってしまう時の対処法

懸念事項や実現方法の考察など

この章は読み飛ばしてもらっても問題ありません。

懸念事項

問題の解決にあたり、頭によぎった不安要素を列挙しておきます。

  • 私自身がion-tabsの構造について完全に理解しきれていない。
  • ネイティブアプリ/Ionicの仕様では、tab移動では前の情報を残しておくのが普通?
  • Ionicの便利な機能を見落としているかもしれない
  • Ionic5では良い解決策が用意されているかもしれない

そもそもtabは1つのページ内を遷移するための機能っぽいので、前の情報が残っているのが普通の仕様なんだと思います。

つまり僕のion-tabsの使い方が邪道ぽいです。。。

実現方法の考察

今回は2パターンを考えていました。
この記事では以下の2の実装をします。

  1. ページ遷移先のURLを指定する
  2. tabのスタックからpopする

1は簡単に実装可能でしたが、ページ遷移した時に前のコンポーネントが一瞬だけ見え不格好になったのでやめました。

手順
  1. ion-tab-buttonでクリックイベントを発火
  2. テンプレート側の情報をコンポーネント側で取得
  3. ion-tabs要素から前のコンポーネント情報をpopする

スタックについて

Ionicのtabやnavigationはスタック(stack)と呼ばれる方法でページ遷移を実現しています。
プッシュ(push)やポップ(pop)についても知っておけば、今回の記事が理解しやすくなると思います。詳しくは以下から。
https://wa3.i-3-i.info/word14717.html ion-tab - Ionic Framework 日本語ドキュメンテーション


ion-tab-buttonにクリックイベント実装

該当する各ion-tab-buttonにクリックイベントを実装します。
また、ion-tabsに参照(ローカル)変数を定義します。

component.html

<ion-tabs #myTabs>
  <ion-tab-bar slot="bottom">

    <ion-tab-button tab="tab1" (click)="popTab($event)">
      <ion-icon name="home"></ion-icon>
      <ion-label>tab1</ion-label>
    </ion-tab-button>

    <ion-tab-button tab="tab2" (click)="popTab($event)">
      <ion-icon name="book"></ion-icon>
      <ion-label>tab2</ion-label>
    </ion-tab-button>

    <ion-tab-button tab="tab3" (click)="popTab($event)">
      <ion-icon name="checkmark-circle"></ion-icon>
      <ion-label>tab3</ion-label>
    </ion-tab-button>

  </ion-tab-bar>
</ion-tabs>



テンプレート側の情報をコンポーネント側で取得

先ほど定義したクリックイベントと参照変数から情報をコンポーネント側で取得します。

component.ts

...
@ViewChild('myTabs', {static: false}) myTabs: IonTabs;
resetStackTabs = ['tab1', 'tab2', 'tab3'];
...
popTab = (event: MouseEvent) => {
  const { tab } = event.composedPath().find((ele: any) =>
  ele.tagName === 'ION-TAB-BUTTON') as EventTarget & { tab: string };
  }
}
...



Tabsのスタックから前情報をポップする

component.ts

...
popTab = (event: MouseEvent) => {
...
    return this.myTabs.outlet.pop(1, tab);
  }
}
...



今後に向けて

以下のコードの解説記事を書こうと思います。

const { tab } = event.composedPath().find((ele: any) =>
ele.tagName === 'ION-TAB-BUTTON') as EventTarget & { tab: string };



参考

素晴らしい記事に感謝致します。
Allow to reset tab navigation stack on changing tabs. · Issue #17761 · ionic-team/ionic-framework · GitHub https://wa3.i-3-i.info/word14717.html
ion-tab - Ionic Framework 日本語ドキュメンテーション

【HTML/Javascript】フロントエンドでCSVデータを出力する方法

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

【目次】

【20/6/26 追記】
この記事の内容だとExcelcsvを開くと文字化けする可能性があります。

この記事の内容+以下のサイトを参考にすると、Excelで開いても文字化けしないcsv(tav)ファイルを作ることができます(サイトのコメント欄も要チェックです)。まあExcel2016以降はUTF-8に対応されたみたいなので、この記事の内容でも問題ないかもですが...
javascript で作成したCSVファイルをエクセルで表示可能にする - Qiita

概要

Angular(フロントエンド)からCSVデータを出力したかったのですが、HTMLとJavascriptだけで簡単に出力ができたので、その備忘録を書きます。

今回のブログのコードはAngular(Typescript)で記述しますが、使用している技術はHTMLとJavascriptの技術になります。ですので、Javascriptを使用されている方も参考にできる記事になっていると思います。

CSVデータ出力方法

処理の流れ

  1. ユーザ(画面)がクリックイベントを発火する
  2. 多次元(2次元)配列でデータを作成
  3. 多次元(2次元)配列のデータをJSON形式に変換し、さらにCSV出力方法を追加
  4. HTMLでa要素を作成
  5. 4のa要素に3のJSON形式のデータとdownload属性を追加する
  6. HTMLドキュメントに5のa要素を追加する
  7. a要素でクリックイベントを発火させる
  8. a要素を破棄する

最終的にJSON形式に変換できればCSV出力はできるので、多次元(2次元)配列ではなくても、オブジェクトデータなどでもCSV出力は可能です。

多次元(2次元)配列を使った理由

2次元配列の構造は以下のような感じです。

var a = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
]


上記のデータのうち1つの要素がCSVの1行になるわけですが、上記データの構造と以下のCSVデータ構造(分かりやすいようにスプレッドシートの画像を載せています)を見比べてみるとどうですか?構造が似ていていませんか? spreadsheet
私は似ているなと思い、データ構造のイメージがしやすかったので、2次元配列を使うことにしました。

多次元(2次元)配列とは?

2つ以上のインデックスが組み合わさっている配列で、配列の中に配列があるイメージです。JavaScriptでは多次元配列という構文は用意されていませんが、多次元配列のように配列を組み合わせても使うことはできます。

詳しくはこちらをご覧ください。


画面とメソッドを作成

component.html

<button (click)="downloadCsv()">CSVダウンロード</button>

component.ts

export class TestComponent {
  downloadCsv() {
    // 以下で記述
  }
}



2次元配列データを作成し、JSON形式に変換

component.ts

downloadCsv() {
  const array: stirng[][] = [
    ['1', '2', '3'],
    ['4', '5', '6'],
    ['7', '8', '9'],
  ]
  // 本来であれば、foerEachやmapなどを使って2次元配列を作ることになるかと思います。その場合は、pushやconcat、new Arrayなどを使うことが多いと思います。
  const csvData: string = this.arrToCSV(array)
}

arrToCSV(array: string[][]): string {
  let csvData = 'data:text/csv;charset=utf-8,'; /// 最初にcsvDataに出力方法を追加しておく
  arr.forEach(a => {
    const row = a.join(',');
    csvData += row + '\r\n';
  });
  return csvData;
}



a要素を作成して、csvを出力

component.ts

downloadCsv() {
...
  const csvData: string = this.arrToCSV(array)

  const encodedUri = encodeURI(csvData); // csvDataをエンコード化する
  const ele = document.createElement('a'); // a要素を作成する

  ele.setAttribute('href', encodedUri);  // a要素に出力データを追加
  ele.setAttribute('download', 'test' + '.csv'); // a要素に出力情報を追加。「'test'」部分は変数を入れることも可能。
  ele.style.visibility = 'hidden';
  document.body.appendChild(ele);
  ele.click(); // HTMLドキュメントに追加したa要素を実行(clickイベント発火)
  document.body.removeChild(ele);
}



今後に向けて

知らないことが無限に出てくる。

参考

素晴らしい記事に感謝致します。
多次元配列 - 配列 - JavaScript入門
クライアント側でCSV生成してダウンロードさせる - ryotah’s blog
【JavaScript】配列データをCSVファイルとして保存できるようにする | あれは魔法だろうか?
Export JSON to CSV file in Angular - GeeksforGeeks

【Ionic/Angular】ion-navでネストがあるナビゲーション機能を実装

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

【目次】

概要

ion-navを使ってrouterを汚さずにページ遷移ができるようにしました。

ion-navのコンポーネントドキュメントだとJavascriptを使うので、私はコンポーネントを使う方法で実装してみました。何故Javascriptを使うのか理由が知りたい...
ion-nav - Ionic Framework 日本語ドキュメンテーション

また、Ionic5から実装されたion-nav-linkも使ってみました(代わりにion-nav-push・back・set-rootがなくなりましたね)
How to Upgrade Your App to Ionic 5 - Ionic AcademyIonic Academy

ちなみに、Angular Materialのmat-treeとion-navを使ってもできそうでしたが、ion-navが良い感じに使いこなせなくて私は途中で挫折しました。あと、ion-tree-listとかあったんですが、公式ではなかったので使うのやめました。ion-treeとかありそうなのにないんですね。

ion-navでネストがあるナビゲーション機能を実装

必要なコンポーネントとデータを作成

ターミナル

$ ionic g component parent
$ ionic g component children
$ ionic g service datas

data.ts

export interface Data {
  name: string;
  children?: Data[];
}


ここのデータ構造は重要です。

datas.ts

import { Data } from './data';

export const DATAS: Data[] = [
  {
    name: 'カテゴリー1',
    children: [
      {name: '子カテゴリー1'},
      {name: '子カテゴリー2'},
    ]
  },
  {
    name: 'カテゴリー2',
    children: [
      {name: '子カテゴリー1'},
      {name: '子カテゴリー2'},
    ]
  },
...
]

datas.service.ts

import { Injectable } from '@angular/core';
import { Data } from './data';
import { DATAS } from './datas';

@Injectable({
  providedIn: 'root'
})
export class DatasService {
  getDatas(): Data[] {
    return DATAS;
  }
}



parentコンポーネントとchildrenコンポーネントを修正

ここが今回最も重要な章です。

プログラミングしていくイメージは、ネストがあるデータやコンポーネントを親(page1・ParentComponent)から子(ChildrenCompnent)に順に渡すイメージです。

その時に使うのがion-navであったりion-nav-linkだったりします。親からデータを受け取る時にはNavParamsオブジェクトを使います。

children.component.ts

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

@Component({
  selector: 'ls-children',
  templateUrl: './children.component.html',
  styleUrls: ['./children.component.scss'],
})
export class ChildrenComponent implements OnInit {
  children: [{[key: string]: string}];

  constructor(private navParams: NavParams) { }

  ngOnInit() {
    this.children = this.navParams.data.children;
  }

}

children.component.html

<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button></ion-back-button>
    </ion-buttons>
    <ion-title>
      子要素
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content  fullscreen>
  <ion-list>
    <ng-container *ngFor="let child of children"> 
      <ion-item button>
        <ion-icon name="arrow-forward" slot="end"></ion-icon>
        <ion-label>
          {{child.name}}
        </ion-label>
      </ion-item>
    </ng-container>
  </ion-list>
</ion-content>


parent.component.ts

import { Component, OnInit } from '@angular/core';
import { NavParams } from '@ionic/angular';
import { ChildrenComponent } from '../children/children.component';

@Component({
  selector: 'ls-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.scss'],
})
export class ParentComponent implements OnInit {
  datas: {[key: string]: any} = {};
  nextPage = ChildrenComponent;

  constructor(private navParams: NavParams) { }

  ngOnInit() {
    this.datas = this.navParams.data;
  }

}

children.component.html

<ion-header>
  <ion-toolbar>
    <ion-title>
      トップ
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content  fullscreen>
  <ion-list>
    <ng-container *ngFor="let data of datas"> 
      <ion-nav-link [component]="nextPage" [componentProps]="{'children': data.children}">
        <ion-item button>
          <ion-icon name="arrow-forward" slot="end"></ion-icon>
          <ion-label>
            {{data.name}}
          </ion-label>
        </ion-item>
      </ion-nav-link>
    </ng-container>
  </ion-list>
</ion-content>



pageにion-navを追加

page1.page.ts

import { Component, OnInit } from '@angular/core';
import { Dictionaries } from 'src/app/shared/models/dictionaries';
import { DatasService } from '../datas.service';
import { ParentComponent } from '../parent/parent.component';

@Component({
  selector: 'app-page1',
  templateUrl: 'page1.page.html',
  styleUrls: ['page1.page.scss']
})
export class Page1Page implements OnInit {
  datas: Datas[];
  navTop: any = ParentComponent;

  constructor(
    private datasService: DatasService,
  ) {}

  ngOnInit() {
    this.getDatas();
  }

  getDatas(): void {
    this.datas = this.datasService.getDatas();
  }

}

page1.page.html

<ion-content [fullscreen]="true">
  <ion-nav [root]="navTop" [rootParams]="datas"></ion-nav>
</ion-content>



応用ヒント

さらにネストが深い場合は、childrenにion-nav-linkを追加して、componentプロパティに自身(children)を反映させる変数を定義しましょう。

example

nextPage = ChildrenComponent


途中でネストを抜け出す場合はngIfを利用します。

example

<ng-container *ngIf="data.children">
...
</ng-container>


もしくは、ネストの深さが一定なら、それだけのコンポーネントを作るのも良さそうです。私はネストが1つだけだったので、parentコンポーネント・childrenコンポーネント・detailコンポーネントの3つで完結させました。


今後に向けて

Ionicは日本語の記事が少ないのでなかなか苦戦してます。。。

少しずつ慣れてはきてるので引き続き英語に負けずに頑張っていきたいと思います。


参考

素晴らしい記事に感謝致します。
ion-nav - Ionic Framework 日本語ドキュメンテーション
ionic-docs/index.html at master · ionic-team/ionic-docs · GitHub
ion-nav-link - Ionic Framework 日本語ドキュメンテーション
How to Upgrade Your App to Ionic 5 - Ionic AcademyIonic Academy