HL7 PHIRのResourceを登録するテスト用サーバ(Repository)が無償で提供されています。それが
HAPI PHIRです。HAPI FHIRの目的は,FHIRの啓蒙と普及だと思います。このサーバを利用すればRESTful APIを用いてPHIRの様々なREsourceを登録,参照,更新,削除を行うことができます。これからFHIRでアプリケーションを作ってみようと考えている人々にとって貴重なテストベッドになります。なぜならPHIRの仕様を自ら実装するには敷居が高すぎるからです。
では,早速,HAPI FHIR Serverを使って簡単なスマホアプリを作ってみましょう。扱うのResourceは
Patientです。初画面でHAPI FHIRに登録されているPatientの一覧を表示し,タップすると選択されたPatientの内容を表示するアプリです。
スクリーンショット
 |
Patient一覧 |
 |
Patient詳細画面 |
上のPatient一覧画面から患者をタップすると下の詳細画面が表示されます。
index.html
まず,index.htmlはons-navigatorを使ってPatient一覧画面(page1.html)を表示します。
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<script src="components/loader.js"></script>
<script src="js/app.js"></script>
<link rel="stylesheet" href="components/loader.css">
<link rel="stylesheet" href="css/style.css">
<script>
ons.bootstrap();
</script>
</head>
<body>
<ons-navigator var="myNavigator" page="page1.html"></ons-navigator>
</body>
</html>
page1.html
page1.htmlにはons-listコンポーネントを用意し,プログラムでこの中に患者一覧を挿入します。
<ons-page id="page1">
<ons-toolbar>
<div class="center">HAPI FHIR Patients</div>
</ons-toolbar>
<br>
<div>
<ons-list id="patient-list">
</ons-list>
</div>
</ons-page>
page2.html
page2.htmlは患者の詳細画面です。divタグの中にプログラムで患者の詳細情報を挿入します。
<ons-page id="page2">
<ons-toolbar>
<div class="left"><ons-back-button>Back</ons-back-button></div>
<div class="center">Hapi FHIR Patient</div>
</ons-toolbar>
<div id="patient-info">
</div>
</ons-page>
app.js
page1が表示されたとき,FHIRで患者検索を行い,その
結果を編集します。結果の編集はlistPatients関数で行います。なお,検索結果はJSON形式です。
listPatients関数ではhtmlを編集したのち,患者クリック時のイベントプロシージャを登録します。登録はセレクタ$('.patient', '#page1')に対して行います。'#page1'のところはthisを使いたいところですが,使えません。なぜならプログラムでons-list-item要素を動的に作成しているため,それにつけたclass="patient"はthisとは紐づけられていないからです(たぶん)。本来,ここでのthisと#page1は同じものを指しているはずですが,そうとは解釈されないようです。
患者がタップされたら患者IDをpage2へ渡して画面遷移を行います。page2が表示されるタイミングでその患者の情報をFHIR Serverに取りに行き,詳細情報を表示します。ここでは,resource.text.divをそのまま出力しています。
$(document).on('pageinit', '#page1', function(){
var url = 'http://fhirtest.uhn.ca/baseDstu2/Patient';
$.ajax({
url: url,
type: 'GET',
data: {
_pretty: true,
}
})
.done(function(resource) {
listPatients(resource);
})
.fail(function(XMLHttpRequest, textStatus, errorThrown) {
var html = '';
html += '<ons-row>' + 'XMLHttpRequest:' + XMLHttpRequest.status + '</ons-row>';
html += '<ons-row>' + 'textStatus:' + textStatus + '</ons-row>';
html += '<ons-row>' + 'errorThrown:' + errorThrown + '</ons-row>';
$("#patient-list").html(html);
var content = $("#patient-list").get(0);
ons.compile(content);
});
});
$(document).on('pageinit', '#page2', function(){
var page = myNavigator.getCurrentPage();
var patientId = page.options.patientId;
var url = 'http://fhirtest.uhn.ca/baseDstu2/Patient/' + patientId;
$.ajax({
url: url,
type: 'GET',
})
.done(function(resource) {
$("#patient-info").html(resource.text.div);
})
.fail(function(XMLHttpRequest, textStatus, errorThrown) {
var html = '';
html += '<ons-row>' + 'XMLHttpRequest:' + XMLHttpRequest.status + '</ons-row>';
html += '<ons-row>' + 'textStatus:' + textStatus + '</ons-row>';
html += '<ons-row>' + 'errorThrown:' + errorThrown + '</ons-row>';
$("#patient-list").html(html);
var content = $("#patient-list").get(0);
ons.compile(content);
});
});
function listPatients(resource) {
var html = '';
$.each(resource.entry, function(index, entry){
html += '<ons-list-item modifier="chevron" class="patient">';
html += '<ons-row>';
html += '<ons-col class="patient-id">' + entry.resource.id + '</ons-col>';
html += '<ons-col>' + entry.resource.name[0].family[0] + ' ' + entry.resource.name[0].given[0] + '</ons-col>';
html += '</ons-row>';
html += '</ons-list-item>';
});
$("#patient-list").html(html);
var content = $("#patient-list").get(0);
ons.compile(content);
$('.patient', '#page1').on('click', function(){
var options = {
patientId: $('.patient-id', this).text()
};
myNavigator.pushPage('page2.html', options);
});
}
なお,Ajaxの成功時及び失敗時の処理の書き方は.done~,.fail~が正しいらしい。詳しくは「
jQuerryのDefferredを用いたモダンなAjaxの書き方」を参照。