【发布时间】:2017-09-17 13:56:31
【问题描述】:
所以我对涉及 Javascript 的问题有了更好的理解。问题在于,在 AJAX 调用刷新 div 的内容之后,该 div 中的内容未链接或未针对 Javascript 初始化。我想要做的是让我的活动列表可以为用户排序。我使用优先级字段来保存活动的顺序,因此当用户刷新或离开页面时,顺序保持不变。
我收到的问题如下:
ActiveRecord::RecordNotFound(找不到 'id'=item 的活动):
因此,活动订单将不会被保存。这发生在 AJAX 调用和刷新之后,它事先正常工作,保存订单和诸如此类的东西。我尝试了一些解决方案,例如 one 并将 Javascript 移到部分没有成功。
我相信上面的错误是由于活动没有正确链接到 Javascript 文件导致它的 id 为“item”所以有谁知道如何解决这个问题或关于如何解决它的任何建议?谢谢!
主视图:
<!-- home.html.erb -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<!-- the jScrollPane script -->
<!--IF THE USER IS LOGGED IN, DISPLAY THE FOLLOWING -->
<% if current_user %>
<!--
<style>
.navbar {
background-color:#2F4F4F
}
</style>
-->
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href='home'>TimeTracker</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Signed in as <%=current_user.email %></a></li>
<li>
<%= link_to 'Sign Out', sign_out_path, method: :delete %>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
<h1 align = "center">Activities</h1>
<div id = 'activity_container'>
<ul id="Categories" class="connectedSortable">
<% @categories.each do |cats| %>
<% if cats.user_id == current_user.id%>
<div class="panel-group">
<div class="panel text-left">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" href="#collapse<%= cats.id%>">
<%= cats.c_name %>
</a>
</h4>
</div>
<div id="collapse<%= cats.id%>" class="panel-collapse collapse">
<ul id="category_activities" class=".connectedSortable">
<% cats.activities.each do |activity| %>
<li class="list-group-item" >
<% if activity.hidden == false || activity.hidden == nil%>
<label class="my_label"><%= activity.a_name %></label>
<!-- Delete Activity -->
<%= link_to destroy_act_path(activity.id), method: :delete, data: { confirm: "Are you sure?" } do %>
<i class="fa fa-trash-o" aria-hidden="true" title="Delete"></i>
<% end %>
<!-- Edit activity -->
<%= link_to edit_act_path(activity.id)do %>
<!--<button class="editActivity" style="border:none; padding:0; background-color: transparent">-->
<i class="fa fa-pencil fa-fw" aria-hidden="true" title="Edit" id="editActivity"></i>
<!--</button>-->
<% end %>
<!-- Hide activity -->
<%= link_to hide_act_path(activity.id), method: :post do %>
<i class="fa fa-eye" aria-hidden="true" title="Hide" id="item"></i>
<% end %>
<% end %>
<% end %>
</li>
</ul>
</div>
</div>
</div>
<% end %>
<% end %>
</ul>
<ul id="Activities" class="connectedSortable" >
<!-- List each activity in database -->
<% @activities.each do |activity| %>
<% if (activity.hidden == false || activity.hidden == nil) && activity.category_id == nil %>
<li class="list-group-item" id='<%=activity.id%>' style="list-style: none;">
<!-- Display activity name -->
<label class="my_label"><%= activity.a_name %></label>
<!-- Delete Activity -->
<%= link_to destroy_act_path(activity.id), method: :delete, data: { confirm: "Are you sure?" }, remote: true do %>
<i class="fa fa-trash-o" aria-hidden="true" title="Delete"></i>
<% end %>
<!-- Edit activity -->
<%= link_to edit_act_path(activity.id)do %>
<button class="editActivity" style="border:none; padding:0; background-color: transparent">
<i class="fa fa-pencil fa-fw" aria-hidden="true" title="Edit" id="editActivity"></i>
</button>
<% end %>
<!-- Hide activity -->
<%= link_to hide_act_path(activity.id), method: :post do %>
<i class="fa fa-eye" aria-hidden="true" title="Hide" id="item"></i>
<% end %>
</li> <!-- End of list item -->
<% end %> <!-- End of if statement -->
<% end %> <!-- End of activity loop -->
</ul>
</div>
<ul class="pager">
<li class="previous"><a href="#"><span aria-hidden="true">←</span>Previous </a></li>
<li class="next"><a href="#"> Next<span aria-hidden="true">→</span></a></li>
<!-- *****************NEW*********************** -->
<%= form_for @activity, :url => create_act_path, remote: true, data: {type: 'script'} do |a| %>
<%= a.text_field :a_name, id: 'a_name_field', placeholder: 'Activity Name'%>
<%= a.select :category_id, Category.all.collect { |c| [c.c_name, c.id] }, include_blank: "--No Category--" %>
<%= a.submit 'Create', id: 'submitButton', class: 'btn btn-primary'%>
<% end %>
<%= form_for @category, :url => create_cat_path, remote: true do |c| %>
<%= c.text_field :c_name, id: 'c_name_field', placeholder: 'Category Name'%>
<%= c.submit 'Create', id: 'submitButton', class: 'btn btn-primary'%>
<% end %>
<!-- Button for showing all hidden items -->
<%= link_to unhide_act_path, method: :post do %>
<button class="showHidden" >Show Hidden</button>
<% end %>
<!-- Button to sort -->
<button class="sortActivity">Sort</button>
<button class="doneSorting">Done Sorting</button>
<!-- ***************************************** -->
</ul>
<!-- IF THE USER IS NOT LOGGED IN, DISPLAY THE FOLLOWING -->
<% else %>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">TimeTracker</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li class="active">
</li>
</ul>
</div>
</div>
</nav>
<div class="loginContainer" align="center">
<h1 align="center">
<b>
Please log in or sign up
</b>
</h1>
<div class="container">
<br>
<%= button_to 'Login', sign_in_path, :method => 'get', class: 'btn' %>
<br>
<%= button_to 'Sign Up', sign_up_path, :method => 'get', class: 'btn' %>
</div>
<!--<div class="container" style="background-color:#D3D3D3">
<input type="checkbox" checked="checked"> Remember me
<span class="psw">Forgot <a align="center" href="#">password?</a></span>
</div> -->
</div>
<% end %>
<script type="text/javascript">
function changeImg(img) {
if (img.src == "<%=asset_path('_unfilledbubble.png')%>"){
img.src = "<%=asset_path('_filledbubble.png')%>";
}
else {
img.src = "<%=asset_path('_unfilledbubble.png')%>";
}
}
</script>
<script type="text/javascript">
$(document).ready(function() {
$(function () {
$('.scroll-pane').jScrollPane({showArrows: true});
});
});
</script>
<script>
$(document).ready(function(){
function callAll(){
set_positions = function(){
// loop through and give each task a data-pos
// attribute that holds its position in the DOM
$('.list-group-item').each(function(i){
$(this).attr("data-pos",i+1);
});
}
// ready = function(){
// call set_positions function
set_positions();
// ************NEW execept for #Activities
$('#Activities').sortable({
connectWith: ".connectedSortable"
});
$('#Activities').disableSelection();
// $('#Categories').sortable({
// connectWith: ".connectedSortable"
// });
// $('#Categories').disableSelection();
$('#category_activities').sortable({
connectWith: ".connectedSortable"
});
$('#category_activities').disableSelection();
// *******end of NEW
$('#Activities li').on('click','li',function (){
var myid = $(this).attr('id');
alert(myid);
});
// after the order changes
$('#Activities').sortable().bind('sortupdate', function(e, ui) {
// array to store new order
var updated_order = []
// set the updated positions
set_positions();
// populate the updated_order array with the new task positions
$('#Activities li').each(function(i){
updated_order.push({ id: $(this).attr('id'), position: i });
});
// send the updated order via ajax
$.ajax({
type: "PUT",
url: '/home/sort',
data: { order: updated_order }
});
});
}
$(document).ajaxComplete(callAll());
})
</script>
局部视图:
<!-- List each activity in database -->
<% @activities.each do |activity| %>
<% if (activity.hidden == false || activity.hidden == nil) && activity.category_id == nil %>
<li class="list-group-item" id="item" data-id="<%activity.id%>" style="list-style: none;">
<!-- Display activity name -->
<label class="my_label"><%= activity.a_name %></label>
<!-- Delete Activity -->
<%= link_to destroy_act_path(activity.id), method: :delete, data: { confirm: "Are you sure?" }, remote: true do %>
<i class="fa fa-trash-o" aria-hidden="true" title="Delete"></i>
<% end %>
<!-- Edit activity -->
<%= link_to edit_act_path(activity.id)do %>
<button class="editActivity" style="border:none; padding:0; background-color: transparent">
<i class="fa fa-pencil fa-fw" aria-hidden="true" title="Edit" id="editActivity"></i>
</button>
<% end %>
<!-- Hide activity -->
<%= link_to activity, method: :post, :controller => :activities, :action => :set_hidden_true, remote: true do %>
<button class="hideActivity" style="border:none; padding:0; background-color: transparent">
<i class="fa fa-eye" aria-hidden="true" title="Hide" id="item"></i>
</button>
<% end %>
</li> <!-- End of list item -->
<% end %> <!-- End of if statement -->
<% end %> <!-- End of activity loop -->
创建 Activity JS 文件:
<!--create_activity.js.erb-->
$('#Activities').html("<%= j (render 'object') %>");
家庭控制器:
class HomeController < ApplicationController
respond_to :html, :js
def new
end
def index
end
def home
@activities = Activity.all
@activity = Activity.new
@categories = Category.all
@category = Category.new
end
def create_activity
@activity = Activity.create(activity_params)
@activity.user_id = current_user.id
@activity.priority = @activity.id
@object = Category.all
@activities = Activity.all
@categories = Category.all
if @activity.save
flash[:success] = 'Activity created successfully'
else
flash[:notice] ='ERROR: Activity could not be create'
end
end
def create_category
@category = Category.new(category_params)
@category.user_id = current_user.id
#@category.priority = @category.id
@object = Category.all
@activities = Activity.all
@categories = Category.all
#@category.priority = @category.id
if @category.save!
flash[:success] = 'Category created successfully!'
else
flash[:error] = 'ERROR: Category was not saved!'
end
end
def destroy_activity
@activity = Activity.find(params[:id])
@activity.destroy
@object = Category.all
@activities = Activity.all
@categories = Category.all
end
def welcome
end
def hide_activity
@object = Category.all
@activities = Activity.all
@categories = Category.all
@activity = Activity.find(params[:id])
@activity.update_attribute(:hidden, true)
respond_to do |format|
format.html {redirect_to activities_url}
format.js
end
end
#NEW 4/15
def edit_activity
@activity = Activity.find(params[:id])
end
def update_activity
@activity = Activity.find(params[:id])
if @activity.update_attributes(activity_params)
flash[:success] = 'Activity updated successfully!'
else
flash[:notice] = 'Activity was not updated'
end
end
def unhide_all
@object = Category.all
@activities = Activity.all
@categories = Category.all
@activities = Activity.all
@activities.update_all(hidden: false)
# redirect_to root_path
end
def sort
params[:order].each do |key, value|
Activity.find(value[:id]).update_attribute(:priority, value[:position])
end
render :nothing => true
end
private
def activity_params
params.require(:activity).permit(:a_name, :category_id)
end
def category_params
params.require(:category).permit(:c_name)
end
end
更新
我尝试了following 并作为测试,将我在 html 中的脚本替换为以下内容:
$('#Activities').on('click','li',function (){
var myid = $(this).attr('id');
alert(myid);
});
在 Ajax 之前,当我点击一个活动时,它会正确地给我它的 ID。但是,在进行 Ajax 调用之后,当我尝试单击一个活动时,我得到了同样的错误,它声称找不到具有“id=item”的活动
【问题讨论】:
-
乍一看,我的猜测是
$(document).ajaxComplete(callAll());修复了一些与活动相关的内容。这意味着$('#Activities').html("<%= j (render 'object') %>");后面应该跟callAll();。如果这触发了很多 JavaScript,您应该提取修复活动 JavaScript 相关内容所需的部分到它自己的函数,并在最后调用该函数。 (在你替换了$('#activities').html(...)之后)。 -
这个问题可以通过明确指定 ajax 请求的触发位置来进一步解决。所以我们知道要遵循什么路径。
-
@JohanWentholt 为迟到的回复道歉。截至目前,我试图简单地让创建函数使用 AJAX,这样用户就不需要刷新整个页面,但是在 AJAX 调用之后,这就是我的问题发生的地方。
标签: javascript jquery ruby-on-rails ajax ruby-on-rails-5