How to create d3 graph using data from Rails database - javascript

I learned to create d3 graph using the d3 book, in which all the dataset is included directly in the <script> tag, which is in turn included in the html body.
I now want to use d3 in my rails app, but I don't know how to:
Pass data from my Rails database to my d3 script
How to "partial out" the javascript? I have seen materials on "unobstrusive javascript", but they are usually about AJAX form submission and I have a hard time converting that to graph drawing (i.e. including a <div> with graph drawn using app data).
There is still not an answer that deals with both of these issues yet, so hopefully this becomes a reference for future Googlers.

In my opinion requesting the data via AJAX would be the "cleanest" way to do that. You could use jQuery's ajax method to do a GET request to say '/get_data.json' ( which you have to add to your routes.rb), which would return you a JSON with the data.
Something like this.
//your JS file
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: '/get_data',
dataType: 'json',
data: "{}",
success: function (received_data) {
var div_where_to_draw = "div.mygraph";
your_d3_function(div_where_to_draw, received_data);
},
error: function (result) {
}
});
function draw_histogram(where_to_draw, data_to_draw){
//Your d3js code here
}
(Note that this JS code is a remake of the answer here)
This is how your controller providing the data could look like(note I made a new controller, you might not want to do that and just use a new action in an existing controller):
#app/controllers/data_controller.rb
class DataController < ApplicationController
def get_data
respond_to do |format|
format.json {}
end
end
end
And this is how your data could look like:
#app/views/data/get_data.json
[1,1,2,3,5,8,13,21,34,55]

Related

Rails 5: Respond to AJAX call with HTML (instead of javascript)

(Rails version 5.1.2)
I would like to respond to AJAX with HTML rather than javascript for much the same reasons as outlined in this stack overflow question.
However, I can't actually get it to work.
I'm using form_for with remote: true to send the request via AJAX. Note that I've also experimented with data: {type: :html}.
My controller action has the line render layout: !request.xhr? and has an associated view. It's this view that I want sent back to the client.
Yet the client-side code:
$("form").on('ajax:success', (e, data, status, xhr) ->
console.log xhr.responseText #using console.log data produces same result
)
Gives:
Turbolinks.clearCache()
Turbolinks.visit("http://localhost:3000/...", {"action":"replace"})
Where's the HTML?
Unless I am completely misunderstanding what you want to do, this should be what you are looking for:
Javascript:
$.ajax({
// remember to add this route to your routes file
url: "products/ajax_render",
success: function(data){
$('.some_div').html(data['html'])
},
});
Ruby on Rails:
def ajax_render
# render some view and store it in a variable
html = render "products/your_view"
# return it inside the json response
render json: { html: html }
end
Am I missing something?

Symfony - Ajax and Twig

I am working on Symfony2 project. And now want to add some dynamic actions.
I want to use jQuery and Ajax calls and API.
Below I wrote my project model.
Issue is there where I put "?" on the picture.
For example I have comments in my page and 2 buttons "oldest" "newest".
Basically on the page load TWIG load comment to my view and everything works fine.
Then I want to click on the button to change way of display comments. But want to do this without reloading a page.
I click btn -> run JavaScript -> connect byt AJAX with API controller -> take back data from database ... And here I stuck
I have data in JSON but have no idea how to load them into my view instead a date loaded by Twig at the beginning.
That's a serious wall on my way to dynamic changes on web page.
Thinking about:
Creating all the view in JavaScript and replace twig data on the view using jQuery like .html() or something - but there would be a lot of HTML code in JavaScript script, not sure that's right way
Maybe you know how to solve that issue in more elegant way?
It is not a Twig, but a JQuery concern. Here is an example.
Route:
my_symfony_route:
path: /get-filtered-list
defaults: { _controller: "CompanyMyBundle:Comment:getFilteredList" }
methods: POST
Controller
public function getFilteredListAction(Request $request)
{
$param1= $request->request->get('param1');
$param2= $request->request->get('param2');
$result = array();
//Fill $result with DB request
return new JsonResponse($result);
}
JQuery request
$.ajax({
type: 'POST',
url: "{{ path('my_symfony_route') }}",
data: { param1: 'value', param2: 'value' },
dataType: 'json',
success: function (data) {
//Handle your JSON data to update the DOM
$.each(data, function(index, element) {
$('#myDivId').append($('<div>', {
text: element.name
}));
});
}
});

Update user attribute from Coffeescript?

How can I in Rails write a Coffeescript function to update a database column? I guess an Ajax call of sorts would be ideal:
id = $('#document').attr('data-document-id')
$.ajax
url: "/documents/#{id}/update_attr"
type: "GET"
success: (data) ->
console.log(data)
Is something like this the only way? Or is there something better?
Well, keep in mind that frontend code (html, css, js) cannot access the database directly. So you need an AJAX request.
REST best practices would require you to use a POST/PUT/PATCH method instead of the GET method which should never change the state of the application.
Also, you are not passing any value to the Rails backend.
$.ajax
url: "/whatever/#{id}"
type 'POST'
data:
key: value
success: (data)->
console.log data
On the Rails side you need to setup the appropriate route in config/routes.rb:
post '/whatever/:id', to: 'some_controller#some_action'
Still ideally, following the best practices, you probably have some sort of
resources :apples
already mapped to an ApplesController. You now have to implement the action, which will be like this:
def update
#object = Whatever.find(params[:id])
if #object.update(key: params[:key]
render json: { success: 1 }
else
render json: { success: 0 }
end
end
That implementation is not complete (it does not handle HTML requests, multi-key updates and other fancy things), but still it should solve your problem.

How to call action on onclick-javascript in ruby on rails

I want to perform an action do file in controllers/static_pages_controller.rb:
def fileopen
my_file = File.new("public/CHNAME1.txt","w")
my_file.write "\tfasf"
my_file.close
end
(it work well when i define it in helper and call it in view.)
in myview.html.erb, i want some thing like <button id="button" onclick="readfile()" />
How can I do that?
I tried in application.js
function readfile() {
alert('readfile work')
$.ajax({
alert('ajax work')
url: "/fileopen",
type: "POST",
##don't know what to do to make fileopen work
}
});
}
routes.rb
match '/fileopen', to:'static_pages#fileopen', via: 'get'
and it's seem nothing happen. Only the first alert work.
In answer to your question directly, you have to be able to handle the JS request in the controller. This is typically done by using the respond_to block in Rails, like this:
def fileopen
respond_to do |format|
format.js {
my_file = File.new("public/CHNAME1.txt","w")
my_file.write "\tfasf"
my_file.close
}
end
end
This code may give you some sort of a response with your current code, but it might be the case that you need to appreciate better how Ajax & Rails work in order to help you better
How Ajax Works
Ajax is a javascript technology which sends an "asynchronous" request to other pages on your website. By their nature, asynchronous requests are done completely independently of your main HTTP request, and basically act like a "pseudo" browser -- working in the background
Ajax is used to pull data from JS-enabled endpoints (which are handled with the respond_to function in Rails, which you can then use to modify your page in some way. A lot of people get confused with Ajax, but it's actually quite simple -- it's just javascript which pulls data from another page, allowing you to manipulate your page with that data
Using Ajax In Your Views
The reason why this is important for you is because you mentioned you didn't know what to do with the success callback of your app. Hopefully my explanation will show you that the success part of the $.ajax call should be used to append the data you receive from the controller on your page
This can be done in this way:
$("#button").click(function() {
$.ajax({
url: "/static_pages/fileopen",
type: "POST",
data: {name: $(this).val()},
success: function (data) {
// append data to your page
$("page_element").html(data);
}
});
});

Using Javascript to Add/Remove Users in Rails Admin Interface

In a Ruby on Rails application, I want to be able to place a User's username in a input text box, press an 'Add' button, and have them appear underneath with their details. Then, I can simply remove them from the list if I want using another button.
How does one connect Javascript and Rails database to complete such a task specifically with those buttons? While Javascript isn't a strength of mine, I'm more puzzled by how to extract and modify the Rails database using Javascript. For reference, I'm also using MongoDB.
What would be the best way to approach this?
Here is the jQuery and AJAX code that I'm using to 'POST' to the server endpoint 'admin/popular/users.json', but I'm not sure how to get Rails to create a new user in the database using my Popular::User model.
$(document).ready(function() {
$('.add-to-popular-users-button').click(function(event){
event.preventDefault();
var addToPopularUsersBtn = $(this);
var userToBeAdded = $('input[name=popular_user]').val();
var data = { 'popular_user': {'username': userToBeAdded, 'category': 'popular'} };
var url = "/admin/popular/users.json";
$.ajax({
url: url,
data: data,
dataType: 'json',
type: 'POST',
success: function(e) {
alert('Great success!');
}
});
});
});
Here's my Popular::User model:
class Popular::User
include Mongoid::Document
include Mongoid::Timestamps
POPULAR = 'popular'
field :category, default: POPULAR
index :user_id
belongs_to :user
validates_presence_of :user_id
validates_uniqueness_of :user_id
def self.popular
user_ids = self.where( :category => POPULAR ).map(&:id)
User.where(:_id.in => user_ids)
end
I am not familiar with rails framework, but you can do it using ajax. You can send an ajax post request to controller method which will creae a user, create a table row(or recreate the table), and returnd html place in table.
A simple example is:
$.ajax({
type:'post',
data:{} //user data,
dataType: 'json', //or any other
url: 'page_or_method', //page or method that will return html
success: function (data) {
$('div#userTable').html(data); //in case data contains the table
}
});
Read about $.ajax method (jQuery), or you can use XMLHttpRequest if you don't whant to use jQuery.
So, I was able to figure this out with a bit of testing. But, basically, you can either do this with AJAX/jQuery or with Rails inherent RESTful architecture, i.e., HTTP verbs like calling :delete, and associating it with a particular UI button.
One important idea that you should recognize with AJAX is that whatever data you send to the right server endpoint with a 'POST' or 'DELETE' verb or what have you, it will get picked up by the appropriate controller action. In other words, if I'm sending data via 'POST' to the '/popular/users.json' endpoint to create something, the def create method will be able to manipulate data afterwards. Then, you can assign the data to an ivar in the controller action to be interpreted and manipulated in the UI view corresponding to the controller action.

Categories