#はじめに
AngularJSにすこしずつ慣れてきたような気がします。
まだまだですが、がんばります。
さて、入門編として、ToDoを作成しました。次は、カレンダーを作りたいと思います。
完成すれば、ToDo機能をカレンダーに組み込んで、カレンダーアプリにしたいと思います。
まぁ、Googleカレンダーを使ったほうが便利ですが。。。
#カレンダーの作成
まず、カレンダーデータの作成を行います。
var MyApp = angular.module('calendarApp', []);
MyApp.service('CalendarService', [function () {
this.header = function() {
return ["月", "火", "水", "木", "金", "土", "日"];
}
this.calendar = function() {
var date = new Date(); // 現在日付を取得
var week = [6, 0, 1, 2, 3, 4, 5]; // 月曜始まりにするための変換テーブル
var monthdays = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
var year = date.getFullYear();
// うるう年の計算
if (((year % 4) == 0 && (year % 100) != 0) || (year % 400) == 0){
monthdays[1] = 29;
}
// 月を取得
var month = date.getMonth();
// 今日の日を取得
var today = date.getDate();
// 一日を取得
date.setDate(1);
var startDay = date.getDay();
var carendar = []; // カレンダーデータ
var day; // ループ用
var index = 1; // 日付
for(var i = 0; i < 6; i++) {
var tableLine = []; // 1週間分のデータ
var d = 0; // ループ用
do {
date.setDate(index);
day = date.getDay();
// 1段目: 前月の分を空白にする
if (i == 0 && day > d) {
tableLine[d] = {dd: "", color: "none"};
}
// 6段目: 次の月の分を空白にする
else if(i == 6 && monthdays[month] < day) {
tableLine[week[day]] = {dd: "", color: "none"};
index++;
}
// 最終日の段: 次の月の分を空白にする
else if (index > monthdays[month]) {
tableLine[week[day]] = {dd: "", color: "none"};
index++;
}
// 日にちを設定する
else {
tableLine[week[day]] = {dd: date.getDate(), color: date.getDate() == today ? "today" : "none"};
index++;
}
d++;
// 月曜日開始のカレンダーにするため、土曜日になるまでループする
} while (week[day] != 6)
carendar.push(tableLine);
}
return carendar;
}
}]);
MyApp.controller('CalendarCtrl', ['$scope', 'CalendarService', function ($scope, CalendarService) {
$scope.header = function() {
return CalendarService.header();
}
$scope.calendar = function() {
return CalendarService.calendar();
}
}]);
行っていることは、カレンダーを1週間分の配列を6つ格納したcalendar
変数を作成することです。
dd:
には日付が入っていて、color:
には、今日の場合だけtoday
が設定されます。
将来、休日などのデータを格納するのに使えると思います。
#カレンダービュー
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<link rel="stylesheet" href="calendarSample.css">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script type="text/javascript" src="calendarSample.js"></script>
<title>calendarSample</title>
</head>
<body ng-app="calendarApp">
<div class="container">
<div class="jumbotron">
<h2>calendarSample!</h2>
</div>
<div ng-controller="CalendarCtrl" ng-Init="calendar = calendar()">
<table class="table table-striped">
<th ng-repeat="head in header()">{{head}}</th>
<tr ng-repeat="week in calendar">
<td ng-repeat="day in week" class="today-{{day.color}}">{{day.dd}}</td>
</tr>
</table>
</div>
</div>
</body>
</html>
今回新しいキーワードが出てきました。ng-Init="calendar = calendar()"
です。
簡単に言えば、初期化です。テンプレートが実行される前に行う処理を記述します。
.today-today {
background: skyblue;
}
td {
height: 50px;
}
#以外に簡単?いや、そうでもなかった
こうやって見ると、簡単にできたように思います。
でも実際にはそうでもありませんでした。
StackOverflowで質問をして解決できた状態でした。
問題は、ng-Init
を行わないと無限ループに陥る可能性があるため、
AngularJSのエラーが発生しました。
<div ng-controller="CalendarCtrl" ng-Init="calendar = calendar()">
<table class="table table-striped">
<th ng-repeat="head in header()">{{head}}</th>
<tr ng-repeat="week in calendar">
この部分を以下に変えてみるとわかります。
<div ng-controller="CalendarCtrl">
1. <table class="table table-striped">
<th ng-repeat="head in header()">{{head}}</th>
2. <tr ng-repeat="week in calendar()">
初期化せずにng-repeat
に関数を呼び出すと、Error: [$rootScope:infdig]になります。
ネスト構造の配列を使用する場合は、ng-Init="list = list()"
のように初期化時に
値を取得して、ループ数を確定させる必要があります。
#おわりに
今回は、だいぶ勉強になりました。
GitHub - AngularJS_Canendarにソースをアップしています。
次は、Googleカレンダーっぽいものを作ってみたいです。
また、大変そうだなぁ。