javascriptのエラー解決に苦心したので、その記録。
状況
チャットアプリのメッセージ機能の更新を非同期通信上で、実施しようとしたところ、
投稿まで非同期で通信できなくなった。
問題のjsファイル
(function(){
var buildHTML = function(message){
console.log(message)
if (message.image){
console('1')
var html =
`<div class = "message" data-message-id=${message.id}>
<div class="messages__message" >
<div class="messages__message__info">
<div class="messages__message__info__member">
${message.user_name}
</div>
<div class="messages__message__info__date">
${message.created_at}
</div>
</div>
<div class="messages__message__text">
<p class="messages__message__text__content">
${message.content}
</p>
</div>
<img src=${message.image} >
</div>`
return html;
} else {
console.log('2')
var html =
`<div class = "message" data-message-id=${message.id}>
<div class="messages__message" >
<div class="messages__message__info">
<div class="messages__message__info__member">
${message.user_name}
</div>
<div class="messages__message__info__date">
${message.created_at}
</div>
</div>
<div class="messages__message__text">
<p class="messages__message__text__content">
${message.content}
</p>
</div>`
return html;
};
}
$('.new_message').on('submit', function(e){
e.preventDefault();
var formData = new FormData(this);
var url = $(this).attr('action')
$.ajax({
url: url,
type: "POST",
data: formData,
dataType: 'json',
processData: false,
contentType: false
})
.done(function(data){
console.log(data)
var html = buildHTML(data);
$('.middle').append(html);
$('form')[0].reset();
$('.middle').animate({ scrollTop: $('.middle')[0].scrollHeight},'fast');
$('input').prop('disabled', false);
})
.fail(function(){
alert('メッセージ送信に失敗しました');
})
})
var reloadMessages = function() {
//カスタムデータ属性を利用し、ブラウザに表示されている最新メッセージのidを取得
last_message_id = $('.message:last').data("message-id");
$.ajax({
//ルーティングで設定した通りのURLを指定
url: "api/messages",
//ルーティングで設定した通りhttpメソッドをgetに指定
type: 'get',
dataType: 'json',
//dataオプションでリクエストに値を含める
data: {id: last_message_id}
})
.done(function(messages) {
console.log(messages)
if (messages.length !== 0) {
//追加するHTMLの入れ物を作る
var insertHTML = '';
//配列messagesの中身一つ一つを取り出し、HTMLに変換したものを入れ物に足し合わせる
$.each(messages, function(i, message) {
insertHTML += buildHTML(message)
});
//メッセージが入ったHTMLに、入れ物ごと追加
$('.middle').append(insertHTML);
$('.middle').animate({ scrollTop: $('.middle')[0].scrollHeight});
$("#new_message")[0].reset();
$(".form__submit").prop("disabled", false);
}
})
.fail(function() {
console.log('error');
});
};
if (document.location.href.match(/\/groups\/\d+\/messages/)) {
setInterval(reloadMessages, 7000);
}
});
関連するhamlファイル
.messages
.messages__message
.messages__message__info
.messages__message__info__member
= message.user.name
.messages__message__info__date
= message.created_at.strftime("%Y年%m月%d日 %H時%M分")
.messages__message__text
- if message.content.present?
%p.messages__message__text__content
= message.content
= image_tag message.image.url, class: 'lower-message__image' if message.image.present?
問題解決までの変更点は以下のとおり。
1. jsファイル、"buildHTML"内で定義されたhtmlにreturn html;を2箇所追記する。(エラーの解決にはこれだけでよかった気もする...)
2. hamlファイルから".message"のクラスを削除、hamlファイルとscssファイルをそれに合わせて調整する。
3. そのままでは自動更新された文にcssが当たらないので、"div class="messages__message" "の記述を削除する。(本来は閉じタグも消去しなければいけないが、記述ミスで上記コードには表記されていなかった)
4. .done内の".message"でクラス指定されている部分のクラスを指定し直す。
変更後のコードは以下
jsファイル
$(function(){
var buildHTML = function(message){
if (message.image){
var html =
`<div class = "message" data-message-id=${message.id}>
<div class="message__info">
<div class="message__info__member">
${message.user_name}
</div>
<div class="message__info__date">
${message.created_at}
</div>
</div>
<div class="message__text">
<p class="message__text__content">
${message.content}
</p>
</div>
<img src=${message.image} >
</div>`
return html;
} else {
var html =
`<div class = "message" data-message-id=${message.id}>
<div class="message__info">
<div class="message__info__member">
${message.user_name}
</div>
<div class="message__info__date">
${message.created_at}
</div>
</div>
<div class="message__text">
<p class="message__text__content">
${message.content}
</p>
</div>`
return html;
};
}
$('.new_message').on('submit', function(e){
e.preventDefault();
var formData = new FormData(this);
var url = $(this).attr('action')
$.ajax({
url: url,
type: "POST",
data: formData,
dataType: 'json',
processData: false,
contentType: false
})
.done(function(data){
var html = buildHTML(data);
$('.middle').append(html);
$('form')[0].reset();
$('.middle').animate({ scrollTop: $('.middle')[0].scrollHeight},'fast');
$('input').prop('disabled', false);
})
.fail(function(){
alert('メッセージ送信に失敗しました');
})
})
var reloadMessages = function() {
//カスタムデータ属性を利用し、ブラウザに表示されている最新メッセージのidを取得
last_message_id = $('.message:last').data("message-id");
$.ajax({
//ルーティングで設定した通りのURLを指定
url: "api/messages",
//ルーティングで設定した通りhttpメソッドをgetに指定
type: 'get',
dataType: 'json',
//dataオプションでリクエストに値を含める
data: {id: last_message_id}
})
.done(function(messages) {
if (messages.length !== 0) {
//追加するHTMLの入れ物を作る
var insertHTML = '';
//配列messagesの中身一つ一つを取り出し、HTMLに変換したものを入れ物に足し合わせる
$.each(messages, function(i, message) {
insertHTML += buildHTML(message)
});
//メッセージが入ったHTMLに、入れ物ごと追加
$('.middle').append(insertHTML);
$('.middle').animate({ scrollTop: $('.middle')[0].scrollHeight});
$("#new_message")[0].reset();
$(".form__submit").prop("disabled", false);
}
})
.fail(function() {
console.log('error');
});
};
if (document.location.href.match(/\/groups\/\d+\/messages/)) {
setInterval(reloadMessages, 7000);
}
});
hamlファイル
.message{data: {message: {id: message.id}}}
.message__info
.message__info__member
= message.user.name
.message__info__date
= message.created_at.strftime("%Y年%m月%d日 %H時%M分")
.message__text
- if message.content.present?
%p.message__text__content
= message.content
= image_tag message.image.url, class: 'lower-message__image' if message.image.present?