2. OnsenuiとAngularjsで簡単に動きのあるページがつくれる

前回の（[OnsenuiとAngularjsで簡単に動きのあるページがつくれる](http://qiita.com/s-hei/items/5a7724c5fa4fc7c86aa9)）つづきから。

#OnsenuiとAngularjsでできること

##スライディングメニュー

滑らかなメニューが作成できる。
[ons-sliding-menu](https://ja.onsen.io/v1/reference/ons-sliding-menu.html)というUIコンポーネント
![onsenui_menu.gif](https://qiita-image-store.s3.amazonaws.com/0/135781/71acb70d-04b5-4821-7eeb-1fff2e188d58.gif)

###実装例

```html:myApp.html
<ons-sliding-menu var="myMenu" main-page="index.html" menu-page="menu.html" max-slide-distance="200px" type="overlay" side="left"></ons-sliding-menu>

<ons-template id="menu.html">
  <ons-list>
    <ons-list-item modifier="chevron">
      メニューその１
    </ons-list-item>
    <ons-list-item modifier="chevron">
      メニューその２
    </ons-list-item>
  </ons-list>
</ons-template>

<ons-template id="index.html">
  <ons-navigator var="myNavigator">
    <ons-page>
      <ons-toolbar>
        <div class="left">
          <ons-toolbar-button ng-click="$ctrl.toggleMenu()">
            <ons-icon icon="ion-navicon"></ons-icon>
          </ons-toolbar-button>
        </div>
        <div class="center">index.html</div>
      </ons-toolbar>
      <div class="message">
        {{$ctrl.welcome}}
      </div>
    </ons-page>
  </ons-navigator>
</ons-template>
```

```js:myApp.js
class MyApp {
  constructor() {
    this.welcome = 'Hello world!';
  }

  toggleMenu() {
    myMenu.toggleMenu();
  }
}
```

##滑らかなページ遷移
滑らかな動きでページ遷移が実装できる。
遷移アニメーションは数パターン用意されている。
[他のパターンはこちら](https://ja.onsen.io/v1/guide.html#Transitionanimation)
![onsenui_pushpage.gif](https://qiita-image-store.s3.amazonaws.com/0/135781/6dfaad19-afa2-8ed3-52e5-0d1b1fa4f3c4.gif)

###実装例

myApp.htmlのindex.html内にページ遷移用のボタンを設置

```html:myApp.html
<div class="nav">
  <button class="button button--large button--outline" ng-click="$ctrl.showList()">Push list page</button>
</div>
```

ボタンを押した時にページ遷移する関数を作成

```js:myApp.js
showList() {
  myNavigator.pushPage('list.html');
}
```

遷移先のページlist.html作成

```html:list.html
<ons-page>
  <my-list-page></my-list-page>
</ons-page>
```

`myListPage`コンポーネント作成
html生成後にons-toolbarがコンポーネント外に設置されるのが少し怪しいが、今のところ動きに問題はない。

```html:myListPage.html
<ons-toolbar>
  <div class="left">
    <ons-back-button>Back</ons-back-button>
  </div>
  <div class="center">{{$ctrl.title}}</div>
</ons-toolbar>
<div class="message">
  {{$ctrl.welcome}}
</div>
```

```js:myListPage.js
class myListPage {
  constructor() {
    this.title = 'list.html';
    this.welcome = 'This is list page';
  }
}
myListPage.$inject = [];

export default {
  templateUrl: './src/components/myListPage/myListPage.html',
  controller: myListPage,
};

```

app.jsにコンポーネントを登録

```js:app.js
import myApp from '../components/myApp/myApp';
import myListPage from '../components/myListPage/myListPage';

.
.
.

  // componentの定義
  app.component('myApp', myApp);
  app.component('myListPage', myListPage);

})();
```

##配列から一覧をつくる
[CiNii Books](https://support.nii.ac.jp/ja/cib/api/b_opensearch)のapiを利用して書籍のデータを取得して著者名一覧を作成する
ここでは、api処理の部分をclassにしてangularjsのserviceに登録する例を示す。

初期画面
<img width="320" alt="list.png" src="https://qiita-image-store.s3.amazonaws.com/0/135781/74fefdcd-80dc-53b1-286d-a3ae82362c01.png">

入力してボタンを押すと
<img width="320" alt="list_result.png" src="https://qiita-image-store.s3.amazonaws.com/0/135781/db06a5d9-db93-c108-f8ba-d03c2e9d5e9e.png">

###実装例

apiを取得するサービス作成

```js:src/js/services/BookService.js
export default class BookService {
  constructor($http) {
    this.$http = $http;
  }

  get(params) {
    params.format = 'json';
    return this.$http(
      {
        method: 'GET',
        url: 'http://ci.nii.ac.jp/books/opensearch/search',
        params,
        responseType: 'json',
      }
    );
  }
}
BookService.$inject = ['$http'];
```

サービスの登録

```js:app.js
import myApp from '../components/myApp/myApp';
import myListPage from '../components/myListPage/myListPage';

import BookService from './services/BookService';

.
.
.

  // serviceの定義
  app.service('BookService', BookService);

})();
```

myListPageコンポーネント

```js:myListPage.js
class myListPage {
  constructor(BookService) {
    this.BookService = BookService;
    this.params = {};
    this.results = {};
  }

  get(params) {
    this.BookService.get(params).then(
      (response) => {
        this.results = response.data['@graph'][0];
      }
    );
  }
}
myListPage.$inject = ['BookService'];

export default {
  templateUrl: './src/components/myListPage/myListPage.html',
  controller: myListPage,
};
```

```html:myListPage.html
<ons-toolbar>
  <div class="left">
    <ons-back-button>Back</ons-back-button>
  </div>
  <div class="center">list.html</div>
</ons-toolbar>
<div class="formarea">
  <div class="formarea-inputs">
    <input type="search" placeholder="Search" class="search-input" ng-model="$ctrl.params.q">
  </div>
  <div><button class="button--large button--outline" ng-click="$ctrl.get($ctrl.params)">Get books</button></div>
</div>
<ons-list class="book-list" ng-if="$ctrl.results['opensearch:totalResults']" modifier="inset">
  <ons-list-header>{{$ctrl.results['opensearch:totalResults']}}件みつかりました</ons-list-header>
  <ons-list-item ng-repeat="item in $ctrl.results.items">
    <div>{{item['dc:creator'] || '不明'}}</div>
  </ons-list-item>
</ons-list>
```

##引っ張り更新
snsなんかのタイムラインによくある引っ張り更新（pull to refresh）機能も簡単に実装できる。
[ons-pull-hook](https://ja.onsen.io/v1/reference/ons-pull-hook.html)というUIコンポーネント
引っ張った時に好きな処理をさせられるので、今回は検索条件をリセットさせる。

![capture.gif](https://qiita-image-store.s3.amazonaws.com/0/135781/d661c3ce-3a51-d039-1296-c439e4bf44f1.gif)


###実装例

**ちなみにons-pull-hookはons-pageかons-scrollerの子要素じゃないとダメ。**

```html:myListPage.html
<ons-scroller>
  <ons-pull-hook var="myListLoader" ng-action="$ctrl.load($done)" height="150px">
    <span ng-switch="$ctrl.getCurrentState()">
      <span class="message-bind" ng-switch-when="initial">ひっぱると更新します</span>
      <span class="message-bind" ng-switch-when="preaction">離すと更新します</span>
      <span class="message-bind" ng-switch-when="action">読み込みを開始します</span>
    </span>
  </ons-pull-hook>
  <ons-toolbar>
    <div class="left">
      <ons-back-button>Back</ons-back-button>
    </div>
    <div class="center">list.html</div>
  </ons-toolbar>
  <div>
    <div class="formarea">
      <div class="formarea-inputs">
        <input type="search" placeholder="Search" class="search-input" ng-model="$ctrl.params.q">
      </div>
      <div><button class="button--large button--outline" ng-click="$ctrl.get($ctrl.params)">Get books</button></div>
    </div>
    <ons-list class="book-list" ng-if="$ctrl.results['opensearch:totalResults']" modifier="inset">
      <ons-list-header>{{$ctrl.results['opensearch:totalResults']}}件みつかりました</ons-list-header>
      <ons-list-item ng-repeat="item in $ctrl.results.items">
        <div>{{item['dc:creator'] || '不明'}}</div>
      </ons-list-item>
    </ons-list>
  </div>
</ons-scroller>
```

```js:myListPage.js
class myListPage {
  constructor(BookService, $timeout) {
    this.BookService = BookService;
    this.$timeout = $timeout;
    this.params = {};
    this.results = {};
  }

  get(params) {
    this.BookService.get(params).then(
      (response) => {
        this.results = response.data['@graph'][0];
      }
    );
  }

  load($done) {
    this.$timeout(() => {
      // 引っ張り終了後の処理
      this.params = {};
      this.results = {};
      $done();
    }, 1000);
  }

  getCurrentState() {
    return myListLoader.getCurrentState();
  }
}
myListPage.$inject = ['BookService', '$timeout'];

export default {
  templateUrl: './src/components/myListPage/myListPage.html',
  controller: myListPage,
};
```


次回[（3. OnsenuiとAngularjsで簡単に動きのあるページがつくれる）](http://qiita.com/s-hei/items/3eba528a712cc4d0449b)は、formとかdialog,スプラッシュスクリーンなど