Статьи

Интеграция календаря в ваше приложение Ionic

Для сегодняшней демонстрации я решил попробовать кое-что, на что я хотел выделить время — интеграцию с календарем на мобильном устройстве. К счастью, для этого есть отличный плагин —  Calendar-PhoneGap-Plugin . Этот плагин предоставляет все типы хуков в локальный календарь, включая возможность поиска и добавления событий. С этим плагином я быстро набрал демо.

Я начал с создания приложения, которое просто возвращало события из списка и отображало их как есть. Вот мнение:

Снимок экрана симулятора 18 сентября 2015 г., 11.32.58

Давайте посмотрим на код, стоящий за этим. Во-первых, HTML. Поскольку это приложение очень простое, я не использую маршруты и шаблоны.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title></title>

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">

    <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
    <link href="css/ionic.app.css" rel="stylesheet">
    -->

    <!-- ionic/angularjs js -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>

    <!-- cordova script (this will be a 404 during development) -->
    <script src="cordova.js"></script>

    <!-- your app's js -->
    <script src="js/app.js"></script>
    <script src="js/controllers.js"></script>
    <script src="js/services.js"></script>
  </head>
  <body ng-app="starter">

    <ion-pane ng-controller="MainCtrl">
      <ion-header-bar class="bar-stable">
        <h1 class="title">Ionic Calendar Demo</h1>
      </ion-header-bar>
      <ion-content>

<div class="card" ng-repeat="event in events">
<div class="item item-divider">
{{event.title}}
</div>
<div class="item item-text-wrap">
{{ event.description }}
<p/>
<strong>When: {{ event.date | date:'short' }}</strong>
</div>
</div>

      </ion-content>
    </ion-pane>
  </body>
</html>

Это все должно быть довольно котельной плитой. Я просто перебираю события и создаю пользовательский интерфейс для каждого из них. Теперь давайте посмотрим на код контроллера.

angular.module('starter.controllers', [])

.controller('MainCtrl', function($scope, Events) {

Events.get().then(function(events) {
console.log("events", events);
$scope.events = events;
});

});

Да, просто позвоните в службу и оформите события. Trivial. Теперь давайте посмотрим на сервис.

angular.module('starter.services', [])

.factory('Events', function($q) {

var incrementDate = function (date, amount) {
var tmpDate = new Date(date);
tmpDate.setDate(tmpDate.getDate() + amount)
return tmpDate;
};

//create fake events, but make it dynamic so they are in the next week
var fakeEvents = [];
fakeEvents.push(
{
"title":"Meetup on Ionic",
"description":"We'll talk about beer, not Ionic.",
"date":incrementDate(new Date(), 1)
}
);
fakeEvents.push(
{
"title":"Meetup on Beer",
"description":"We'll talk about Ionic, not Beer.",
"date":incrementDate(new Date(), 2)
}
);
fakeEvents.push(
{
"title":"Ray's Birthday Bash",
"description":"Celebrate the awesomeness of Ray",
"date":incrementDate(new Date(), 4)
}
);
fakeEvents.push(
{
"title":"Code Review",
"description":"Let's tear apart Ray's code.",
"date":incrementDate(new Date(), 5)
}
);

var getEvents = function() {
var deferred = $q.defer();
deferred.resolve(fakeEvents);
return deferred.promise;
}

  return {
get:getEvents
  };

});

Итак, это немного сложнее. У меня есть набор поддельных данных, которые создают четыре события в будущем. Служба затем возвращает эти поддельные события. Итак, давайте поднимем это на ступеньку выше. Учитывая, что наш плагин Календарь может проверять события, я собираюсь обновить свой код, чтобы отображать, было ли событие добавлено в календарь или нет. Вот пример.

Снимок экрана симулятора 18 сентября 2015 г., 11.41.36

На этом снимке экрана вы видите кнопки, чтобы добавить событие в свой календарь. Обратите внимание, что третье событие, однако, распознается как находящееся в календаре. Чтобы заставить это работать, я обновил сервисный вызов для событий, чтобы обработать проверку календаря. Это было немного сложно, поскольку каждый вызов асинхронный, но $ q облегчает его обработку.

var getEvents = function() {
var deferred = $q.defer();

/*
Logic is:
For each, see if it exists an event.
*/
var promises = [];
fakeEvents.forEach(function(ev) {
//add enddate as 1 hour plus
ev.enddate = incrementHour(ev.date, 1);
console.log('try to find '+JSON.stringify(ev));
promises.push($cordovaCalendar.findEvent({
title:ev.title,
startDate:ev.date
}));
});

$q.all(promises).then(function(results) {
console.log("in the all done");
//should be the same len as events
for(var i=0;i<results.length;i++) {
fakeEvents[i].status = results[i].length === 1;
}
deferred.resolve(fakeEvents);
});

return deferred.promise;
}

Я устанавливаю значение состояния для событий, чтобы показать, существует ли событие. Вернувшись на сторону дисплея, я справляюсь с этим так:

<p ng-if="event.status">This event is added to your calendar already!</p>
<button ng-if="!event.status" ng-click="addEvent(event,$index)" class="button button-block button-balanced">Add to Calendar</button>

Довольно просто, правда? Теперь давайте посмотрим на код добавления. Я пропущу код контроллера, так как все, что он делает, это вызывает службу и обновляет область.

var addEvent = function(event) {
var deferred = $q.defer();

$cordovaCalendar.createEvent({
title: event.title,
notes: event.description,
startDate: event.date,
endDate:event.enddate
}).then(function (result) {
console.log('success');console.dir(result);
deferred.resolve(1);
}, function (err) {
console.log('error');console.dir(err);
deferred.resolve(0);
});

return deferred.promise;

}

И просто чтобы доказать, что это работает — вот событие, которое я только что добавил:

Снимок экрана симулятора 18 сентября 2015 г., 11.46.06

Я поместил полный исходный код для этой демонстрации на GitHub:  https://github.com/cfjedimaster/Cordova-Examples/tree/master/calendarionic . Я хочу поблагодарить Эдди Вербруггена за помощь в использовании его плагина и за исправление ошибки, с которой я столкнулся!