4

I have been working with Rails for a little while now. I got some stuff figured out, but I am struggling with this. I have an array of blog posts, rendered with just their title. In the controller the object looks simply like:

@articles

On my main page I render it through a partial and display just the title.

<%= render 'shared/article_view', :collection => @articles %>

This gives me a list of articles on the main page. When I click on the title I would like to open it up in a separate div. I have this working with a form. However, I'm not sure how to pass a parameter to the javascript that is getting called. I'm assuming I could pass the id to my view_article.js.erb file and could from there call

@article = Article.find_by_id(id)

and then

<p><%= @article.text %></p>

However, I have no idea how to pass any sort of parameter to this file. It may not even work and I could be entirely wrong in doing this. As I said, still learning. Anyway, thanks for the help!

3
  • I think I get what you're asking. You could try setting a data-id attr on your title element that contains your article id. In JS you would bind a click event to the title els, extract the ids, and make an ajax request to your articles endpoint and return json, which you would render in your div. Let me know if I'm on the right track... Commented Jun 28, 2012 at 4:38
  • That's about right. The issue with that is, I'm displaying multiple articles at a time and they're all <class = article>. Can I set a data-id in a class? I've accomplished this in the past (not in Rails) by setting a click listener that would trigger article_view(id) then I would use AJAX to get the relevant data. I feel like this should be possible in Rails... Commented Jun 28, 2012 at 5:05
  • Sorry for not being clear. A data-id is a custom HTML attribute you can set on any element. More info here. Essentially you'd bind the event to elements with class article and then infer the id from the attribute using jQuery. Commented Jun 28, 2012 at 5:22

2 Answers 2

4

My syntax might be a little off, but here's how I would go about it:

HTML

 <div data-id="<%= @article.id %>" class="article"><%= @article.title %></div>

JS

This might help explain how your js would work: http://guides.rubyonrails.org/asset_pipeline.html. What I usually do is create an object that contains all my bindings (and other methods) for a particular view. Then in the view, somewhere at the bottom, I'll create an instance of the object in a document ready block and bind up the DOM. All your js will be added by the manifest file (application.js) wherever you include it in your layout.

app/assets/javascripts/users.js

// Wraps your binding in a document ready function
// Runs as soon as the DOM is loaded
$(function() {
  $('.article').on('click', function() {
    var id = $(this).attr('data-id');
    $.get('articles/' + id, function(data) {
      // Handle the result
      $('.article-window').html(data);
    });
  });
});

app/assets/javascripts/application.js

  // This directive will include all your js files in the javascripts folder
  //= jquery
  //= require_tree .

app/views/layouts/application.html.erb (or wherever your layout is)

  // This adds all your js to the page
  <%= javascript_include_tag "application" %>

Rails Controller

class ArticlesController < ApplicationController
  respond_to :html, :json
  def show
    @article = Article.find(params[:id]
    respond_with do |format|
      format.json { render :json => @article }
    end
  end
end
Sign up to request clarification or add additional context in comments.

7 Comments

This makes sense. The only thing I'm really unsure about is where to put both the JS and the stuff for the Rails controller.
If anyone can help improve this answer, please feel free to send edits.
Sorry if this is a stupid question. As of now, is show the only place that the javascript would work?
Oh. Um no :) Not a stupid question. In the above example that js would run on every page. Your layout looks at the directives in application.js and -- in this case -- includes every file. Every item with class article would have the same click event.
If you only want it to work on the show page you can take that js above and move it from users.js directly to the bottom of the show view in a script tag. Then it will only run on that page. If you need it to run in some places and not others, let me know and we can walk through it.
|
0
class ArticleController

def show
  @article = Article.find(params[:id]
  respond_to do |format|
    format.json {render :json => @article.text } #now when u try to get host/articles.json/[id of article] you will get json with article object
  end
end

in article.js.erb(coffe in my example) you can convert coffe to js using http://js2coffee.org/ article.js.coffee

$('document').ready ->
  $('.article').live 'click', ->
    $.ajax
      url: 'articles/' + $(this).attr('id') #getting article#show with id of article
      complete: (data) ->
        article = JSON.parse(data.responseText)
        $('p').empty()
        $('p').append(article.text)

something like this email me to antiqe at gmail.com if you have errors

2 Comments

If I were to put the code in the ArticleController into different controllers, would it still call the file in article.js.erb?
@antiqe just a heads up, live() was deprecated in 1.7 in favor of on()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.