雖然已經邁入angular
4 的階段,但目前支援的套件仍然很少,雖然有些跟不上潮流,但angualr1仍有不少的粉絲,所以先討論如何angular
1 的行事曆套件
angular-material-calendar,因為剛好案子有需要所以拿來研究看看,也許以後會改用angular4
的 calendar
版本… 呵呵
npm install --save angular-material-calendar |
@section
Header {
<link
href="~/Scripts/Bootstrap/3.0.2/css/bootstrap.min.css"
rel="stylesheet"
/>
<link
href="~/Content/ian-style.css?@version"
rel="stylesheet"
/>
<link
href="/SharedJS/AngularJS/Material/angular-material.min.css"
rel="stylesheet"
/>
<link
href="/SharedJS/AngularJS/Material/angular-material-calendar.min.css"
rel="stylesheet"
/>
}
@section
Scripts {
<script
src="~/Scripts/jquery-1.8.2.min.js"></script>
<script
src="/SharedJS/AngularJS/1.4.8/angular.min.js"></script>
<script
src="/SharedJS/AngularJS/1.4.8/angular-animate.min.js"></script>
<script
src="/SharedJS/AngularJS/1.4.8/angular-sanitize.js"></script>
<script
src="/SharedJS/AngularJS/1.4.8/angular-aria.min.js"></script>
<script
src="/SharedJS/AngularJS/1.4.8/angular-route.min.js"></script>
<script
src="/SharedJS/AngularJS/1.4.8/angular-messages.min.js"></script>
<script
src="/SharedJS/AngularJS/Material/angular-material.min.js"></script>
<script
src="/SharedJS/AngularJS/Material/angular-material-calendar.min.js"></script>
<script
src="~/Scripts/Bootstrap-UI/ui-bootstrap-tpls-0.10.0.min.js"></script>
<script
src="~/Areas/Holiday/Scripts/holidayFactory.js"></script>
<script
src="~/Areas/Holiday/Scripts/IndexController.js"></script>
<script
src="~/Areas/Holiday/Scripts/popupController.js"></script>
} |
因為筆者也有使用angular-material.js的相關特效,所以相依性的套件也一併加入引用參考,請各位視情況加入參考吧~
但最重要的是
angular-material-calendar的css
和js
是必要元件
<calendar-md
flex
layout
layout-fill
calendar-direction="direction"
on-prev-month="prevMonth"
on-next-month="nextMonth"
on-day-click="dayClick"
title-format="'MMMM
y'"
ng-model='selectedDate'
week-starts-on="firstDayOfWeek"
data-start-month="{{calendarMonth}}"
data-start-year="{{calendarYear}}"
tooltips="tooltips"
day-format="dayFormat"
day-label-format="'EEE'"
day-label-tooltip-format="'EEEE'"
day-tooltip-format="'fullDate'"
day-content="setDayContent"
disable-future-selection="false"></calendar-md> |
雖然頁面上的參數那麼多…
其實先知道如何設定起始年份和起始月份,就可以了喔…
如果想進一步的瞭解format
格式有哪些…
還請各位自行研究,目前僅探討簡單的功能。
var
app = angular.module('Holiday',
['ui.bootstrap',
'ngMaterial',
'materialCalendar']);
app.controller('IndexController',
function
($scope, $http, $filter, $q, $timeout, $modal,
MaterialCalendarData, holidayFactory)
{
$scope.calendarYear=new
date().getFullYear(); //設定calendar的起始年
$scope.calendarMonth=new
date().getMonth(); //設定calendar的起始月份
$scope.dayFormat
= "d";
$scope.selectedDate
= null;
$scope.selectedDate
= []; //選擇日期
$scope.firstDayOfWeek
= 0; //設定每週開始【星期日】,以此類推
$scope.setDirection
= function
(direction) {
$scope.direction
= direction;
$scope.dayFormat
= direction === "vertical"
? "EEEE,
MMMM d"
: "d";
};
//點選行事曆的某天後,觸發的事件
$scope.dayClick
=
function
(date) {
$scope.toggleModal(date);
};
//可以設定行事曆的內容
$scope.setDayContent
=
function
(date) {
//此函式將會被多次觸發,因為一個月份的日期有三十多天,所以此函式會被多次重複呼叫,而傳入的參
數
date
會陸續傳進不同的日期
(1~30)
var
contentDay = "";
//此函式會被多次呼叫,所以如果在此函式中透過API或後端取資料,將會造會效能低下,所以需要
後端取得的值,暫存在頁面中。
取得設定行事曆的值以json暫存
id=’holiday’的text,並取回結果
var
jsonHolidays = $("#holidays").val();
if
(jsonHolidays.length > 0) {
var
holidays = JSON.parse(jsonHolidays);
contentDay
= $filter("date")(date,
"yyyy-MM-dd");
//取得日期轉格式
var
checkData = holidays[contentDay];
//確認此日期是否為假日
if
(checkData == undefined) {
return
"<p><br><br><p>";
//如果非假日,傳回的內容
}
else
{
//判斷如果為假日列表有此日期,再判斷(是假日),傳回紅字,否傳回籃字
if
(holidays[contentDay].isHoliday == true)
{
return
"<font
color=red>"
+ holidays[contentDay].holidayName + "</font>";
}
else
{
return
"<font
color=blue>"
+ holidays[contentDay].holidayName + "</font>";
}
}
}
else
{
//如果判斷頁面上的id=’holiday’的text
並無值(第一次讀取時),將會進入此區塊,因為要從後端
讀取資料,雖然再將值回傳到行事曆中…
所以需要用非同步的處理
var
deferred = $q.defer();//先設定行事曆非同步
var
startDate = $filter("date")(date,
"yyyy")
+ "-"
+ "01"
+ "-"
+ "01";
var
endDate = $filter("date")(date,
"yyyy")
+ "-"
+ "12"
+ "-"
+ "31";
//從後端讀取假日列表的APPI
$scope.hoilday
= $scope.reloadData(startDate, endDate).then(function
(result) {
contentDay
= $filter("date")(date,
"yyyy-MM-dd");
$("#holidays").val(angular.toJson(result));
holidays
= result;
var
checkData = holidays[contentDay];
if
(checkData == undefined) {
//以非同步處理結果
deferred.resolve("<p><br><br><p>");
}
else
{
if
(holidays[contentDay].isHoliday == true)
{
deferred.resolve("<font
color=red>"
+ holidays[contentDay].holidayName + "</font>");
}
else
{
deferred.resolve("<font
color=blue>"
+ holidays[contentDay].holidayName + "</font>");
}
}
});
//回傳非同步結果
return
deferred.promise;
}
}
//設定某日期的行事曆的函式(
稱自訂)
$scope.setContentViaService
= function
(setDate,isHoliday,holidayName) {
//某種情況下,需要
UPDATE
某一天的日期的內容,只需呼叫
MaterialCalendarData
務
var
holidays = JSON.parse($("#holidays").val());
var
contentDay = $filter("date")(setDate,
"yyyy-MM-dd");
if
(isHoliday == true)
{
MaterialCalendarData.setDayContent(setDate,
"<p><font
color=red>"
+ holidayName + "</font></p>");
}
else
{
MaterialCalendarData.setDayContent(setDate,
"<p><font
color=blue>"
+ holidayName + "</font></p>");
}
}
//出現子視窗:
情境中為了在行事曆點選某一天後,就能讀取該日期的內容,
就在controller引用
$model,可以另外設定子視窗的單獨的網頁內容和JavaScript,以利於未來高度重複利用
$scope.toggleModal
= function
(holiday_datetime) {
$scope.modInstance;
$scope.holiday_datetime
= holiday_datetime; //透過$scope
傳遞參數給另一個controller
$scope.modInstance
= $modal.open({
templateUrl:
'myModalContent.html',
scope:
$scope,
controller:
"popupController"
});
} |
popupController.js
app.controller("popupController",
function
($scope, $http, $filter, $q, $timeout, $modal,$controller,
MaterialCalendarData,
holidayFactory)
{
$scope.form
= {};
var
curentDay = $filter("date")($scope.holiday_datetime,
"yyyy-MM-dd");
var
startDate = $filter("date")($scope.holiday_datetime,
"yyyy")
+ "-"
+ "01"
+ "-"
+ "01";
var
endDate = $filter("date")($scope.holiday_datetime,
"yyyy")
+ "-"
+ "12"
+ "-"
+ "31";
$scope.curentDay
= curentDay;
$scope.form.isHoliday
= true;
//預設為假日
holidayFactory.LoadHoliday(curentDay).then(function
(result) {
var
loadHolidayObj = JSON.parse(result.data.data);
if
(loadHolidayObj != undefined) {
$scope.form.holidayName
= loadHolidayObj.holidayName;
$scope.form.isHoliday
= loadHolidayObj.isHoliday;
}
});
$scope.save
= function
() {
var
msg = "";
$scope.holidayNameEmpty
= false;
if
($scope.form.holidayName == undefined || $scope.form.holidayName
== "")
{
msg
= "請輸入假日名稱";
$scope.holidayNameEmpty
= true;
}
if
(msg.length == 0) {
holidayFactory.SaveDate(curentDay,
$scope.form.holidayName, $scope.form.isHoliday).then(function
() {
holidayFactory.GetHolidays(startDate,
endDate).then(function
(result) {
$("#holidays").val(result.data.data);
//put
the holiday value in page
})
});
//在某些情況下,無法完全脫離父
controller
的相依性,利用當行事曆要傳遞參數給子視窗,仍然要呼叫另一個controller
的某事件處理,所以只好透過呼叫另一個controller方法,呼叫它的方法。
var
testCtrlViewModel = $scope.$new();
$controller("IndexController",
{ $scope: testCtrlViewModel });
testCtrlViewModel.setContentViaService($scope.holiday_datetime,
$scope.form.isHoliday, $scope.form.holidayName);
$scope.modInstance.dismiss('cancel');
//子視窗自動隱藏
}
}
$scope.close
= function
() {
$scope.modInstance.dismiss('cancel');
}
}); |
Index.cshtml主畫面要引用子視窗的html
<script type="text/ng-template" id="myModalContent.html"> @{ Html.RenderPartial("@popup"); } </script> </div> |
@popup.cshtml
(子視窗的畫面內容)
<div class="modal-header
btn-primary"> <button type="button" class="close" ng-click="close(false)" data-dismiss="modal" aria-hidden="true">×</button> <h4 class="modal-title">行事曆假日設定【 {{holiday}} 】</h4> </div> <div class="modal-body"> <form> <div class="form-group"> <label for="holidayName">假日名稱</label> <input type="text" ng-model="form.holidayName" class="form-control" id="holidayName"placeholder="名稱" maxlength="30" /> <br /> <label for="isHoliday">是否假日</label> <md-checkbox id="isHoliday" aria-label="假日" ng-model="form.isHoliday"></md-checkbox> </div>
</form>
</div><div class="modal-footer"> <button type="button" ng-click="close()" class="btn btn-default" data-dismiss="modal">No</button> <button type="button" ng-click="save()" class="btn btn-primary" data-dismiss="modal">Yes</button> </div> |
子視窗的ng-model雙向綁定,需要以物件為單位,例如
form.holidayName,
form.isHoliday 而無法以holidayName
和
isHoliday為ng-model命名,否則無法進行雙向綁定…
畫面呈現:
補充說明:
因為案子的需要,剛好要取得政府機關的行事曆API,所以透過Factory的功能,將所有呼叫API集中,方便日後管理
HoldayFactroy.js
function
initFactory(app) {
app.factory("holidayFactory",
function
($http, $q) {
return
{
LoadHoliday:
function
(settingDate) {
return
$http({
method:
"Post",
data:
{ settingDate: settingDate },
url:
"/Web/Holiday/LoadHoliday",
cache:
true
});
},
}
})
} |
HomeController.cs
[HttpPost]
public
async
Task<bool>
LoadGovSchedule(int
year) {
try
{
return
controllerHolidayObj.LoadGovSchedule (year);
}
catch
(Exception
ex)
{
_log.ErrorException("SaveGovSchedule:
",
ex);
throw
new
Exception(ex.Message);
}
} |
透過controller
可以取得angular傳入的參數,僅供參考,未來也可考慮用WebAPI或其他分散式API,達到資料共享和重複利用。
ControllerHolidy.cs
private
List<viewHoliday>
LoadGovSchedule(int
year) {
try
{
HttpWebRequest
request =
(HttpWebRequest)WebRequest.Create("http://data.ntpc.gov.tw/api/v1/rest/datastore/382000000A-000077-002");
request.Method
= "GET";
JavaScriptSerializer
json_serializer = new
JavaScriptSerializer();
List<viewHoliday>
govSchedule = new
List<viewHoliday>();
DateTime
dtGovDateTime = new
DateTime();
string
holidayName = "";
using
(WebResponse
wr = request.GetResponse())
{
using
(StreamReader
myStreamReader = new
StreamReader(wr.GetResponseStream()))
{
string
data = myStreamReader.ReadToEnd();
dynamic
jsonObject = json_serializer.Deserialize<dynamic>(data);
dynamic
result = jsonObject["result"];
dynamic
records = result["records"];
foreach
(dynamic
item in
records)
{
holidayName
= HolidayName(item["name"],
item["holidayCategory"]);
dtGovDateTime
= DateTime.ParseExact(item["date"],
"yyyy/M/d",
null);
if
(dtGovDateTime.Year == year) {
govSchedule.Add(new
viewHoliday()
{
holidayDate
= dtGovDateTime,
holidayName
= holidayName,
isHoliday
= (item["isHoliday"]
== "是")
? true
: false
});
}
}
}
}
return
govSchedule;
}
catch
(Exception
ex)
{
throw
new
Exception("controllerHoliday.LoadGovSchedule",
ex);
}
} |
以上用來示範如何取得JSON格式傳回的訊息
沒有留言:
張貼留言