詳細画面表示時の項目更新について

いつもお世話になっております。

JSで、生年月日から年齢計算をして「文字列(一行)」フィールドに、年齢をセットしています。
編集画面保存時は年齢が正しく更新されますが、詳細画面表示時に同じ処理を入れても年齢が更新されません。

JSをデバッグしたところ、
年齢フィールド「record[‘age’][‘value’]」には正しい年齢の値がセットされていますが、画面表示では、計算前の値が表示されている状態です。

JS実行と画面表示のタイミング(順番)の問題であるように思えますが、
画面表示後にJS「[‘app.record.detail.show’]」が処理されているのでしょうか?
それが原因でしたら、画面表示前にJSが実行されるような対処法はありますでしょうか?

hiroko5572さん

詳細画面表示時のイベントでは、フィールドの値書き換えは出来なかったと思います。

詳細画面表示の時に、年齢フィールドを更新する必要がある場合、 REST API を使用して、直接レコードを更新する事になると思います。

https://cybozudev.zendesk.com/hc/ja/articles/201941784-%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E6%9B%B4%E6%96%B0-PUT-

更新後に画面を再読み込みすれば、更新後の値が表示されるはずです。

ご参考になれば。

hiroko5572さん

編集画面保存時は年齢が正しく更新されますが、詳細画面表示時に同じ処理を入れても年齢が更新されません。

上海レンユアー 松村さんと重複しますが、・・・これは、レコード追加編集イベントには「フィールドの値を書き換える」という機能がありますが、レコード表示イベントには存在しないことから、あくまで表示画面に対するイベントということで、値を操作できる機能は働かないという仕様だと思います。

レコード詳細表示画面を開いたときに何らかのアクションを起こすとすれば、REST APIつまりkintone.api() を利用するのが常套手段だと思われます。

画面表示後にJS「[‘app.record.detail.show’]」が処理されているのでしょうか?

画面表示イベントですので、「表示直後」と解釈頂いても遜色ないかと思います。

それが原因でしたら、画面表示前にJSが実行されるような対処法はありますでしょうか?

表示前とすると、大抵一覧画面からの遷移になると思いますが、手を尽くしたとしてもREST APIか編集画面を絡ませる必要性が出てくることから、REST APIに帰着するという流れだと思います(ちょっと表現に難しいですが)。

また、この場合更新に合わせて画面をリロードさせるのも常套手段だと思いますが、何かしらのチェックを入れないとループになりますので、今回ですと年齢計算を行った結果として既存の値と異なる(他の例では、対象のフィールドが空、ルックアップされている項目が元アプリから変更になってる)場合にのみレコード更新及び画面リロードを行うという方法になるかと思います。

上海レンユアー 松村さん、山下さん
ご返答ありがとうございます。

画面表示時にREST APIで年齢フィールドの更新処理を記述しましたが、ループにはまってしまいました。

結局、年齢フィールドとは別に、DOMにて年齢項目を作成し、詳細画面表示時に年齢を再計算して表示する方法を取りました。

再計算の際に、年齢フィールドの値と異なれば、REST APIで年齢フィールドの更新処理を行っています。

これにより、詳細画面では、年齢フィールドとDOMで作成した年齢項目が両方表示されてしまいますので、「kintone.app.record.setFieldShown」で年齢フィールドを非表示にしました。

一覧や他のアプリと多数連携しているため、既存の年齢フィールドを完全に削除する訳にはいかず、この方法で対応しました。

妥当かどうか分かりませんが、解決しましたので、ご連絡いたします。
どうもありがとうございました。

hiroko5572さん

ひとまず解決されたようで良かったですが、・・・ちょっと書いてみました。詳細表示イベントで、文字列(1行)を用いている年齢のフィールドに他に何らかのカスタマイズが絡んでいなければ、こんな感じでやると良さそうに思いますが、いかがでしょうか。

(function() {
  "use strict";

  kintone.events.on(['app.record.detail.show'], function(event) {
    //console.log(event);
    var record = event.record;

    var existing_age = parseInt(record['age']['value']);

    if(record['birthday']['value']!=null){
      // referred to https://msdn.microsoft.com/en-us/library/ie/ee532932%28v=vs.94%29.aspx
      var birthday = new Date(record['birthday']['value']);
      var today = new Date();
      var years = today.getFullYear() - birthday.getFullYear();
      birthday.setFullYear(today.getFullYear());
      if (today < birthday){
        years--;
      }
      var real_age = years;
      //console.log(real_age);
      if(existing_age != real_age){
        var params = {
          app: kintone.app.getId(),
          id: kintone.app.record.getId(),
          record: {
            age: {
              value: real_age
            }
          }
        };
        kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', params, function(resp) {
          alert('年齢を更新します。');
          location.reload(true);
        }, function(resp) {
          // エラーの場合はメッセージを表示する
          var errmsg = 'レコード更新時にエラーが発生しました。';
          // レスポンスにエラーメッセージが含まれる場合はメッセージを表示する
          if (resp.message !== undefined){
            errmsg += resp.message;
          }
          alert(errmsg);
        });
      }
    }
    return event;
  });
})();

birthday は生年月日を入れる日付フィールドのフィールドコードの想定で、これに対する入力チェックを除いては前言通りの流れです。