2017年9月20日水曜日

Angular メモ

Angular アプリケーションプログラミング を読み、要点をメモしています。本文のコピーにならないように、自分の言葉に置き換えて記載しています。


2 章 Angular の基本
2.1 Angular を利用するための準備

2.1.1 Angular アプリケーションの基本構造

npm start コマンド:
Angular 同梱の lite-server が実行されます。この時、TypeScript が JavaScript にトランスパイルされます。
→ 2.3.1 で詳細説明。

xxx.js.map:
ソースマップファイルという。ts ファイルと js ファイルを紐付けています。デバッグ時に ts ファイルでデバッグ実行することができます。

2.2.1 モジュールについて

NgModule:
モジュール定義のためのモジュール

BrowserModule:
アプリケーションをブラウザで実行するためのモジュール

Angular モジュール:
オブジェクトをまとめるための入れ物という概念です。定義されているクラスの中は空でも動作します。(e.g. AppModule)

Angular モジュール = デコレーター + クラス
デコレーターでクラスの構成情報を設定します。


2.2.2 コンポーネント

app.component.ts 一部抜粋
@Component({
  selector: 'my-app',
  template: `<h1>Hello {{name}}</h1>`,
})

→ selector で指定されている要素(my-app)に、template で設定されているテンプレートを適用する、という意味です。変数 name の前後を囲っている {{...}} は Interpolation という構文で、変数を受け取る際の記述方法です。


2.2.3 スタートアップ
main.ts:
アプリケーション起動のための情報を設定しています。

main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
→ app.module から AppModule をインポートし、bootstrapModule メソッドで起動しています。


2.3.1 package.json
アプリケーションの情報、及びアプリケーションで利用するライブラリの情報をまとめています。

scripts コマンドには npm のサブコマンドを定義しています。
{
  "name": "angular-quickstart",
  ...
  "scripts": {
    ...
    "start": "concurrently \"npm run build:watch\" \"npm run serve\"",
    ...
  },

→ npm start と入力すると TypeScript とトランスパイル、lite-server の実行及びアプリケーションのロードが行われますが、実際にはこの package.json のショートカット経由でこれら処理が呼び出されます。


3 データバインディング
3.2 Interpolation(補間)構文
{{...}} 式の内部では、グローバルオブジェクトを参照することができません。
グローバルオブジェクトは、window、document など。

3.3 プロパティバインディング
テンプレート内の HTML 要素のプロパティと、コンポーネントのプロパティ値を紐付けます。ここでは、テンプレートの a タグの href プロパティと、コンポーネントの url プロパティの値を紐付けています。

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `<a [href]="url">go to Yahoo!</a>`,//プロパティバインディング
})
export class AppComponent 
{
  url = "http://www.yahoo.co.jp";
}

→ 出力結果は <a href="http://www.yahoo.co.jp">go to Yahoo!</a> になります。


3.5 イベントバインディング
3.5.1 イベントバインディングの基本

テンプレート内にハンドルするイベントと、イベントに対応するメソッドを紐付けます。ここでは click イベント発生時に myClick() メソッドが呼びされます。

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `<input type="button" [value]="myText" (click)="myClick()"/>`,//イベントハンドリング
})
export class AppComponent 
{
  myText = "クリック前";
  myClick() {
    this.myText = "クリック後";
  }
}

3.5.2 イベント情報の取得

JavaScript では func(evt) の形式でイベント引数を参照することができますが、Angular では $event という表記になります。

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `<input type="button" [value]="myText" (click)="myClick($event)"/>`,//イベント引数
})
export class AppComponent 
{
  myText = "クリック前";
  myClick(e: MouseEvent) {
    this.myText = "クリック後";
    console.log(e.target);
  }
}

実行結果:


















3.5.3 テンプレート参照変数

テンプレート内の要素への参照ができる仕組みです。下記では、input 要素を myInput として参照し、myInput の value プロパティを log メソッドの引数として渡しています。

@Component({
  selector: 'my-app',
  template: `<input #myInput type="text" (input)="log(myInput.value)"/>`,//テンプレート参照変数
})
export class AppComponent 
{
  log(myInput: string) {
    console.log(myInput);
  }
}


input 要素(myInput) に値を入力していくと、input イベントに紐づく log メソッドが呼び出され、コンソールに input 要素の value が出力されています。























なお、テンプレート参照変数は、テンプレート内の別の要素からも参照することができます。input イベントが発生したタイミングで、label 要素に入力文字列が変化していきます。

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <input #myInput type="text" (input)="0"/>
    <label>「{{myInput.value}}」が入力されました。</label>
    `,
})
export class AppComponent 
{
  
}

3.5.4 キーイベントのフィルタリング(keyup.enter イベント)

Angular では Enter キーを押下したタイミングでイベントを処理するというコモンシナリオに対応する keyup.enter イベントを用意してくれています。下記例では、input 要素に値を入力し、Enter を押下したタイミングでコンソールに入力値を出力しています。

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <input #myInput type="text" (keyup.enter)="log($event)"/>
    `,
})
export class AppComponent 
{
  log(e: MouseEvent){
    var target: HTMLTextAreaElement = <HTMLTextAreaElement>e.target;
    console.log(target.value);
  }
}

3.6 双方向バインディング

コンポーネントの持つプロパティと UI 要素と紐付け、コンポーネント側からの変更、もしくは UI 上での変更を受け取り、ビュー ↔ コンポーネントの間で値を同期する機能です。双方向バインディングは他の開発プラットフォーム(例えば、WPF など .NET Framework)にもある、便利な機能ですね。

app.module.ts では、双方向バインディングに必要となる FormsModule をインポートします。

app.module.ts
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';//追加

import { AppComponent }  from './app.component';

@NgModule({
  imports:      [ BrowserModule, FormsModule ],//FormsModule を追加
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

app.component.ts では、テンプレートに form 要素を配置し、その中に双方向バインディングを実装する input 要素を配置します。双方向バインディングには ngModel ディレクティブを利用します。
ここでは 2 つの input 要素を用意し、共通のコンポーネントプロパティを参照します。どちらかの input 要素で値が変更されれば、myValue の変更通知を受けて、もう一方の input 要素の値も自動的に切り替わります。

app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  //template に form 要素を定義し、form 要素内に input 要素を 2 つ定義します。
  //どちらかの input 要素の値を変更すると、もう一方の input 要素の値も自動的に変更されます。
  //両方の input 要素は共に、ngModel を利用して myValue プロパティの値を双方向バインドしています。
  template: `
    <form>
    <input id="myText1" name="myText1" type="text" [(ngModel)]="myValue"/>
    <input id="myText2" name="myText2" type="text" [(ngModel)]="myValue"/>
    </form>
    `
})
export class AppComponent 
{
  myValue = "abc";
}

4. 標準パイプ/ディレクティブ
4.1 パイプ

パイプは、テキストや数値などの値をフォーマットする機能です。よく使われるフォーマットのパターンは Angular で予め用意してくれています。

下記、myText プロパティと myNumber プロパティをパイプで整形しています。
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <p>{{myText | uppercase}}</p>
    <p>{{myText | lowercase}}</p>
    <p>{{myNumber | currency}}</p>
    <p>{{myNumber | currency: 'JPY': true}}</p>
    `
})
export class AppComponent 
{
  myText = "ABCdef";
  myNumber = 198000;
}

実行結果












i18nPlural
評価の値が単数形の場合と、複数形の場合で表示を変更するためのパイプです。次の例では、配列の length に応じて表示文字列を決定しています。また、テンプレート内にバインドするプロパティに、# を含めると、評価された items.length の値を埋め込むことができます。

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <p>{{items.length | i18nPlural: status}}</p>
    `
})
export class AppComponent 
{
  items = ["a", "b", "c", "d", "e"];
  status={
    "=0": "None is selected yet.",
    "=1": "1 item is selected.",
    "other": "# items are selected",
  }
}

実行結果

4.2 ディレクティブ
4.2.1 ngIf
要素の表示、非表示切り替えに利用できます。条件が真のときには表示し、偽のときは非表示にします。


app.module.ts
forms 、FormsModule をインポートします。

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';//追加

import { AppComponent }  from './app.component';

@NgModule({
  imports:      [ BrowserModule, FormsModule ],//FormsModule を追加
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }


app.component.ts
div 要素内に *ngIf="条件" で条件判定を行います。

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <form>
    <label for="show">check the box</label>
      <input id="show" name="show" type="checkbox" [(ngModel)]="isVisible" />
    </form>
    <div *ngIf="isVisible">
    text here...
    </div>
    `
})
export class AppComponent 
{
  isVisible = false;
}


2017年9月16日土曜日

WPF DependencyProperty 簡易サンプル

WPF の DependencyProperty を簡単に実装したサンプルコードです。


C# コード
TextBox クラスを継承した MyTextBox クラスを定義し、string 型の MyProperty を用意します。DependencyProperty.Register メソッドの引数 FrameworkPropertyMetadata から、デフォルト値(今回は null)とデフォルトのバインドモード(今回は TwoWay)を設定します。

public class MyTextBox : TextBox
{
    public string MyProperty
    {
        get { return (string)GetValue(MyPropertyProperty); }
        set { SetValue(MyPropertyProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MyPropertyProperty =
        DependencyProperty.Register(
            "MyProperty", 
            typeof(string), 
            typeof(MyTextBox),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
}


XAML コード
XAML 側では、MyTextBox の MyProperty プロパティを、自身の Text プロパティと、別に用意した TextBox の Text プロパティにバインドしています。

<StackPanel Orientation="Vertical">
    <local:MyTextBox x:Name="myTextBox1" Text="{Binding MyProperty, RelativeSource={RelativeSource Self}, UpdateSourceTrigger=PropertyChanged}" MyProperty="This is my property."/>
    <TextBox Text="{Binding ElementName=myTextBox1, Path=MyProperty, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>

2017年9月15日金曜日

XAMPP MySQL の日本語文字化け対応

データベース作成時に、照合順序として utf8_general_ci を選択すると、日本語を文字化けすることなく扱うことができるようになります。












2017年9月14日木曜日

MySQL JOIN コマンド

incident テーブル
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| id    | int(11)       | NO   | PRI | NULL    |       |
| title | varchar(1000) | YES  |     | NULL    |       |
| owner | int(11)       | YES  |     | NULL    |       |
+-------+---------------+------+-----+---------+-------+

owner テーブル
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| id    | int(11)       | NO   | PRI | NULL    |       |
| name  | varchar(1000) | YES  |     | NULL    |       |
+-------+---------------+------+-----+---------+-------+

incident テーブルと owner テーブルを結合する。
SELECT i.id, i.title, o.name
FROM `incident` AS i
RIGHT JOIN (SELECT id, name FROM `owner`) AS o
ON i.owner = o.id

2017年9月13日水曜日

Require.js によるモジュール管理

Require.js を利用して JavaScript ファイルをまとめて管理してみます。

フォルダとファイルの構成は以下のとおりです。



index.html

ここでは jQuery と require.js を参照します。
jQuery を参照した後に、require.js への参照を加えます。require.js の script タグ内に、data-main 属性を加えて、require.js が管理する JavaScript のエントリポイントを指定します。ここでは js フォルダ配下の main.js をエントリポイントにしますので "js/main" と記載します。

index.html の実装内容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>

    <script src="js/jquery.js" type="text/javascript"></script>
    <script data-main="js/main" src="js/require.min.js" type="text/javascript"></script>
</head>
<body>
    <input id="btn1" type="button" value="get jQuery closed issues"/>
    <ul id="issueList"></ul>
</body>
</html>


js/main.js
require.js で読み込まれるエントリポイントです。この中に処理の実装と読み込む JavaScript ファイルを追加していきます。JavaScript の追加方法は、require メソッドの第一引数に配列で指定していきます。ここでは、'jquery' と 'github/api' の2つが配列要素として指定されています。これら配列要素は .js の拡張子を除いた名前で指定しています。
require メソッドの第二引数には、第一引数で読み込んだ JavaScript ファイルのスクリプトにアクセスすることができます。

js/main.js の実装内容
//require.js の require メソッドを使い、jquery.js ファイル、github フォルダの api.js ファイルをロード
require(['jquery', 'github/api'], function ($, api){
    $(document).ready(function(){

        $("#btn1").click(function(){

            //github/api.js の issues メソッドを呼び出し、github の jQuery の closed issues をダウンロード
            api.issues()
            .done(function(issues){
                
                //ダウンロード結果を出力
                var ul = $("#issueList").empty();
                var array = [];

                for(var i = 0; i < issues.length; i++){
                    array.push($("<li>" + issues[i].id + ": " + issues[i].title + ", " + new Date(issues[i].updated_at) + "</li>"))
                }
                ul.append(array);
            });
        })
    });
});


github/api.js
github にある jQuery の 既に閉じられた issue のコレクションを取得しています。データ取得部分のため、main.js とは別途ファイルを分けて実装しています。

github/api.js の実装内容
define(['jquery'], function($){
    return {
        issues: function(){
            //github の jQuery の closed issues を取得
            return $.getJSON("https://api.github.com/repos/jquery/jquery/issues?state=closed");
        }
    }
});

実行結果:
index.html には main.js のみを参照していますが、require.js が他の JavaScript ファイルも読み込んでくれているので、データ取得やデータ出力も行われました。


2017年9月12日火曜日

node.js の JavaScript モジュール分割

node.js で、ある機能をモジュールとして分割し、アプリケーションから呼び出して利用する例です。

Square 変数に、calc メソッド、print メソッドを実装します。node.js では、読み込まれる JavaScript は node.js 配下のクロージャーとして読み込まれます。このため、外部からこの JavaScript の機能にアクセスするには、module.exports にアクセス用の関数を定義します。ここでは calc メソッドを定義することで、Square 変数の内容を隠蔽化しています。

square.js
var Square = function(){
    var self = this;

    this.calc = function(x, y)
    {
        self.square = x * y;
        return self;
    }

    this.print = function(callback){
        callback(this.square);
        return self;
    }
}

module.exports = {
    calc: function(x, y){
        return new Square(x).calc(x, y);
    }
}


square.js に実装した calc メソッドを使って、面積の計算を行います。

app.js
var Square = require("./square.js");

Square
    .calc(3,5)
    .print(function(result){
        console.log(result);
    });


コンソール画面から、"node app.js" を入力して Enter 押下で実行します。

C:\dev\nodejs\Calc>node app.js
15

出力結果として 15 が得られました。

2017年9月11日月曜日

ASP.NET MVC, ASP.NET Web API でのデータベース接続

ASP.NET MVC、ASP.NET Web API 両方で同じ設定が可能です。

Web.config
App_Data フォルダに DB1.mdb がある状態で、下記のように connectionString を設定します。
<connectionStrings>
  <!--a database file(mdf, ldf) will be created in App_Data folder of the project and attach to SQL Server-->
  <add name="DataContext" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\DB1.mdf;Integrated Security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>

C# コードでは、Web.config で設定した接続文字列を使ってデータベースへ接続します。
var str = ConfigurationManager.ConnectionStrings["DataContext"].ConnectionString;

using (SqlConnection connection = new SqlConnection(str))
{
    connection.Open();
    using (SqlCommand command = new SqlCommand("Select * from dbo.incident;", connection))
    {
        SqlDataReader dr = command.ExecuteReader();
        while (dr.Read())
        {
            Debug.WriteLine(dr.GetValue(1).ToString());
        }
        dr.Close();
    }
}


2017年9月6日水曜日

jQuery promise と deferred の利用例

jQuery promise と deferred の簡単な利用例です。このままコピー & ペーストで動作します。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
</head>
<body>
    <input id="btn1" type="button" value="click me"/>

    <script>
        var task1 = function() {
            var dfd = $.Deferred();
            setTimeout(function() {
                console.log("1つ目の処理");
                dfd.resolve();
            }, 2000);
            return dfd.promise();
        };

        var task2 = function(){
            console.log("2つ目の処理");
        }

        $(function() {
            $('#btn1').on('click', function() {

                // promise を返す関数の後に、then や done で次に実行したい関数をつなげる
                task1().then(task2);
                
                //こういう書き方が多いかも
                // var promise = task1();
                // promise.then(task2);
            });
        });
    </script>
</body>
</html>