レコード一覧画面でボタン押下時に、指定のレコードのサブテーブルに行を追加する

お世話になっております。

 

https://cybozudev.zendesk.com/hc/ja/community/posts/200907434-JavaScript%E3%81%A7%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%AE%E8%A1%8C%E8%BF%BD%E5%8A%A0

上記を参考に、レコード一覧画面に設置したボタンを押下→対象のレコードにあるサブテーブルに

行を追加するコードを書きましたが、動作しません。

現在のコードは以下の通りです。(GETで、対象のレコードは正常に拾えています。)

======================================================================================

//ボタン押下時のイベント
bthozon.onclick = function () {

var masterAppId = 123;
var query = ‘レコード番号="’ + recno + ‘"’;

// CSRFトークンの取得
var token = kintone.getRequestToken();
// 登録先アプリの設定
var appURL = kintone.api.url(‘/k/v1/record’);

kintone.api(
kintone.api.url(‘/k/v1/records’, true),
‘GET’, {
app: masterAppId,
query: query
},
function(resp) {

//レコードがあった場合の処理
if (resp.records.length) {

var insertedRow = { // テーブルへの追加行
“value” : {
“tb1” : {
“value” : “テストです”
},
“tb2” : {
“value” : “テストです”
},
“tb3” : {
“value” : “テストです”
},
“tb4” : {
“value” : “テストです”
},
"tb15 : {
“value” : “テストです”
}
}
};

resp.records[0].テーブル.value.push(insertedRow); // 取得したレコードJSONのテーブルの最終行に追加

// JSONの設定
var strJSON = ‘{ “app”: masterAppId,“id”: recno, “record” : { “テーブル” : { “value” :’ + resp.records[0].テーブル.value + ‘}},“REQUEST_TOKEN”:"’ + token + ‘" }’; // テーブル部分をリクエスト用JSONに組込み

var xmlhttp = new XMLHttpRequest();

xmlhttp.open(“PUT”, appURL, false);
//xmlhttp.open(“PUT”, appURL, true);
xmlhttp.setRequestHeader(‘X-Requested-With’,‘XMLHttpRequest’);
xmlhttp.setRequestHeader(‘Content-Type’,‘application/json’);
xmlhttp.send(strJSON);

if (xmlhttp.status == 200) {
//成功した時の処理
window.alert(“アタックリスト「” + recname + “」への電話履歴を追加しました”);

}else{ //削除失敗
//失敗した時の処理
}

//レコードがなかった場合の処理
} else if (!resp.records.length) {
window.alert(“レコードはありませんでした”);
}

}); //GETのresp終了

} //電話内容保存ボタンのクリックイベント終了

======================================================================================

 

ボタン押下時に、コンソールを開いてエラーを確認すると、

「xmlhttp.send(strJSON);」の行に×マークが出ており、エラー内容は以下の通りでした。

「Failed to load resource: the server responded with a status of 400 (Bad Request)」

 


var strJSON = ‘{ “app”: masterAppId,“id”: recno, “record” : { “テーブル” : { “value” :’ + resp.records[0].テーブル.value + ‘}},“REQUEST_TOKEN”:"’ + token + ‘" }’; // テーブル部分をリクエスト用JSONに組込み


上記部分の記載に問題があるのでしょうか。

 

誤りのある部分などご指摘いただければ幸いです。

y-shikiさん

おそらくappURLで定義されているリクエスト先が間違っていることが原因だとは思いますが、kintone.api.urlメソッドにtrueを渡した場合はどうなりますでしょうか?

瀧ヶ平 様

 

「xmlhttp.open(“PUT”, appURL, true);」に変更して実行した結果、

Failed to load resource: the server responded with a status of 400 (Bad Request)のエラーメッセージは変わりませんでしたが、

追加で以下のようなメッセージも表示されました。

{“message”:“認証に失敗しました。セッション認証には、「X-Requested-With」ヘッダーが必要です。”,“id”:“1505999166-2019403605”,“code”:“CB_JH01”}

 

以下のナレッジを参考に、リクエスト方法で間違いがあるかさがしておりますが、見つけられていません。

■kintone REST API リクエスト

https://cybozudev.zendesk.com/hc/ja/articles/202166310-kintone-REST-API-%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88

 

PUTの際は「var appURL = kintone.api.url(‘/k/v1/record’);」というリクエスト方法ではエラーとなるのでしょうか?

y-shikiさん

説明が足りずすいません、そうではなくappURL = kintone.api.url(“/k/v1record”) の部分を kintone.api.url(“/k/v1/record”, true) にするという意味です。
ゲストスペースのアプリの場合は、REST APIのリクエスト先が違うため、kintone.api.urlメソッドの第2引数にtrueを渡して得たurlにアクセスする必要があります

瀧ヶ平 様

 

理解が足らず申し訳ありません。

var appURL = kintone.api.url(‘/k/v1/records’, true);としたときのエラーは

var appURL = kintone.api.url(‘/k/v1/records’);と同じ内容のエラーとなりました。

 

今回のアプリはゲストスペースではありません。

 

もう少し、リクエストの方法を勉強したいと思います。

y-kishiさん

見る限りではおそらくXMLHttpRequestを利用する際にAPI認証をしていないことが原因かと思います。
kintone.APIメソッドを利用した形に書き直すか、こちら(https://cybozudev.zendesk.com/hc/ja/articles/201941754-REST-API%E3%81%AE%E5%85%B1%E9%80%9A%E4%BB%95%E6%A7%98)を参考に認証情報を設定すれば解決するかと%E3%82%92%E5%8F%82%E8%80%83%E3%81%AB%E8%AA%8D%E8%A8%BC%E6%83%85%E5%A0%B1%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8C%E3%81%B0%E8%A7%A3%E6%B1%BA%E3%81%99%E3%82%8B%E3%81%8B%E3%81%A8)

リクエストヘッダーに「xmlhttp.setRequestHeader(‘X-Cybozu-Authorization’,‘***************************’);」と

認証情報を追記しましたが、エラー内容が変わりませんでしたので、

kintone API で Promiseを使用してみました。

 

以下ようにコードを書いたのですが、サブテーブルに行が追加されませんでした。

=============================================================

//レコード一覧画面でのイベント※「recno」は予め取得済み
//ボタン押下時のイベント
bthozon.onclick = function () {

var masterAppId = 123;
var query = ‘レコード番号="’ + recno + ‘"’;

return new kintone.Promise(function(resolve, reject) {
var params = {app: masterAppId, query: query};

kintone.api(‘/k/v1/records’, ‘GET’, params, function(resp) {
resolve(resp);
});

}).then(function(resp) {

//レコードがあった場合の処理
if (resp.records.length) {

var insertedRow = { // テーブルへの追加行
“value” : {
“recallday” : {
“type”: “DATE”,
“value” : “テストです”
},
“時刻” : {
“type”: “TIME”,
“value” : “テストです”
},
“person” : {
“type”: “DROP_DOWN”,
“value” : “テストです”
},
“受け入れ” : {
“type”: “SINGLE_LINE_TEXT”,
“value” : “テストです”
},
“callresult” : {
“type”: “MULTI_LINE_TEXT”,
“value” : “テストです”
}
}
};

resp.records[0].サブテーブル.value.push(insertedRow);

//レコードがなかった場合の処理
} else if (!resp.records.length) {
window.alert(“アタックリストにレコードはありませんでした”);
}

//レスポンス終了の記載
}).then(function(resp) {
return event;
});

} //ボタンのクリックイベント終了

=============================================================

XMLHttpRequestに代わる方法としてpromisを使用してみたのですが、

「resp.records[0].サブテーブル.value.push(insertedRow);」といった指定はできないのでしょうか?

y-kishiさん

記載されているPromiseでのコードを見る限り、レコード更新のPUTリクエストが記述されていないため、レコード更新が行われていないのだと思います。

なので、

kintone.api(kintone.api.url("/k/v1/records"), "GET", params).then(function(resp) {
// respからレコードを取得、編集し更新用のレコードオブジェクトを record として定義する
return kintone.api(kintone.api.url("/k/v1/record"), "PUT", {app: appId, id: recordId, record: record});
}).then(function(res) {
// 更新後の処理
});

のようにする必要があります

 

瀧ヶ平 様

 

ご回答ありがとうございます。

 

// respからレコードを取得、編集し更新用のレコードオブジェクトを record として定義する

 

理想としては、ボタンの押下イベントで対象レコードのサブテーブルに行を1行だけ追加したかったのですが、

PUTするためにはサブテーブルの全行を取得し、その情報の最後尾に追加する行の情報を追加するという動作が必要なのですね。

 

対象レコードによってサブテーブルの行数がまちまちなので、for文で配列の結合する方法などを考えてみます。

お世話になっております。

 

https://cybozudev.zendesk.com/hc/ja/community/posts/204397936-%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%AE%E8%BF%BD%E5%8A%A0

上記URLを参照しコードを書いたところ、無事サブテーブルに行が追加されました。

 

ただ、このコードではサブテーブルの末尾に行が追加されてしまいます。

希望としては、先頭の行に追加したいのですが、以下コードのどの部分を変更すればそのような動きになりますでしょうか。

 

「//subtable = subtable.unshift(appended_subtable); // 既存と追加分のサブテーブルを結合」を試してみたのですが

先頭の行には追加されませんでした。

 

ご教示いただければ幸いです。

==============================================================

//var existing_subtable = record[“<サブテーブル>”].value; // 既存のサブテーブル

var existing_subtable = resp.records[0].<サブテーブル>.value; // 既存のサブテーブル

var subtable = []; // 最終的にPUTするサブテーブル

var appended_subtable = []; // 追加したいサブテーブル

// 既存のサブテーブルを抽出
for (var i = 0; i < existing_subtable.length; i++) {
subtable.push(existing_subtable[i]);
}

appended_subtable = {
“value” : {
“tb1” : {
“type”: “DATE”,
“value” : app10
},
“tb2” : {
“type”: “TIME”,
“value” : app11
},
“tb3” : {
“type”: “DROP_DOWN”,
“value” : app13
},
“tb4” : {
“type”: “SINGLE_LINE_TEXT”,
“value” : app6
},
“tb5” : {
“type”: “MULTI_LINE_TEXT”,
“value” : app7
}
}
};

subtable = subtable.concat(appended_subtable); // 既存と追加分のサブテーブルを結合

//subtable = subtable.unshift(appended_subtable); // 既存と追加分のサブテーブルを結合

var put_record = {}; // レコード更新用オブジェクト
put_record[“<サブテーブル>”] = {
value: subtable
};

// 更新処理
kintone.api(kintone.api.url(‘/k/v1/record’, true), ‘PUT’, {
app: masterAppId,
id: respId,
record: put_record
});

==============================================================

y-kishiさん

先頭に追加したいのであれば

subtable = [].concat(appended_subtable, subtable);

とすれば可能です

瀧ヶ平 様

 

「subtable = [].concat(appended_subtable, subtable);」と変更したところ、

サブテーブルの先頭に行が追加され、希望する機能を実装することができました。

 

遅い時間にも関わらずご対応いただきありがとうございました。