cybozu developer network

カテゴリー内の他の記事

第7回 カスタマイズビューを利用してみよう

はじめて kintone をカスタマイズする人が kintone API の基礎知識を学べるよう、チュートリアルの内容を充実させてリニューアルしました。
   リニューアル後のチュートリアルは次のページを参照してください。
   はじめよう kintone API

(著者: 落合 雄一

はじめに

今回は、カスタマイズビューを利用した他のサンプル/Tipsへの橋渡しになるように、レコード一覧データ取得とカスタマイズビューを組み合わせる基本的な方法をご紹介します。
今回の題材としては、第5回の信号機アプリを再利用していきますので、再度設定をご確認の上準備願います!( ̄Λ ̄)ゞ
それと、カスタマイズビューとはいえ一覧画面でレコード取得したデータを利用する事に何の違いもありませんので、自信のない方はもう一度復習してみてくださいねっ(^^♪

カスタマイズビューの設定

それでは早速、準備した信号機アプリにカスタマイズビューを設定していきましょう!
設定方法については、kintoneユーザーヘルプの一覧を設定するにもありますが順を追って説明します。操作はアプリの設定 から、一覧の追加で行います。

※ カスタマイズ形式の一覧を作成、または編集するにはkintoneシステム管理権限が必要です。

 

①一覧名
一覧表示を切り替えるドロップダウンに使われる値ですので、任意に設定して頂いて結構です。管理上使いやすいと思う名前をつけてください。

②レコード一覧の表示形式
「カスタマイズ」を選択してください。

③一覧ID
kintoneによって自動的に振られる数値で、作成する都度違うものが割り当てられます。これはあとで使いますので、図の赤で囲った部分に表示されている値を画面で確認して忘れないようにメモしておいてください。φ( ̄ー ̄ )メモメモ
また、今回はページネーションを利用しますので、チェックが入っている事を確認してください。ここのチェックが外れていると、例えレコード件数が何件あろうともevent.recordsの戻りが空の配列になってしまいます。これはカスタマイズビューを使う上で非常に重要な事なので是非覚えておいてください(^^)

④HTML
ここへ入力した値(HTMLコード)が一覧画面のデータ表示部に置き換わります。以下で記述した内容については、あとで解説しますね!

ここまで入力出来たらいつものように保存→設定完了してください。また、あわせてJavaScript/CSSでカスタマイズの項を確認し、第5回で使ったファイルがまだ残っているようでしたら削除しておいてください。第5回のJavaScriptが動作すると、話がややこしくなってしまいますので。。。。。。。(/・_・\)

保存後に一覧画面へ戻って、①で設定した名前の一覧を選択すると作成したカスタマイズビューを見る事が出来ます。今は図のようにデータは表示されていませんが、その部分はこれから作っていきますので気にしないでください(^^)

選択された一覧によって処理を切り替える

先にも説明した通り、カスタマイズビューも一覧画面には変わりありませんので、いつものようにレコード一覧画面の表示後イベントのapp.record.index.showを使います。

さぁ、それではいよいよ取得した一覧データを利用してカスタマイズビューに・・・・・といきたいところですが、少し待ってください。
今の信号機アプリには、第5回で扱った表形式のものと今回作成したカスタマイズビュー用のものと2種類の一覧が存在しているはずです。
このまま記述したのでは、どちらを選択していても同じJavaScriptが実行されてしまいますね(^^;;
最初からあった表形式の一覧を表示しているときには動作せず、カスタマイズビューのときだけ動作するというような処理を書きたい場合にはどのようにすれば良いのでしょうか?

方法1: eventオブジェクトのプロパティを利用する

カスタマイズビューを作るときに③に表示されているものをメモしたのを思い出してみてください。まずはこの一覧IDを利用する方法をご紹介します。もう一度レコード一覧画面の表示後イベントのeventオブジェクトのプロパティを確認してみましょう。

プロパティ名 説明
appId 数値 アプリID
viewType 文字列 'list' または 'calendar' または 'custom'
viewId 数値 ビューID
viewName 文字列 ビュー名
records 配列 またはオブジェクト

viewType によって下記の値となる
・list : レコードオブジェクト※の配列
・calendar : キーを日付文字列、値をレコードオブジェクトの配列としたオブジェクト。

例:

{
    "2013-12-01": [record1, record2],
    "2013-12-20": [record1]
}
 Copyクリップボードにコピーしました

・custom かつ ページネーションがtrue : レコードオブジェクト※の配列
・custom かつ ページネーションがfalse : 空配列

※レコードオブジェクトとは、フィールドコードとフィールドの値などのレコードの情報を含むオブジェクトです。
フィールドの値は、フィールドの形式によって異なります。詳細はフィールド形式をご確認ください。

offset 数値

viewType によって下記の値となる
・list : 一覧のオフセット数
・calendar : null
・custom かつ ページネーションがtrue : 一覧のオフセット数
・custom かつ ページネーションがfalse : 0

size 数値 viewType によって下記の値となる
・list : 一覧のレコード数
・calendar : null
・custom かつ ページネーションがtrue : 一覧のレコード数
・custom かつ ページネーションがfalse : 0
date 文字列 viewType によって下記の値となる
・calendar : カレンダービューの表示月。2013年 6月なら "2013-06"
・calendar以外 : null
type 文字列

イベントタイプ

 

プロパティ名のところに、viewIdというのがありますね。ここに、一覧IDが入っている事を確認するため、以下のJavaScriptを動かしてみましょう。event.viewIdと比較する数値は、③でメモして頂いた値に書き換える事をお忘れなく。

カスタマイズビューを選択しているときにのみ、alertが表示されました!

同じ事はeventオブジェクトのevent.viewNameでも出来るんで、ついでに確認してみましょう(^^♪

この場合は、①で入力した値を利用することになります。

方法2: カスタマイズビューのDOM要素を利用する

こちらは、カスタマイズビューを作成する際の④に入力するHTMLに他の一覧には存在しない要素IDをあらかじめ書いておき、レコード一覧画面の表示後イベントで呼び出された際に有無を判定する方法です。今回のサンプルでは全体を括るdivのidに"my-customized-view"を記述していますので、このDOM要素取得可否を条件に利用してみます。

取得したレコードを利用する

さて、それでは一覧で取得したrecordオブジェクトの中身をカスタマイズビューに反映していきましょう(^^♪

もうお気づきの方もいらっしゃると思いますが、要は④で投稿したHTMLのtbody(要素id="my-tbody")に子要素をDOM操作して入れていくだけです。ここまではじめようシリーズを読んで下さった皆さんはレコード一覧取得やDOM操作はマスターしている事と思いますので、この辺りについて詳しい説明は省略します。以下のサンプルを利用して皆さんのアプリに応用してみてください。

今はまだ単純なテーブルレイアウトなので、正直しょぼいと思う方もいるかも知れませんね。。。。
しかし、カスタマイズビューで好きなようにHTMLコードやCSSを書いてあげれば、いくらでもカッコ良くしていく事が出来そうです。Σd=(・ω-`o)グッ♪

最後に

いかがでしょう?カスタマイズビューの基本について、これでお分かり頂けましたでしょうか?
一覧画面をよりリッチにしていこうとした場合、カスタマイズビューは非常に有効な機能です。
今後の皆さんの参考のため、いくつかのTipsやサンプルをご紹介しますのであわせてご確認ください。

また、ページネーションを利用しない場合にevent.records以外でレコード一覧を取得する方法について今回は触れませんでした。そのあたりについて、実は上記に取り上げたサンプル/Tipsの中にはその問題を解決しているものもあるのですが、詳しくはまた別の回に紹介したいと思います(^^)
それでは、また次回お会いしましょう。

Let’s kintoneカスタマイズ\(^o^)/

このTipsは、2022年7月版で確認したものになります。

<<第6回 テーブルの値を利用する | 第8回 簡単な更新処理に挑戦してみよう>>

デモ環境

こちらのデモ環境から実際に動作を確認できます。
https://dev-demo.cybozu.com/k/12/

デモ環境の利用は、事前に cybozu developer network のメンバー登録が必要です。画面右上の「サインイン」ボタンよりご登録ください。
デモ環境アカウントとパスワードは、サインイン後にこちらのページでご確認ください。

記事に関するフィードバック

記事のコメント欄は記事に対するフィードバックをする場となっております。
右の記事フィードバックのためのガイドを参照してコメントしてください。
記事のリンク切れなど、気になる点がある場合も、こちらのフォームからフィードバックいただけますと幸いです。

Avatar
Chihiro

大変勉強になりました!ありがとうございます。
まだやはり一人でやるには理解していないことがたくさんなので、こちらを拝見させていただきながら勉強していきたいと思います!
もし可能であれば、業務で近々に対応が必要なことがございまして、是非どこかで方法を掲載いただけましたら幸いです。

現在、生年月日のデータを使って年齢を自動計算するようには設定できたのですが、この年齢を使って登録されているレコードの年齢の平均を算出したく思っています。本当は10代、20代・・・というグラフもつけたいと思っているのですが、まだまだ私にはハードルが高すぎるので、まずは平均年齢だけでも算出できればと思っているのですが、良い方法はございませんでしょうか。

是非アドバイスをお願いいたします。

Avatar
落合 雄一

こちらこそ、読んでいただきありがとうございます!

平均年齢の算出ですね。
一番簡単な方法は、kintone.apiを使ってREST APIで全てのレコードを取得し、普通に平均を算出する方法かと思います。
ただし、kintoneは1度に最大100件しかレコードを取得できないため、レコード数が多い場合はレコードの取得に多くの時間が必要となります。
そのため、レコード数が多い場合は違うアルゴリズムを採用したほうが良いのかもしれません。

以下のプログラムは、全てのレコードを取得して平均年齢を算出するプログラムです。

(function() {
"use strict";

// 年齢のフィールドコード
var ageFieldCode = 'age';

// レコード一覧画面
kintone.events.on('app.record.index.show', function(event) {
    (new KintoneRecordManager).getRecords(function(records) {
        var sumAge = 0;
        var recordNum = records.length;
        for (var i = 0; i < recordNum; i++) {
            sumAge += parseInt(records[i][ageFieldCode].value, 10);
        }
        var average = sumAge / recordNum;
        window.alert('平均年齢は'+average+'です');
    });
});

})();

/**
* Kintoneと通信を行うクラス
*/
KintoneRecordManager = (function() {
KintoneRecordManager.prototype.query = '';

KintoneRecordManager.prototype.records = [];

KintoneRecordManager.prototype.appId = null;

KintoneRecordManager.prototype.query = '';

KintoneRecordManager.prototype.limit = 100;

KintoneRecordManager.prototype.offset = 0;

function KintoneRecordManager() {
    this.appId = kintone.app.getId();
}

// すべてのレコード取得する
KintoneRecordManager.prototype.getRecords = function(callback) {
    kintone.api('/k/v1/records', 'GET', {
        app: this.appId,
        query: this.query + (' limit ' + this.limit + ' offset ' + this.offset)
    }, (function(_this) {
        return function(res) {
            var len;
            Array.prototype.push.apply(_this.records, res.records);
            len = res.records.length;
            _this.offset += len;
            if (len < _this.limit) {
                _this.ready = true;
                if (callback !== null) {
                    callback(_this.records);
                }
            } else {
                _this.getRecords(callback);
            }
        };
    })(this));
};

return KintoneRecordManager;

})();

以上、参考になりますでしょうか?
わかりにくい点がありましたらまたご質問ください!

Avatar
Chihiro

ご返信いただきありがとうございます!そして、ご丁寧なご説明本当にありがとうございます。
早速内容を自分なりに読んでみたのですが、早速質問をさせてください・・・。
今、年齢を出しているのが生年月日のフィールド内で出すようにしているのですが、上記いただいた内容を有効にするには、フィールド自体をageという名前で表示できるようにしなくてはいけないということで理解は正しいでしょうか。
もし可能であれば、生年月日から年齢を出して一つのフィールドに表示させて、そこから平均を出すというやり方も合わせてご教示いただけますでしょうか。
素人質問で大変申し訳ありません・・・。
どうぞよろしくお願いいたします。

Avatar
落合 雄一

>上記いただいた内容を有効にするには、フィールド自体をageという名前で表示できるようにしなくてはいけないということで理解は正しいでしょうか。
年齢フィールド(フィールドコード:age)が必要になりますね。

>生年月日から年齢を出して一つのフィールドに表示させて、そこから平均を出す
年齢フィールドは持たないが、一覧画面では年齢を表示したいということでしょうか?
この場合、カスタマイズビューで一覧表示を自作する必要がでてきます。

参考になるかわかりませんが、以下は生年月日→平均年齢を算出するサンプルです。

(function() {
    "use strict";

    // 生年月日のフィールドコード
    var birthdayFieldCode = 'birthday';

    // 年齢を計算
    var getAge = function (birthdateString) {
        var today = new Date();
        var birthday = new Date(birthdateString);
        var age = today.getFullYear() - birthday.getFullYear();
        var m = today.getMonth() - birthday.getMonth();
        if (m < 0 || (m === 0 && today.getDate() < birthday.getDate())) {
            age--;
        }

        return age;
    };

    // レコード一覧画面
    kintone.events.on('app.record.index.show', function(event) {
        (new KintoneRecordManager).getRecords(function(records) {
            var sumAge = 0;
            var recordNum = records.length;
            for (var i = 0; i < recordNum; i++) {
                var birthday = records[i][birthdayFieldCode].value;
                var age = getAge(birthday);
                sumAge += age;
            }
            var average = sumAge / recordNum;
            window.alert('平均年齢は'+average+'です');
        });
    });

})();

/**
* Kintoneと通信を行うクラス
*/
KintoneRecordManager = (function() {
    KintoneRecordManager.prototype.query = '';

    KintoneRecordManager.prototype.records = [];

    KintoneRecordManager.prototype.appId = null;

    KintoneRecordManager.prototype.query = '';

    KintoneRecordManager.prototype.limit = 100;

    KintoneRecordManager.prototype.offset = 0;

    function KintoneRecordManager() {
        this.appId = kintone.app.getId();
    }

    // すべてのレコード取得する
    KintoneRecordManager.prototype.getRecords = function(callback) {
        kintone.api('/k/v1/records', 'GET', {
            app: this.appId,
            query: this.query + (' limit ' + this.limit + ' offset ' + this.offset)
        }, (function(_this) {
            return function(res) {
                var len;
                Array.prototype.push.apply(_this.records, res.records);
                len = res.records.length;
                _this.offset += len;
                if (len < _this.limit) {
                    _this.ready = true;
                    if (callback !== null) {
                        callback(_this.records);
                    }
                } else {
                    _this.getRecords(callback);
                }
            };
        })(this));
    };

    return KintoneRecordManager;
})();

以上、参考になりますでしょうか?
わかりにくい点がありましたらまたご質問ください!

Avatar
Chihiro

早速のご回答ありがとうございます。
今も四苦八苦私なりにトライをしておりました・・・。
年齢のフィールド、持たせたいと思っています。
「生年月日」というフィールドと「年齢」というフィールドを作りたいのですが、それもスタックしておりました。。

●詳細画面、一覧画面共に生年月日とは別フィールドで年齢を出すようにする方法はございますでしょうか。
●その上で、出来ればスペースのトップに「アプリ貼り付け」を使って平均年齢を表示できるようにしたく思っています。これは可能でしょうか。
 難しい場合は、一覧の上部に表示する形式にしたいと思います。(こちらの講座でボタン配置された場所のイメージです)
●今回の平均年齢は、会員ステータスというフィールドの値が「入会」になっている方だけを対象に算出したく思っていますが、こうした指定も同時に可能でしょうか。

大変恐縮ですが、何卒よろしくお願いいたします。

Avatar
落合 雄一

結論から言うと全てできます。
方法ですが、なるべく簡単な方法が良いかと思います。
以下のような仕様でどうでしょうか?

■会員アプリ
・生年月日
・年齢
・ステータス(入会...)
...

■平均年齢アプリ
・平均年齢
・算出日時

■簡単な仕様
・会員アプリの一覧で、ボタンクリックでその時の入会者の平均年齢を算出
・算出した平均年齢を平均年齢アプリに登録
・算出時に年齢が上がったレコードがあればレコードを更新する
・定期的にボタンをクリックする
・スペースのトップに平均年齢アプリを貼り付け(一覧orグラフ)
グラフにして平均年齢の推移を見るのもいいかもしれません。

■JavaScript
会員アプリ
・レコード追加/編集画面
 年齢フィールドは自動計算するので編集不可にする
・レコード追加/編集保存前
 年齢を計算する
・一覧画面
 ボタンクリックで平均年齢を算出し、平均年齢アプリに登録する

(function() {
"use strict";

// 生年月日のフィールドコード
var birthdayFieldCode = 'birthday';
// 年齢のフィールドコード
var ageFieldCode = 'age';

// 年齢を計算
var getAge = function (birthdateString) {
    var today = new Date();
    var birthday = new Date(birthdateString);
    var age = today.getFullYear() - birthday.getFullYear();
    var m = today.getMonth() - birthday.getMonth();
    if (m < 0 || (m === 0 && today.getDate() < birthday.getDate())) {
        age--;
    }

    return age;
};

// ボタン生成
var createButton = function (id, title, onClick) {
    var button = document.createElement('button');
    button.id = id;
    button.innerHTML = title;
    button.onclick = onClick;

    kintone.app.getHeaderMenuSpaceElement().appendChild(button);
};


// レコード追加・編集画面
kintone.events.on(['app.record.create.show', 'app.record.edit.show'], function(event) {
    // 年齢フィールドを編集不可にする
    event.record[ageFieldCode].disabled = true;
    return event;
});

// レコード追加・編集保存前イベント
kintone.events.on(['app.record.create.submit', 'app.record.edit.submit'], function(event) {
    // 年齢を計算
    var birthday = event.record[birthdayFieldCode].value;
    event.record[ageFieldCode].value = getAge(birthday);

    return event;
});

// レコード一覧画面
kintone.events.on('app.record.index.show', function(event) {
    createButton('average_age', '平均年齢算出', function () {
        var manager = new KintoneRecordManager;
        manager.query = 'status in ("入会")';
        manager.records = [];
        manager.getRecords(function(records) {
            var sumAge = 0;
            var recordNum = records.length;
            for (var i = 0; i < recordNum; i++) {
                var birthday = records[i][birthdayFieldCode].value;
                var age = getAge(birthday);
                sumAge += age;
                /**
                 * @todo
                 * 年齢に変更がある場合、kintone.api('record', 'PUT', ...)でレコードを更新する
                 */
            }
            var average = sumAge / recordNum;

            /**
             * @todo
             * 平均年齢アプリにkintone.api('record', 'POST', ...)でレコードを追加する
             */

            window.alert('平均年齢は'+average+'です');
        });
    });
});

})();

/**
* Kintoneと通信を行うクラス
*/
KintoneRecordManager = (function() {
KintoneRecordManager.prototype.query = '';

KintoneRecordManager.prototype.records = [];

KintoneRecordManager.prototype.appId = null;

KintoneRecordManager.prototype.query = '';

KintoneRecordManager.prototype.limit = 100;

KintoneRecordManager.prototype.offset = 0;

function KintoneRecordManager() {
    this.appId = kintone.app.getId();
}

// すべてのレコード取得する
KintoneRecordManager.prototype.getRecords = function(callback) {
    kintone.api('/k/v1/records', 'GET', {
        app: this.appId,
        query: this.query + (' limit ' + this.limit + ' offset ' + this.offset)
    }, (function(_this) {
        return function(res) {
            var len;
            Array.prototype.push.apply(_this.records, res.records);
            len = res.records.length;
            _this.offset += len;
            if (len < _this.limit) {
                _this.ready = true;
                if (callback !== null) {
                    callback(_this.records);
                }
            } else {
                _this.getRecords(callback);
            }
        };
    })(this));
};

return KintoneRecordManager;

})();

以上、参考になりますでしょうか?
仕事中は回答できない場合が多いですが、わかりにくい点がありましたらまたご質問ください!

Avatar
Chihiro

ありがとうございます!!!いただいた仕様素晴らしいです。本当に親切にご対応いただき感謝です。
これから、いただいたコードも読み解いてみたいと思います!
追加の素人質問で大変恐縮なのですが、設定方法についても教えていただけますでしょうか・・・。
度々のお願いで大変恐縮なのですが、いくつか質問と確認をさせていただけましたらと思います。

【仕様について】
●一覧画面と詳細画面の年齢表示のところだけは、ステータス(入会・退会等)に関わらず年齢を表示することは可能でしょうか。
●現在は「入会」のみなのですがこれを今後他のステータス(「手続き中」など)を加えたい場合は、[manager.query = 'status in ("入会")';]を追加するイメージでしょうか。

【設定方法について】
●このjsファイルを顧客アプリ上でアップしましたのですが、フォーム上で年齢を表示させるには、フォームの編集で年齢フィールドを作るという認識で良いでしょうか。
その場合、「数値」のフィールドをドラッグアンドドロップで追加して、フィールドコードをageにするということで良いでしょうか。
●平均年齢アプリをスタートのスレッドに置く方法について教えていただけますでしょうか。

なお、一覧画面で平均年齢ボタンを押した時に表示される平均年齢は、正しいものが表示されました!ありがとうございました!!!
色々とお忙しい中ご迷惑ばかりおかけいたしますが、何卒よろしくお願いいたします。

Avatar
落合 雄一

【仕様について】
●一覧画面と詳細画面の年齢表示のところだけは、ステータス(入会・退会等)に関わらず年齢を表示することは可能でしょうか。
→ステータスに関わらず表示されます。

●現在は「入会」のみなのですがこれを今後他のステータス(「手続き中」など)を加えたい場合は、[manager.query = 'status in ("入会")';]を追加するイメージでしょうか。
→その通りです。詳しくは以下をご参照ください。
https://cybozudev.zendesk.com/hc/ja/articles/202331474#step2

【設定方法について】
●このjsファイルを顧客アプリ上でアップしましたのですが、フォーム上で年齢を表示させるには、フォームの編集で年齢フィールドを作るという認識で良いでしょうか。
その場合、「数値」のフィールドをドラッグアンドドロップで追加して、フィールドコードをageにするということで良いでしょうか。
→その通りです。フィールドコードを変更したい場合は、JSのageFieldCodeを変更してください。

●平均年齢アプリをスタートのスレッドに置く方法について教えていただけますでしょうか。
スペースの管理者の場合、スペースのトップに「本文を編集」というリンクが表示されます。
そこで「アプリの貼り付け」で平均年齢アプリを選んでください。

@todoと記述していることろは、以下を参考にしてください。
https://cybozudev.zendesk.com/hc/ja/articles/202166310
https://cybozudev.zendesk.com/hc/ja/articles/202166160#step1
https://cybozudev.zendesk.com/hc/ja/articles/201941784#step1

以上、参考になりますでしょうか?

Avatar
Chihiro

お忙しい中ありがとうございます。ステータスの追加等、試してみたいと思います!
ToDoのところも引き続き確認してみたいと思います。
度々で恐縮なのですが、あと2点質問良いでしょうか・・・。

●一覧のボタンなのですが、「第2回 レコード一覧画面にボタンを置いてみよう!」でもあった増殖バグが起きております。
 この場合、色々試しているのですが、ボタン自体がなくなってしまったりという現象になってしまっております。
 教えていただけますでしょうか。

●アプリの貼り付けをクリックした後に出てくるところで平均年齢アプリが出てこない場合は、どこか設定漏れがありそうでしょうか・・・。

何卒よろしくお願いいたします。本当に色々とありがとうございます!

Avatar
落合 雄一

>●一覧のボタンなのですが、「第2回 レコード一覧画面にボタンを置いてみよう!」でもあった増殖バグが起きております。
修正したものを下に置いているので見てみてください。

>●アプリの貼り付けをクリックした後に出てくるところで平均年齢アプリが出てこない場合は、どこか設定漏れがありそうでしょうか・・・。
実際の画面がわからないのでちょっと答えにくいです。。。
管理権限や確認漏れなどいろいろ調べてみてください。
すいません。

とりあえずJavaScriptは作っておいたので、参考にしてみてください。

/**
 * 会員管理アプリ
 * 
 * JavaScriptに必要なフィールド
 *  生年月日
 *      フィールド名:生年月日
 *      フィールドタイプ:日時
 *      フィールドコード:birthday
 *      備考:なし
 *  年齢
 *      フィールド名:年齢
 *      フィールドタイプ:数値
 *      フィールドコード:age
 *      備考:単位記号(歳, 後に付ける)
 *  会員ステータス
 *      フィールド名:会員ステータス
 *      フィールドタイプ:ラジオボタン
 *      フィールドコード:status
 *      備考:項目(手続き中, 入会, 退会)
 * 
 * 平均年齢アプリ
 *  平均年齢
 *      フィールド名:平均年齢
 *      フィールドタイプ:数値
 *      フィールドコード:average_age
 *      備考:単位記号(歳, 後に付ける), 小数点以下の表示桁数はお好みで
 *  算出日時
 *      フィールド名:算出日時
 *      フィールドタイプ:作成日時
 *      フィールドコード:変更の必要なし
 *      備考:なし
 * 
 * @author Yuichi Ochiai <ochiai@cstap.com>
 */
(function() {
    "use strict";

    // 平均年齢アプリのアプリID
    var averageAgeAppId = 440;

    // 生年月日のフィールドコード
    var birthdayFieldCode = 'birthday';
    // 年齢のフィールドコード
    var ageFieldCode = 'age';


    // 年齢を計算
    var getAge = function (birthdateString) {
        var today = new Date();
        var birthday = new Date(birthdateString);
        var age = today.getFullYear() - birthday.getFullYear();
        var m = today.getMonth() - birthday.getMonth();
        if (m < 0 || (m === 0 && today.getDate() < birthday.getDate())) {
            age--;
        }

        return age;
    };

    // ボタン生成
    var createButton = function (id, title, onClick) {
        var button = document.createElement('button');
        button.id = id;
        button.innerHTML = title;
        button.onclick = onClick;

        kintone.app.getHeaderMenuSpaceElement().appendChild(button);
    };


    // レコード追加・編集画面
    kintone.events.on(['app.record.create.show', 'app.record.edit.show'], function(event) {
        // 年齢フィールドを編集不可にする
        event.record[ageFieldCode].disabled = true;
        return event;
    });

    // レコード追加・編集保存前イベント
    kintone.events.on(['app.record.create.submit', 'app.record.edit.submit'], function(event) {
        // 年齢を計算
        var birthday = event.record[birthdayFieldCode].value;
        if (birthday) {
            event.record[ageFieldCode].value = getAge(birthday);
        }

        return event;
    });

    // レコード一覧画面
    kintone.events.on('app.record.index.show', function(event) {
        // 既にボタンがある場合はスルー
        if (document.getElementById('average_age')) {
            return event;
        }

        createButton('average_age', '平均年齢算出', function () {
            var manager = new KintoneRecordManager;
            manager.query = 'status in ("入会")';
            manager.records = [];
            manager.getRecords(function(records) {
                var sumAge = 0;
                var recordNum = records.length;
                for (var i = 0, l = recordNum; i < l; i++) {
                    var record = records[i];
                    var birthday = record[birthdayFieldCode].value;
                    if (!birthday) {    // 生年月日が空の場合は、平均年齢算出対象から外す
                        recordNum--;
                        continue;
                    }
                    var age = getAge(birthday);
                    sumAge += age;

                    // 年齢に変更がある場合レコードを更新する
                    if (age !== parseInt(record[ageFieldCode].value, 10)) {
                        var updateRecord = {};
                        updateRecord[ageFieldCode] = {value: age};
                        kintone.api('/k/v1/record', 'PUT', {
                            app: kintone.app.getId(),
                            id: record['$id'].value,
                            record: updateRecord
                        });
                    }
                }


                var average = sumAge / recordNum;

                // 平均年齢アプリにレコードを追加する
                kintone.api('/k/v1/record', 'POST', {
                    app: averageAgeAppId,
                    record: {
                        average_age: {
                            value: average
                        }
                    }
                });

                window.alert('平均年齢は'+average+'です');
            });
        });
    });

})();

/**
* Kintoneと通信を行うクラス
*/
KintoneRecordManager = (function() {
    KintoneRecordManager.prototype.query = '';

    KintoneRecordManager.prototype.records = [];

    KintoneRecordManager.prototype.appId = null;

    KintoneRecordManager.prototype.query = '';

    KintoneRecordManager.prototype.limit = 100;

    KintoneRecordManager.prototype.offset = 0;

    function KintoneRecordManager() {
        this.appId = kintone.app.getId();
    }

    // すべてのレコード取得する
    KintoneRecordManager.prototype.getRecords = function(callback) {
        kintone.api('/k/v1/records', 'GET', {
            app: this.appId,
            query: this.query + (' limit ' + this.limit + ' offset ' + this.offset)
        }, (function(_this) {
            return function(res) {
                var len;
                Array.prototype.push.apply(_this.records, res.records);
                len = res.records.length;
                _this.offset += len;
                if (len < _this.limit) {
                    _this.ready = true;
                    if (callback !== null) {
                        callback(_this.records);
                    }
                } else {
                    _this.getRecords(callback);
                }
            };
        })(this));
    };

    return KintoneRecordManager;
})();
Avatar
Chihiro

時間が空いてしまい申し訳ありません・・・!早速確認してみたいと思います。
このソースも、調べながら読解してみたいと思います。お忙しい中丁寧にご対応いただきましてありがとうございました。
アプリの追加も、調べてみます!
本当にありがとうございました。

Avatar
落合 雄一

いえいえ(^^)
わからない点がありましたらご質問ください!

Avatar
KUNI

このページを参考に作成しました。
とても簡単に一覧表を作成することが出来ました。
・・・が、添付ファイルのところで悩んでいます。

「文字列項目」や「Webサイトのアドレス項目」は下記の書き方で表示されたのですが、添付ファイルについては書き方が全く分かりません。
(文字列)
  cell1.innerHTML = record.氏名.value;
  cell2.innerHTML = record.内容.value;
(Webサイト)
  var tmpB = document.createElement('a');
  tmpB.href = record.参考URL.value;
  tmpB.innerHTML = record.参考URL.value;
  cell3.appendChild(tmpB);

フィールドコード名は「添付ファイル」です。
上記と同じ書き方だと「[object Object],[object Object]」と表示されます。
当たり前ですが・・・
cell4.innerHTML = record.添付ファイル.value;
添付ファイルは、複数の場合もあるので複数表示もご教示頂ければ幸いです。

他の添付ファイルの表示方法も読んだのですが、出来ればこのページの書き方が一番分かりやすいので
追記で表示出来れば、大変ありがたいです。

よろしくお願いいたします。

Avatar
MANANDHAR ANJU

 一覧をカスタマイズしないでJavaScriptコードを書いてviewId使用してindexを開く時alertが出ますが

一覧をカスタマイズしてJavaScriptコードを書いてviewId 使用してindexを開くとalert出ないのは何ですか。

下のコードを使用してます。

(() => {
  'use strict';
  kintone.events.on('app.record.index.show', (event) => {
    if (event.viewId !== 6131402) {
      return;
    }

    window.alert('Starting Customization ');
  });
})();

Avatar
cybozu Development team

MANANDHAR ANJU 様

cybozu developer network 事務局です。

ご連絡いただいた現象は当方では再現せず、提示いただいたコードでalertは発生しました。
viewIdが正しいかあらためてご確認いただき、
正しい場合は、以下の記事を参考にデバッグにて原因を探していただければと思います。
https://developer.cybozu.io/hc/ja/articles/4977994758297

個別の技術的な質問は cybozu developer コミュニティのご利用をお願いいたします。

サインインしてコメントを残してください。