有没有办法可以在视图中重新加载实例变量而无需重新加载页面?
我有一个AJAX帖子,它会创建一个新记录。我希望将该记录添加到现有的实例变量中。
所以我有action
之类的操作,它会处理action.html.erb
中的视图:
def action
@variable = Variable.where().to_a
end
然后我有一个AJAX请求执行action2
:
def action2
@new_record = Variable.create(params)
respond_to do |format|
format.html
format.json {render :json => @new_record.to_json}
end
end
有没有办法可以刷新@variable
实例变量以包含新创建的记录?
我可以向action
发送另一个AJAX请求吗?如果是这样,我如何在action
中检测到AJAX请求?
我用request.xhr?
尝试了这个^^,但是在执行JS StandardError
之后它会抛出一个奇怪的.click()
?
我不确定我是否朝着正确的方向前进,但如果我是,那么这就是我放在一起的所有代码......
我正在构建一个即时消息服务,我承认我完全是在一起破解原型。我知道有更清洁的方法来处理高流量负载,但我现在正在研究原型。
视图代码看起来像这样......有:HTML聊天框,我每隔2秒发出一个AJAX请求来查找新消息,在同一个函数中我向我所谓的action
发出AJAX请求上面(实际上命名不同的东西),在“刷新”功能之后我有一个.click()
函数来更新用户视图(刚刚提交的那个)。
<div id="wrapper">
<div id="menu">
<p class="welcome">Welcome, <b></b></p>
<p class="logout"><a id="exit" href="#">Exit Chat</a></p>
<div style="clear:both"></div>
</div>
<div id="chatbox">
<% @messages.each do |message| %>
<% if session[:email] == message.email %>
<!-- post to the right side -->
<div id="right-side">
<p>Email: <%= message.email %></p>
<p>Message: <%= message.message %></p>
</div>
<% else %>
<!-- post to the left side -->
<div id="left-side">
<p>Email: <%= message.email %></p>
<p>Message: <%= message.message %></p>
</div>
<% end %>
<% end %>
</div>
<form id="frm1" action="">
Message: <input id="message_input" type="text" name="fname"><br>
<!-- <input type="submit" value="Submit"> -->
<button name="submitmsg" type="submit" id="submitmsg">Try it</button>
</form>
</div>
<p id="demo"></p>
<script>
function retrieveMessages(){
var message;
$.ajax({
type:"GET",
url:"<%= get_messages_path %>",
dataType:"json",
data: {chat_id: <%= @message_info[:chat_id] %>,
last_message: <%= @messages.last.created_at.to_i %>},
success:function(data){
if (data != null){
console.log(data);
console.log(data.message);
message = data.message;
document.getElementById("chatbox").innerHTML += message + '<br>';
}
}
});
$.ajax({
type:"GET",
url:"<%= new_message_path %>",
dataType:"json",
success:function(data){
console.log("success!");
}
}
});
setTimeout(retrieveMessages, 2000);
}
$(document).ready(function(){
//get messages
setTimeout(retrieveMessages, 2000);
//send messages
$("#submitmsg").on('click', function(e){
e.preventDefault();
var x = document.getElementById("frm1"); //This is the form, and not the value of the textbox
var text = "";
var i;
for (i = 0; i < x.length ;i++) {
text += x.elements[i].value;
}
// document.getElementById("chatbox").innerHTML += text;
text_with_br = text + "<br>"
document.getElementById("chatbox").innerHTML += text_with_br;
document.getElementById("frm1").reset();
// console.log(document.getElementById("right"));
//Actual message is in 'text'
$.ajax({
url: "/messages",
method: "post",
data: { message: text,
chat_id: <%= @message_info[:chat_id] %>,
message_counter: <%= @message_info[:message_counter] + 1 %> },
dataType: "JSON",
success: function(response){
//do something,maybe notify user successfully posted their message
},
error: function(error){
console.log(error);
}
});
});
});
</script>
然后,对于action
行动(实际上是new
行动,我称之为@variable
的行为实际为@messages
:
def new
# debugger
# Message.create(:chat_id => 5)
if session[:email].nil?
#user not logged in
redirect_to new_session_path(:message => "need to login")
else
@user = User.where(:email => session[:email]).first
@message_info = Hash(email: @user.email, message_counter: 0, chat_id: Message.last.chat_id + 1)
@messages = Message.where(:chat_id => @message_info[:chat_id]).to_a
respond_to do |format|
format.html
format.json
end
end
end
然后执行AJAX请求以获取最新消息的操作(以便其他浏览器的查看者可以查看)如下所示...
def get
@new_message = Message.where(["created_at > ?", Time.at(params[:last_message].to_i)]).first
respond_to do |format|
format.html
# format.json {render json: @new_message}
format.json {render :json => @new_message.to_json}
end
end
更新
@eggroll建议下面的代码,但我遇到了引导问题
答案 0 :(得分:2)
从您的代码开始,下面是我尝试解决方案。我已经重新命名了元素,希望它能让这些代码更加自我记录,因此您更容易辨别我所做的事情。它并不完美,但它在Chrome中对我有用,所以希望它有所帮助。我假设起始chat_id
为1.如果不是,您可以在控制器的get_last_chat_id
方法中进行调整。
(注意:有几行代码对您来说是多余的,但我必须能够在我现有的一个应用程序中运行此代码。您还应该知道我&# 39; m使用Postgres,jQuery,Devise,HAML和Bootstrap 4 alpha。)
应用/控制器/ messages_controller.rb 强>
class MessagesController < ApplicationController
before_action :authenticate_user!
before_action :set_current_user_email, only: [:index, :display_all_messages]
before_action :set_current_messages, only: [:display_all_messages]
def index
end
def get_last_chat_id
last_chat_id = Message.pluck(:chat_id).max
if last_chat_id
puts '*** LAST CHAT ID: ' + last_chat_id.to_s
else
last_chat_id = 0
puts '*** LAST CHAT ID: ' + last_chat_id.to_s
end
respond_to do |format|
format.json { render json: last_chat_id }
end
end
def save_new_message
new_message = Message.new do |msg|
msg.email = params[:email]
msg.message_text = params[:message_text]
msg.chat_id = params[:chat_id]
end
puts '*** NEW MESSAGE EMAIL: ' + new_message.email
puts '*** NEW MESSAGE TEXT: ' + new_message.message_text
puts '*** NEW MESSAGE CHAT ID: ' + new_message.chat_id.to_s
# Source: https://makandracards.com/housetrip-deck/16879-jquery-ajax-success-done-will-not-run-callbacks-if-request-is-json-but-the-response-is-empty-typical-200
respond_to do |format|
if new_message.save
puts '*** NEW MESSAGE WAS SAVED!!!'
format.json { render json: { ok: true }, status: :ok }
else
puts '*** NEW MESSAGE WAS NOT SAVED!!!'
format.json { render json: { ok: false }, status: :unprocessable_entity }
end
end
end
def display_all_messages
respond_to do |format|
if @current_messages
format.js { }
else
puts '*** THERE ARE NO MESSAGES TO DISPLAY!!!'
end
end
end
private
def set_current_messages
@current_messages = Message.by_created_desc
end
def set_current_user_email
@current_user_email = current_user.email
end
def message_params
params.require(:message).
permit(:email, :message_text)
end
end
应用/模型/ message.rb 强>
class Message < ActiveRecord::Base
scope :by_created_desc, -> { order(created_at: :desc) }
end
<强>分贝/迁移/ 20160717000100_create_messages.rb 强>
class CreateMessages < ActiveRecord::Migration
def change
create_table :messages do |t|
t.string :email, null: false
t.text :message_text
t.integer :chat_id, null: false
t.timestamps null: false
end
add_index :messages, :chat_id, unique: true
end
end
app / assets / javascripts / messages.js (2016-07-17更新)
var messagesRefresher;
$(document).ready(function(){
// AJAX error handling, outputting error messaging to the console
$(document).ajaxError(function (event, jqxhr, settings, thrownError) {
console.log('EVENT: ' + JSON.stringify(event, null, '\t'));
console.log('JQXHR: ' + JSON.stringify(jqxhr));
console.log('SETTINGS: ' + JSON.stringify(settings, null, '\t'));
console.log('THROWN ERROR: ' + thrownError);
});
messagesRefresher = setInterval(refreshMessages, 2000);
$('#new-message-create-btn').on('click', function(e){
e.preventDefault();
$('#new-message-create-btn').addClass('no-display');
$('#new-message-form-wrapper').removeClass('no-display');
});
$('#new-message-cancel-btn').on('click', function(e){
e.preventDefault();
$('#new-message-form-wrapper').addClass('no-display');
$('#new-message-create-btn').removeClass('no-display');
});
$('#new-message-submit-btn').on('click', function(e){
e.preventDefault();
var newMessageEmail = $('#new-message-email').val();
var newMessageText = $('#new-message-text').val();
console.log('*** NEW MESSAGE EMAIL: ' + newMessageEmail);
console.log('*** NEW MESSAGE TEXT:');
console.log(newMessageText);
getLastChatId('/messages/get_last_chat_id').done(function(lastChatId) {
var newMessageChatId = lastChatId + 1;
console.log('*** NEW MESSAGE CHAT ID: ' + newMessageChatId)
saveNewMessage('/messages/save_new_message?email=' + newMessageEmail + '&message_text=' + newMessageText + '&chat_id=' + newMessageChatId).done(function(data) {
console.log('*** MESSAGE # ' + newMessageChatId + ' SAVED!!!')
$('#new-message-form-wrapper').addClass('no-display');
document.getElementById('new-message-form').reset();
$('#new-message-create-btn').removeClass('no-display');
refreshMessages;
});
});
});
});
function refreshMessages() {
displayAllMessages('/messages/display_all_messages').done(function(data) {
console.log('*** MESSAGES REFRESHED!!!');
});
};
function getLastChatId(url) {
return $.ajax({
url: url,
type: 'get',
dataType: 'json'
})
.fail(function() {
alert('AJAX Get Last Chat Id Error');
});
};
function saveNewMessage(url) {
return $.ajax({
url: url,
type: 'get',
dataType: 'json'
})
.fail(function() {
alert('AJAX Save New Message Error');
});
};
function displayAllMessages(url) {
return $.ajax({
url: url,
type: 'get',
dataType: 'script'
})
.fail(function() {
alert('AJAX Display All Messages Error');
});
};
$(window).unload(
function(event) {
clearInterval(messagesRefresher);
}
);
app / views / layouts / application.html.haml(摘录)(已添加:2016-07-18)
.
.
.
%head
%meta{ charset: 'UTF-8' }
%meta{ name: 'viewport', content: 'width=device-width, initial-scale=1, shrink-to-fit=no' }
-# Derived from: http://v4-alpha.getbootstrap.com/getting-started/browsers-devices/
%meta{ 'http-equiv' => 'X-UA-Compatible', content: 'IE=edge' }
= csrf_meta_tags
-# For page-specific meta tags
= content_for?(:meta_tag) ? yield(:meta_tag) : ""
%title Chatbox
= stylesheet_link_tag 'application'
= yield :page_stylesheet_link_tags
= javascript_include_tag 'application'
= yield :page_specific_javascript
.
.
.
应用/视图/消息/ index.html.haml 强>
- content_for :page_specific_javascript do
= javascript_include_tag 'messages.js'
#chatbox
%h1 Chatbox
= link_to 'New Message', 'javascript:;', id: 'new-message-create-btn', class: 'btn btn-sm btn-primary'
#new-message-form-wrapper.no-display
= form_tag messages_path, id: 'new-message-form' do
= hidden_field_tag 'new-message-email', @current_user_email
#new-message-form-label-wrapper
= label_tag 'new-message-text', 'Enter Your Message:'
#new-message-form-text-wrapper
= text_area_tag 'new-message-text', nil, rows: 6, cols: 70
#new-message-form-buttons-wrapper
= submit_tag 'Post Message', id: 'new-message-submit-btn', class: 'btn btn-sm btn-success'
= link_to 'Cancel', 'javascript:;', id: 'new-message-cancel-btn', class: 'btn btn-sm btn-secondary'
#display-messages-wrapper
#messages-column-left.pull-md-left
%h3 Messages From Others
#messages-other-users
#messages-column-right.pull-md-right
%h3 My Messages
#messages-current-user
应用/视图/消息/ display_all_messages.js.haml 强>
$('#messages-other-users').html('');
$('#messages-current-user').html('');
- @current_messages.each do |msg|
- if msg.email == @current_user_email
$('#messages-current-user').append("#{ escape_javascript render(partial: 'message', locals: { email: msg.email, message_created_at: msg.created_at, message_text: msg.message_text }) }");
- else
$('#messages-other-users').append("#{ escape_javascript render(partial: 'message', locals: { email: msg.email, message_created_at: msg.created_at, message_text: msg.message_text }) }");
应用/视图/消息/ _message.html.haml 强>
.message-wrapper
.message-attribution-wrapper
%span.message-attribution-label Posted by:
%span.message-attribution-text=email + ' on ' + message_created_at.strftime('%Y-%m-%d') + ' at ' + message_created_at.strftime('%I:%M:%S %p')
.message-text-wrapper
.message-label Message:
.message-text= message_text
app / assets / stylesheets / messages.scss (2016-07-17更新)
.no-display {
display: none !important;
}
#chatbox {
width: 90%;
margin: .5em auto;
}
#new-message-form-wrapper {
width: 48%;
padding: 1em;
border: 1px solid #ccc;
}
#new-message-form-label-wrapper > label {
font-weight: 700;
}
#new-message-form-buttons-wrapper {
margin-top: .5em;
}
#new-message-submit-btn {
margin-right: .3em;
}
#new-message-submit-btn,
#new-message-cancel-btn {
width: 8em;
}
#new-messages-form-wrapper,
#display-messages-wrapper {
margin-top: 1.5em;
}
#messages-column-left,
#messages-column-right {
width: 48%;
}
.message-wrapper {
width: 96%;
margin: 1em auto;
padding: .5em;
border: 1px solid #ccc;
}
.message-attribution-label,
.message-label {
font-weight: 700;
}
<强>配置/ routes.rb中强>
Rails.application.routes.draw do
resources :messages, only: [:index]
get 'messages/get_last_chat_id', to: 'messages#get_last_chat_id'
get 'messages/save_new_message', to: 'messages#save_new_message'
get 'messages/display_all_messages', to: 'messages#display_all_messages'
end
assests / javascripts / application.js (已添加:2016-07-18)
//= require jquery
//= require jquery_ujs
//= require jquery-ui
//= require bootstrap-sprockets
config / initialization / assets / rb (已添加:2016-07-18)
Rails.application.config.assets.precompile += %w( messages.js )
assets / stylesheets / application.scss (已添加:2016-07-18)
@import 'bootstrap_4a/bs_4a_variable_overrides';
@import 'bootstrap';
@import 'bootstrap_4a/bs_4a_customization';
app / assets / stylesheets / bootstrap_4a / bs_4a_variable_overrides (已添加:2016-07-18)
// http://v4-alpha.getbootstrap.com/getting-started/flexbox/
// Enabling flexbox means reduced browser and device support:
// Internet Explorer 9 and below do not support flexbox.
// Internet Explorer 10 has a few known quirks, requires using a prefix,
// and only supports the syntax from the old 2012 version of the spec.
$enable-flex: true;
app / assets / stylesheets / bootstrap_4a / bs_4a_customization (已添加:2016-07-18)
// http://v4-alpha.getbootstrap.com/getting-started/browsers-devices/
// As of Safari v8.0, fixed-width .containers can cause Safari
// to use an unusually small font size when printing.
// One potential workaround for this is adding the following CSS:
@media print {
.container {
width: auto;
}
}
body {
position: relative;
}
Gemfile (已添加:2016-07-18)
gem 'sass-rails', '~> 5.0'
gem 'jquery-rails'
gem 'jquery-ui-rails', '~> 5.0.5'
gem 'autoprefixer-rails', '~> 6.3.6'
gem 'bootstrap', '~> 4.0.0.alpha3'
更新:.js.erb 版 apps / views / messages / display_all_messages.js.haml
$('#messages-other-users').html('');
$('#messages-current-user').html('');
<% @current_messages.each do |msg| %>
<% if msg.email == @current_user_email %>
$('#messages-current-user').append("<%= escape_javascript render(partial: 'message', locals: { email: msg.email, message_created_at: msg.created_at, message_text: msg.message_text }) %>");
<% else %>
$('#messages-other-users').append("<%= escape_javascript render(partial: 'message', locals: { email: msg.email, message_created_at: msg.created_at, message_text: msg.message_text }) %>");
<% end %>
<% end %>
答案 1 :(得分:0)
您可以使用成功回调,并将div附加到$(“#chatbox”),以下是示例代码。
jQuery.ajax({
type: 'GET',
url: loadUrl,
data: dataString,
dataType: 'html',
success: function(response) {
$("#chatbox").append("
<div id="left-side">
<p>Email:"+ response[:email]+"</p>
<p>Message:"+ response[:message]+"</p>
</div>"
}
});