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

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);
}
});
});

Related

Issue passing parameter to Rails controller using AJAX

I'm wanting to send a post request from my JavaScript code to my show action in Ruby on Rails which contains data that I want to store in an instance variable so I can save it on a form in my view and upload it to my server.
As you can see below, the parameter 'base64' is showing up in my rails logs, but when I try to call #base64 in my view, after grabbing the value in the controller, it's nil.
Any advice is appreciated, thanks!
View
var full_base64 = "data:image/jpeg;base64," + base64;
$.ajax({
data: 'base64=' + full_base64,
type: 'POST',
url: "/videos/show/<%=#video.id%>"
});
Controller
def show
#video = Video.find(params[:id])
if params[:base64].present?
#base64 = params[:base64]
end
end
Routes
post 'videos/show/:id', to: 'videos#show'
Rails server log:
Started POST "/videos/show/1" for 127.0.0.1 at 2020-01-22 12:59:40 -0600
Processing by VideosController#show as */*
Parameters: {"base64"=>"data:image/jpeg;base64,iV...
...
, "id"=>"1"}
Console
>>
#base64
=> nil
>>
If I understand correctly you are trying to pass AJAX to the show action in your controller. This is a very GENERALIZED answer as you have failed to include any of your HTML code and it looks like you don't have a button to fire the AJAX. But I'll try to point you in the right direction. You need to do something along the general lines of:
var full_base64 = "data:image/jpeg;base64," + base64;
$.ajax({
data: 'base64=' + full_base64,
type: 'POST',
url: "/videos/my_ajax_upload"
});
That will send your AJAX call to a controller method I've called my_ajax_upload but you can call it whatever you like. In your controller you would need something like:
def my_ajax_upload
#video.update(base_64: params[:base64])
respond_to do |format|
format.js {render :action => "base_64_response" }
end
end
This responds to the initial AJAX call by saving the param you sent to the DB and replying by calling a file called base_64_response.js.erb which might look something like:
$('#pic_upload').html('<%= escape_javascript(render :partial => 'base_64_response') %>');
Which will render the HTML file called base_64_response.html.erb which needs to contain the html code you want to appear in the page that called it.
<div id="pic_upload">
<%= #base64 =>
</div>
The cycle is load page -> do something to trigger AJAX call to controller method -> process AJAX call with controller method -> render JS file -> JS file replaces div in page with new html
You probably need to read up more on how AJAX works in Rails. This RailsCast might help http://railscasts.com/episodes/136-jquery-ajax-revised?view=asciicast
Just FYI - I have also noticed strange things in Rails if you do not explicitly define the content type. In your posted example you are not stating the contentType and it could be parsing nil for that reason. When posting base 64 data you can specify the content type as:
$.ajax({
data: 'base64=' + full_base64,
type: 'POST',
contentType: 'application/octet-stream'
url: "/videos/show/<%=#video.id%>"
});
and it may change what the controller parses for the body.
How to post an image in base64 encoding via .ajax?
Just use string instead of symbol for hash key
if params["base64"].present?
#base64 = params["base64"]
end

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?

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.

Javascript to Django views.py?

This may sound simple, but how do I send the data from a Javascript array in my index.html template to my views.py?
When the user clicks a "Recommend" button, my code calls a function that accesses my database and prints a name on the template.
def index(request):
if(request.GET.get('Recommend')):
sql_handler.recFunc()
context['name'] = sql_handler.name
return render(request, 'polls/index.html', context)
I have an array of checkbox values in Javascript that are calculated after the user presses "Recommend". I want to send it to my index view and use it as the parameter for another function.
So:
def index(request):
if(request.GET.get('Recommend')):
sql_handler.recommend()
context['name'] = sql_handler.name
//something??
tags = check_array_javascript
context['tags'] = tags
return render(request, 'polls/index.html', context)
How can I do this? I've been searching similar questions, but I'm new to Django and web development in general, so I either did not understand the answers or they didn't help me.
Alright, so for sending data from the client (JavaScript) to the backend (your Django app) you need to employ something called Ajax, it stands for Asynchronous JavaScript and XML.
Basically what it does is allowing you to communicate with your backend services without the need of having to reload the page, which, you would have to do using a normal POST or PUT form submission.
The easiest implementation is using jQuery. jQuery is first and foremost a DOM manipulation library but since its inception has grown to encompass much more than that.
A jQuery ajax call looks like this.
$(document).ready(function() {
$.ajax({
method: 'POST',
url: '/path/to/your/view/',
data: {'yourJavaScriptArrayKey': yourJavaScriptArray},
success: function (data) {
//this gets called when server returns an OK response
alert("it worked!");
},
error: function (data) {
alert("it didnt work");
}
});
});
This can then be checked for in your views.py
def index(request):
if request.is_ajax():
#do something
request_data = request.POST
return HttpResponse("OK")

Calling a function from a template using javascript

I'm very new to Django and there's something I'm trying to do that I don't seem to understand how. Right now I have elements of the page show/hide using javascript onclick. What I'm showing includes a dropdown box. What I would like to do is to call a python client side function I wrote, passing the choice and thus making changes to the database. The function is written and I have the frontend working but I don't understand how to take the submit button and get the javascript to not only show/hide elements but end up calling this function.
I don't want the page to refresh which my research so far leads me to believe I need to use AJAX and some sort of POST. Not really sure about that. I've got no experience with this kind of thing. I was wondering if I was on the right track or somewhere that might help me get there/a guide of some kind.
You are correct, you will need to use AJAX. Here is quick example:
template.html
<button type="button" id>Click Me!</button>
{% block inline_js %}
<script type="text/javascript">
$(document).ready(function () {
$(document).on("click",'#button',
function() {
$.ajax({
type: "POST",
data: { action: "delete"},
success: function(data){}
</script>
You can put your AJAX functions directly in your view. If you put nothing in your 'url' argument of your AJAX call, it will call itself (your view that called it).
views.py
def post(self,request, *args, **kwargs):
#Add a AJAX request check. If it is AJAX, redirect to AJAX function
if self.request.is_ajax():
return self.ajax(request)
#===========================================================================
# AJAX
#===========================================================================
def ajax(self, request):
response_dict= {
'success': True,
}
#Your SQL DROP code here...
return HttpResponse(simplejson.dumps(response_dict), mimetype='application/json')
You have to make POST request with JavaScript, and receive it on the server. The basic idea: you send data (JSON, maybe) from the client using XMLHttpRequest or $.ajax (if your project uses jQuery). It is in theory, I am not familiar with Django as well. But according to the docs Django can not handle AJAX by default, so it seems to be what you need: http://www.dajaxproject.com/dajaxice/

Categories