目次

フィルタ

バインドされたデータを加工する仕組み。

単一の値用と配列用とがある。

作成したコード

filter.js

(function () {
  var app = angular.module("MemberManager");

  // 性別フィルタ
  // 'male'なら'男'、'female'なら'女'を返す
  app.filter("gender", function () {
    return function (value) {
      if (value == 'male') return '男';
      if (value == 'female') return '女';
      return '?';
    };
  });

  // 性別選別フィルタ
  // 指定した性別だけを通す
  // m : 男性
  // f : 女性
  // b : 両方
  // それ以外 : 何も通さない
  app.filter('genderSelect', function () {
    return function (values, flag) {
      if (!angular.isArray(values)) return values;
      if (flag == 'b') return values;
      var newValues = [];
      angular.forEach(values, function (v) {
        if ((flag == 'm' && v.gender == 'male') ||
          (flag == 'f' && v.gender == 'female'))
          newValues.push(v);
      });
      return newValues;
    }
  });
}());

controllers.js

ListControllerのスコープにflagを追加した。この値を見て、list.htmlで表示する性別を切り替える。

(function () {
  var app = angular.module("MemberManager");

  // アプリケーションコントローラ
  app.controller("AppController", function ($scope, $location) {
    $scope.changeUrl = function (url) {
      $location.path(url);
    }
  });

  // リストコントローラ
  app.controller("ListController", function ($scope, MemberService) {
    $scope.members = MemberService.members;
    $scope.flag = 'm';
  });

  // 新規登録コントローラ
  app.controller("RegistController", function ($scope, MemberService) {
    $scope.name = "jiro";
    $scope.gender = "";
    $scope.mail = "jiro@aaa.jp";
    $scope.bloodtype = "AB";

    // 新規作成が押された
    $scope.registClicked = function () {
      MemberService.regist($scope.name, $scope.gender,
        $scope.mail, $scope.bloodtype);
      $scope.changeUrl('/');
    };
  });

  // 修正コントローラ
  app.controller("ModifyController", function ($scope, $routeParams, MemberService) {
    var m = MemberService.members[$routeParams.num];
    $scope.num = $routeParams.num;
    $scope.mem = new MemberService.Member();
    $scope.mem.id = m.id;
    $scope.mem.name = m.name;
    $scope.mem.gender = m.gender;
    $scope.mem.mail = m.mail;
    $scope.mem.bloodtype = m.bloodtype;

    // 修正ボタンが押された
    $scope.modify = function () {
      MemberService.modify($scope.num, $scope.mem);
      $scope.changeUrl('/');
    };

    // 削除ボタンが押された
    $scope.delete = function () {
      MemberService.delete($scope.num);
      $scope.changeUrl('/');
    };
  });
}());

services.js

(function () {
    var app = angular.module("MemberManager");

    // 会員クラス
    // id : シリアル番号
    // name : 氏名
    // gender : 性別
    // mail : メールアドレス
    // bloodtype : 血液型
    // modified : 修正日時
    var Member = function (id, nm, ge, ma, bt, mo) {
        this.id = id;
        this.name = nm;
        this.gender = ge;
        this.mail = ma;
        this.bloodtype = bt;
        this.modified = mo;
    };

    // 会員サービス
    app.factory("MemberService", function () {
        var ms = {} // サービスの実体
        ms.s_max = 0; // 会員番号の最大値
        ms.members = []; // 会員リスト
        ms.Member = Member; // 会員コンストラクタ

        // 新規会員の登録
        ms.regist = function (nm, ge, ma, bt) {
            ms.members.push(new ms.Member(++ms.s_max,
                nm, ge, ma, bt, new Date()));
        };
        
        // 会員情報の修正
        ms.modify=function(num,mem){
            var m=ms.members[num];
            m.name=mem.name;
            m.gender=mem.gender;
            m.mail=mem.mail;
            m.bloodtype=mem.bloodtype;
            m.modified=new Date();
        }
        
        // 会員情報の削除
        ms.delete=function(num){
            ms.members.splice(num,1);
        };
        
        return ms;
    });
}());

app.js

(function () {
    var app = angular.module("MemberManager", ['ngRoute']);

    // ルーティング
    app.config(function ($routeProvider) {
        $routeProvider
            .when('/', {
                templateUrl: 'list.html',
                controller: 'ListController'
            })
            .when('/regist', {
                templateUrl: 'regist.html',
                controller: 'RegistController'
            })
            .when('/modify/:num', {
                templateUrl: 'modify.html',
                controller: 'ModifyController'
            })
            .otherwise({
                redirectTo: '/'
            });
    });

    // 初期化
    app.run(function (MemberService) {
        MemberService.regist("john", "male", "john@aaaa.jp", "A");
        MemberService.regist("paul", "male", "paul@bbbb.uk", "B");
        MemberService.regist("marry", "female", "marry@cccc.jp", "O");
    });
}());

list.html

表示する性別を選択できるようにした。ng-modelでListControllerのflagと結んでいる。

<p>
  <button ng-click="changeUrl('regist')">新規登録</button>
</p>
<select ng-model="flag">
  <option value='b'>両方</option>
  <option value='m'>男</option>
  <option value='f'>女</option>
  <option value=''>なし</option>
</select>
<table border="1" width="100%">
  <tr>
    <th>ID</th>
    <th>氏名</th>
    <th>性別</th>
    <th>メール</th>
    <th>血液型</th>
    <th>更新日</th>
  </tr>
  <tr ng-repeat="m in members|genderSelect:flag">
    <td>{{m.id}}</td>
    <td><a href="#/modify/{{$index}}">{{m.name}}</a></td>
    <td>{{m.gender|gender}}</td>
    <td>{{m.mail}}</td>
    <td>{{m.bloodtype}}</td>
    <td>{{m.modified | date:'yyyy年MM月dd日 HH時mm分ss秒'}}</td>
  </tr>
</table>

バリデーション

フォームの入力欄に入力されるデータを検証できる機能。

作成したコード

regist.html

<h3>新規登録</h3>
<p>新しい会員情報を入力してください。</p>
<form novalidate name="RF">
  <p>氏名:
    <input type="text" name="NM" ng-model="name" required/>
    <span ng-show="RF.NM.$invalid">※必須項目です</span>
  </p>
  <p>性別:
    <input type="radio" name="gender" value="male" ng-model="gender" />男
    <input type="radio" name="gender" value="female" ng-model="gender" />女</p>
  <p>メール:
    <input type="email" name="MA" ng-model="mail" required/>
    <span ng-show="RF.MA.$invalid">※必須項目です</span>
  </p>
  <p>血液型:
    <select ng-model="bloodtype">
      <option>A</option>
      <option>B</option>
      <option>AB</option>
      <option>O</option>
    </select>
  </p>
  <p>
    <button ng-click="registClicked()" ng-disabled="RF.$invalid">
      新規登録
    </button>
    <button onclick="history.back()">キャンセル</button>
  </p>
</form>

Bootstrap3

導入手順

作成したコード

index.html

<!doctype html>
<html ng-app="MemberManager">

<head>
  <meta charset="utf-8">
  <title>会員管理システム</title>
  <script type="text/javascript" src="vendors/jquery-2.1.4.js"></script>
  <script type="text/javascript" src="vendors/angular.js"></script>
  <script type="text/javascript" src="vendors/angular-route.js"></script>
  <script type="text/javascript" src="vendors/bootstrap-3.3.6-dist/js/bootstrap.js"></script>
  <script type="text/javascript" src="js/app.js"></script>
  <script type="text/javascript" src="js/controllers.js"></script>
  <script type="text/javascript" src="js/services.js"></script>
  <script type="text/javascript" src="js/filters.js"></script>
  <link rel="stylesheet" href="vendors/bootstrap-3.3.6-dist/css/bootstrap.css">
</head>

<body ng-controller="AppController">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h1>会員管理システム <small>Ver 0.1</small></h1>
    </div>
    <div class="panel-body">
      <div ng-view></div>
    </div>
</body>

</html>

list.html

<p>
  <button class="btn btn-default" ng-click="changeUrl('regist')">
    新規登録
  </button>
</p>
<select class="form-control" ng-model="flag">
  <option value='b'>両方</option>
  <option value='m'>男</option>
  <option value='f'>女</option>
  <option value=''>なし</option>
</select>
<table class="table">
  <thead>
    <tr>
      <th>ID</th>
      <th>氏名</th>
      <th>性別</th>
      <th>メール</th>
      <th>血液型</th>
      <th>更新日</th>
    </tr>
  </thead>
  <tr ng-repeat="m in members|genderSelect:flag">
    <td>{{m.id}}</td>
    <td><a href="#/modify/{{$index}}">{{m.name}}</a></td>
    <td>{{m.gender|gender}}</td>
    <td>{{m.mail}}</td>
    <td>{{m.bloodtype}}</td>
    <td>{{m.modified | date:'yyyy年MM月dd日 HH時mm分ss秒'}}</td>
  </tr>
</table>

regist.html

<div class="panel panel-default">
  <div class="panel-heading">
    <h4>新規登録</h4>
  </div>
  <div class="panel-body">
    <p>新しい会員情報を入力してください。</p>
    <form novalidate name="RF">
      <div class="form-group">氏名:
        <input type="text" class="form-control" name="NM" ng-model="name" required/>
        <span ng-show="RF.NM.$invalid">※必須項目です</span>
      </div>
      <div class="form-group">性別:
        <div class="radio-inline">
        <input type="radio" name="gender" value="male" ng-model="gender" />男
        </div>
        <div class="radio-inline">
        <input type="radio" name="gender" value="female" ng-model="gender" />女
        </div>
      </div>
      <div class="form-group">メール:
        <input type="email" class="form-control" name="MA" ng-model="mail" required/>
        <span ng-show="RF.MA.$invalid">※必須項目です</span>
      </div>
      <div class="form-group">血液型:
        <select class="form-control" ng-model="bloodtype">
          <option>A</option>
          <option>B</option>
          <option>AB</option>
          <option>O</option>
        </select>
      </div>
      <p>
        <button class="btn btn-success" ng-click="registClicked()" ng-disabled="RF.$invalid">
          新規登録
        </button>
        <button class="btn btn-default" onclick="history.back()">キャンセル</button>
      </p>
    </form>
  </div>
</div>

modify.html

<div class="panel panel-default">
  <div class="panel-heading">
    <h3>会員情報の修正</h3>
  </div>
  <div class="panel-body">
    <p>会員情報を修正してください。</p>
    <form name="MF">
      <p>ID:{{mem.id}}</p>
      <div class="form-group">氏名:
        <input type="text" class="form-control" name="NM" ng-model="mem.name" required/>
        <span ng-show="MF.NM.$invalid">※必須項目です</span>
      </div>
      <div class="form-group">性別:
        <div class="radio-inline">
          <input type="radio" name="gender" value="male" ng-model="mem.gender" />男
        </div>
        <div class="radio-inline">
          <input type="radio" name="gender" value="female" ng-model="mem.gender" />女
        </div>
      </div>
      <div class="form-group">メール:
        <input type="email" class="form-control" name="MA" ng-model="mem.mail" required/>
        <span ng-show="MF.MA.$invalid">※必須項目です</span>
      </div>
      <div class="form-group">血液型:
        <select class="form-control" ng-model="mem.bloodtype">
          <option>A</option>
          <option>B</option>
          <option>AB</option>
          <option>O</option>
        </select>
      </div>
      <p>
        <button class="btn btn-success" ng-disabled="MF.$invalid" ng-click="modify()">修正</button>
        <button class="btn btn-default" onclick="history.back()">キャンセル</button>
        <button class="btn btn-danger" ng-click="delete()">削除</button>
      </p>
    </form>
  </div>
</div>

サーバとの連携

本研修で使用するサーバーはさくらサーバーである。

ウェブサーバー

URLは、http://seminar-senior.jeez.jp となっている。

これは、中堅SE向け研修用に取得したドメインである。

FTPサーバー

FTPサーバーも同じ名前である。 ユーザ名、パスワードはセミナー中に示す。

DBサーバー

DBとしてMySQLが利用できる。

サーバー名はmysql514.db.sakura.ne.jpであるが、これは上記のウェブサーバーのみからアクセス可能である。

データベース管理ツールはphpMyAdminがここから使用できる。

ユーザ名、パスワードはセミナー中に示す。

作成したコード

service.js

(function () {
  var app = angular.module("MemberManager");

  // 会員クラス
  // id : シリアル番号
  // name : 氏名
  // gender : 性別
  // mail : メールアドレス
  // bloodtype : 血液型
  // modified : 修正日時
  var Member = function (id, nm, ge, ma, bt, mo) {
    this.id = id;
    this.name = nm;
    this.gender = ge;
    this.mail = ma;
    this.bloodtype = bt;
    this.modified = mo;
  };

  // 会員サービス
  app.factory("MemberService", function ($http) {
    var ms = {} // サービスの実体
    ms.s_max = 0; // 会員番号の最大値
    ms.members = []; // 会員リスト
    ms.Member = Member; // 会員コンストラクタ

    // 新規会員の登録
    ms.regist = function (nm, ge, ma, bt) {
      ms.members.push(new ms.Member(++ms.s_max,
        nm, ge, ma, bt, new Date()));
    };

    // 会員情報の修正
    ms.modify = function (num, mem) {
      var m = ms.members[num];
      m.name = mem.name;
      m.gender = mem.gender;
      m.mail = mem.mail;
      m.bloodtype = mem.bloodtype;
      m.modified = new Date();
    }

    // 会員情報の削除
    ms.delete = function (num) {
      ms.members.splice(num, 1);
    };

    // サーバーからデータをロードする
    ms.load = function () {
      $http({
          method: 'post',
          url: 'http://seminar-senior.jeez.jp/fuchida/MemberManager/php/getMember.php'
        })
        .success(function (data, status, headers, config) {
          console.log(data);
          for (var i in data) {
            ms.members.push(new ms.Member(data[i].id,
              data[i].name,
              data[i].gender,
              data[i].mail,
              data[i].bloodtype,
              new Date(data[i].modified)));
          }
        })
        .error(function (data, status, headers, config) {
          alert("MemberServce: load error");
        });
    };

    return ms;
  });
}());

app.js

(function () {
  var app = angular.module("MemberManager", ['ngRoute']);

  // ルーティング
  app.config(function ($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: 'list.html',
        controller: 'ListController'
      })
      .when('/regist', {
        templateUrl: 'regist.html',
        controller: 'RegistController'
      })
      .when('/modify/:num', {
        templateUrl: 'modify.html',
        controller: 'ModifyController'
      })
      .otherwise({
        redirectTo: '/'
      });
  });

  // 初期化
  app.run(function (MemberService) {
    MemberService.load();
    //MemberService.regist("john", "male", "john@aaaa.jp", "A");
    //MemberService.regist("paul", "male", "paul@bbbb.uk", "B");
    //MemberService.regist("marry", "female", "marry@cccc.jp", "O");
  });
}());

getMember.php

<?php
  try{
    $pdo=new PDO("mysql:host=mysql514.db.sakura.ne.jp;".
                "dbname=forcreate_fuchida;".
                "charset=utf8",
                "forcreate","junior2015");
    $q="select * from member";
    $s=$pdo->prepare($q);
    $s->execute();
    print json_encode($s->fetchAll());
  }catch(PDOException $e){
    print json_encode(array("msg"=>$e->getMessage()));
  }
?>

中堅SE向け研修


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS