所以我有这样的布局:
家/ index.html.erb:
<div class="optionscontainer btn-group btn-group-justified">
<%= link_to posts_path, class:"options btn btn-primary", remote: true do %>
<i class="fa fa-book optionseach" aria-hidden="true"></i>All posts
<% end %>
<%= link_to stories_path, class:"options btn btn-primary", remote: true do %>
<i class="fa fa-book optionseach" aria-hidden="true"></i>All stories
<% end %>
</div>
<div id="content" class="">
</div>
在posts_controller.rb
中我有:
def index
@posts = Post.all
respond_to do |format|
format.html #looks for views/books/index.html.erb
format.js #looks for views/books/index.js.erb
end
end
在stories_controller.rb
中我有:
def index
@stories = Story.all
respond_to do |format|
format.html #looks for views/books/index.html.erb
format.js #looks for views/books/index.js.erb
end
end
在我的观看次数/帖子/ index.js.erb
中$("#content").html("<%= j (render 'posts') %>");
在我的views / stories / index.js.erb
中$("#content").html("<%= j (render 'stories') %>");
我_posts.html.erb
views/posts
和_stories_html.erb
中的views/stories
当我点击帖子按钮时,会发生视图,但是当我点击故事按钮时,什么都没有渲染?
答案 0 :(得分:16)
好的,在进入解决方案之前,让我们了解request-response
周期。
当您搜索http://stackoverflow.com时,您会在client
(您的浏览器)向StackOverflow(SO)server
发送请求。客户端和服务器通过HTTP
协议进行通信,如果用户请求服务器知道的内容,则服务(发送)响应(html,css,js文件)。浏览器知道如何显示从服务器接收的html内容。每个浏览器都有自己的样式表(user-agent-stylesheet
),它还将样式应用于从服务器发回的html页面中链接的css文件中。请注意,这一切都发生在同步,而server
正在处理客户端的请求时,浏览器标签为inactive
,因为它正在等待服务器的访问响应。单击链接时会发生相同的过程。它会向服务器创建一个新请求。
来自服务器的响应可以是HTML
,JSON
,XML
等。您可能已经注意到,synchronous
通信不是我们一直想要的。< / p>
如果我们发出新的synchronous
请求,浏览器会再次提取HTML
,CSS
和JS
以及image
个文件(不要进入高速缓存)。我们不想为每个请求更新整个页面。
通常,只有部分页面在请求后更新,并且提供良好的用户体验。
这是Javascript擅长的地方。它可以异步地向服务器发出请求(网页不会重新加载),还可以使用名为AJAX
(Asynchronous Javascript XML)的内容更新页面的某些部分。
典型的AJAX请求是这样的。您向服务器发出请求,但这次是异步的,服务器以XML
响应,而不是HTML
和Javascript
解析XML
文档更新页面的一部分。尽管它现在被称为AJAX,但是现在,JSON用于跨服务交换信息。
因此,要发出AJAX请求,我们需要一个链接,点击后会发送XMLHttpRequest
(异步请求),服务器应该回复JSON
或XML
或者然后脚本应解析响应并更新DOM
(Document Object Model)。在Vanilla JS
(普通javascript)中发出AJAX请求很复杂,人们通常使用Jquery
的{{1}}方法发出AJAX请求(代码行数较少)。有关详细信息,请参阅http://api.jquery.com/jquery.ajax/。
但在ajax
中,它更容易。我们可以使用rails
(Unobtrusive Javascript)发出AJAX请求。让我们看看它在行动。
要使链接发送AJAX请求,您需要在UJS
帮助器中设置remote: true
。这会在生成的HTML中添加link_to
。
例如以下erb
data-remote=true
生成html
<%= link_to "All books", books_path, remote: true %>
确定。现在我们已经准备好发出<a data-remote="true" href="/books">All books</a>
个请求了。将代码修改为
AJAX
我假设你有控制器,模型和视图设置。同时在终端中执行<div style="margin-top:50px;" class="wrapper">
<div class="optionscontainer btn-group btn-group-justified">
<%= link_to posts_path, class:"options btn btn-primary", remote: true do %>
<i class="fa fa-book optionseach" aria-hidden="true"></i>All posts
<% end %>
<%= link_to stories_path, class:"options btn btn-primary", remote: true do %>
<i class="fa fa-rss optionseach" aria-hidden="true"></i>All stories
<% end %>
<%= link_to books_path, class:"options btn btn-primary", remote: true do %>
<i class="fa fa-users optionseach" aria-hidden="true"></i>All books
<% end %>
</div>
<div id="content">
<!-- The content goes here -->
</div>
以查看应用程序的现有路由。您应该看到以下内容(订单并不重要)
rake routes
注意:此处Prefix Verb URI Pattern Controller#Action
posts GET /posts(.:format) posts#index
stories GET /stories(.:format) stories#index
books GET /books(.:format) books#index
对应于返回的格式,可以是format
,html
,js
或xml
。
json
中的posts_path
指向url_helper
,这意味着每当向posts#index
应用程序中的服务器发出请求时,它首先到达路由器并且系统会调度到rails
中指定的相应controller
操作
在这种情况下,如果我们向routes.rb
发出请求,请求将被发送到books#index action。在操作中,您可以从http://localhost:3000/books
获取数据并将响应发送到客户端。
由于我们对AJAX感兴趣并且我们指定了database
,因此rails会期望将remote:true
响应返回给客户端(即JS
,它负责呈现内容动态地)。
我将解释如何处理script
的AJAX请求,并且您可以对其他控制器应用相同的想法。(BooksController
和posts
)。
stories
我们在这里做的就是告诉控制器在客户端请求JS响应时呈现class BooksController < ApplicationController
def index
@books = Book.all
respond_to do |format|
format.html #looks for views/books/index.html.erb
format.js #looks for views/books/index.js.erb
end
end
#other actions
end
,或者在HTML响应的情况下呈现index.js.erb
。当我们没有指定要呈现的文件时,rails如何知道呈现index.html.erb
或index.html.erb
?这是什么轨道很受欢迎.Rails遵循Convention Over Configuration。
实际上,index.js.erb
推断要从controller
名称呈现的模板。
下一步是使用action
来更新@books
div。在添加代码以呈现所有书籍之前,我们需要一个模板来渲染吗?这是部分进入的地方。部分是可重复使用的#content
_ books.html.erb view' and a partial in rails is prefixed with '_'. For example:
书籍。
创建部分is a partial for
app/views/books/_books.html.erb
现在创建<% @books.each do |book| %>
<div class="book">
#Display the fields
</div>
<% end %>
并添加以下内容:
app/views/books/index.js.erb
此单行将部分$("#content").html("<%= j (render 'books') %>");
呈现为_books.html.erb
div。等待。它是如何工作的?让我们分成几块。
#content
内的任何内容都是ruby代码。它的执行和值被替换为<%= %>
。 <%= %>
模板化工具允许您在erb
内编写ruby
代码。那么,这是做什么的呢?
javascript
它将呈现<%= j (render 'books') %>
,从参数推断为books/_books.html.erb
。它返回render
生成的html。
_books.html.erb
做什么?它实际上是j
方法的别名。它用于转义从部分escape_javascript
返回的内容。
解释_books.html.erb
html的原因会使这个答案更长。我强烈建议您在this SO帖子中阅读kikito的答案(第3个答案)。
因此,我们将html从partial传递为字符串(请注意escaping
周围的引号)到<%= %>
方法,该方法已添加到html
div中。而已!
我建议您检查服务器日志并浏览开发人员工具中的#content
选项卡,以深入了解AJAX的工作原理。
对其他控制器(Network
和PostsController
)执行相同的操作。
希望这有帮助。
答案 1 :(得分:0)
链接必须设置为remote: true
,并且必须指向不同的操作(或相同但接收不同的参数)。
这些动作必须响应js并渲染其js视图。
这将是这样的:
您的观点:
<div style="margin-top:50px;" class="wrapper">
<div class="optionscontainer btn-group btn-group-justified">
<%= link_to 'All Posts', posts_path, class: 'options btn btn-primary', method: :get, remote: true %>
</div>
<div id='placeholder'>
<%= render 'all_posts' %>
</div>
</div>
视图/帖/ index.js.erb的
$('#placeholder').html("<%= j (render 'all_posts') %>");
答案 2 :(得分:-2)
如你想通过单一方法索引#home实现这一点。然后你必须通过链接传递一些额外的信息
<div style="margin-top:50px;" class="wrapper">
<div class="optionscontainer btn-group btn-group-justified">
<a style="background-color:#4183D7;" href="<%= path_to_index_home(request: :p) %>" class="options btn btn-primary" data-remote=true><i class="fa fa-book optionseach" aria-hidden="true"></i>All posts</a>
<a style="background-color:#59ABE3;" href="<%= path_to_index_home(request: :s) %>" class="options btn btn-primary" data-remote=true><i class="fa fa-rss optionseach" aria-hidden="true"></i>all stories</a>
<a style="background-color:#81CFE0;" href="<%= path_to_index_home(request: :b) %>" class="options btn btn-primary" data-remote=true><i class="fa fa-users optionseach" aria-hidden="true"></i>all books</a>
</div>
<div data-load-partial>
<%= render 'name_of_your_default_partial' , locals: {collection: @collection} %>
</div>
</div>
现在我们必须编辑我们的控制器。在控制器顶部添加此行
ALLOWED_REQUESTS = { p: 'Post' , s: 'Story' , b: 'Book' }
将您的主页操作编辑为
@request = params[:request].blank? ? 'Post' : ALLOWED_REQUEST[params[:request].to_sym]
@collection = @request.constantize.all
现在是时候渲染适当的部分了。如果您有不同的表结构并且想要显示具有不同html的不同字段,那么您可以创建三个不同的部分,如_book.html.erb,_story.html.erb,_post.html.erb,您可以在家中调用它.js.erb文件
$('[data-load-partial]').html('<%= j render partial: "#{@request.downcase}" , locals: { collection: @collection } %>');
如果您想对这三种类型使用相同的部分,那么您可以将其作为
$('[data-load-partial]').html('<%= j render partial: "name_of_your_partial" , locals: { collection: @collection } %>');