How to update both a responsive front-end and the database? - javascript

I am looking for ways to update the cart in my toy e-commerce application without having to reload the page and I was following this pen.
For example the code that is updating a product's quantity is the following:
$('.product-quantity input').change( function() {
updateQuantity(this);
});
It works nicely but the database is not updating of course at this point.
I was wondering what is the best way to update both the front-end and the database with products' quantities or similar operations? I am probably looking for AJAX but not sure what the latest best practices are (ideally with as less JS as possible).

Your updateQuantity() function has to make an ajax call to a method in your controller that handles the change in the database and responds to either json or js to manipulate the dom.
function updateCart(e){
$.ajax({
type: "patch",
url: 'your_route_to_method', //point to the route that updates the item
data: {
your_resource_scope: { quantity: e.value } //sanitize input in strong params
},
success: function (response) {
//response is the json you get back from your controller
//handle the logic of whatever happens in the dom after you update the quantity
}
});
}
I'd suggest attaching the id of the product you want to update to the input's parent so you can pass it to your route and remember to pass the value under the required scope so you can sanitize the input in your controller via strong_params.
In your controller:
def update
respond_to do |format|
if #your_resource.update(your_resource_params)
format.json { render json: { key: value } } #build the json you want to return
else
#handle failiure
end
end
If you decide to respond in js instead of json, you need to create a view with the same name as your method with a .js or .js.erb extension (instead of .html/.html.erb) and handle the successful response in js. In this view you have access to all the instance variables declared in your method. For example:
# => update.js.erb or your_custom_method_name.js.erb
$('#resource_#{ #your_resource.id }_price').replaceWith('<p>#{ #your_resource.quantity * #your_resource.price }</p>');
If you go this route, remember to delete the success part of your ajax call.

Related

How to pass data from Laravel View to Ajax or Javascript code without html div (id or class) - Laravel 5.3

So, currently I am passing values stored in Database MySQL to View (using Controller). I do simple querying ModelName::where()->first();.
I have my data right now in View. I want to use that data in Ajax or Javascript code that I am writing.
I can have 46 values and one way to do this is to have <div id="field1"></div> for 46 times set div style to display:none in css and in Javascript use document.getElementById('field1'); to access the values and finally, do whatever I want to do with it.
But I find this quite long and un-necessary to do as there is no point of printing all the values in html first and then accessing it. How can I directly get {{$data}} in Javascript?
myCode
public function index(Request $request){
$cattfs = Cattf::all();
$cattts = Cattt::all();
$cattos = Catto::all();
return view('/index',compact('cattfs'));
}
View
Nothing in the view. and I prefer it to be none.
Javascript and Ajax
$(document).ready(function()
{
init();
});
function init(){
my_Date = new Date();
var feedback = $.ajax({
url:url,
dataType: "JSON",
type: "GET",
}).success(function(data){
console.log(data);
//I have some data called data from url
//I want some data from controller like: cattf,cattt,catto
//I will combine url data and cattf and do simple arithmetic to it
//finally output to the view.
}).responseText;
}
One good way would be to actually make a small API to get your data. Let's say you wanted to retrieve users.
In the api.php file in your route folder:
Route::get('/posts', function () {
return Post::all();
});
and then you just need to use http://yourUrl.dev/api/posts as your URL sent in your .ajax() call to work with what you need.
I found best solution use this: https://github.com/laracasts/PHP-Vars-To-Js-Transformer
It takes values from controller directly to Javascript.

How to pass a JavaScript var into a Rails Controller

I'm looking to pass a JavaScript variable into a Rails Controller. The interesting part is that the variable is generated inside Canman, and I cannot use it (yet) outside of it.
This is probably just JavaScript and not necessarily related with Canman. But I'm just not sure what it is happening here.
The approach I'm following (but completely open if there is a better way) is to populate a hidden field with jQuery, just to access the data via params from the controller.
If possible (and if this is a good practice) I will like to avoid the form, and just call some JavaScript on click and then pass that variable to the controller.
View
= form_for #post do |form|
= form.hidden_field :base64
= form.submit
JavaScript
$('form').submit(function(event){
Caman('#canvas', img, function() {
var imageBase64 = this.toBase64();
alert(imageBase64); // works fine
$('#post_base64').val(imageBase64);
});
alert(imageBase64); // nothing
});
PostsController
def update
#post = Post.find(params[:id])
raise '¯\_(ツ)_/¯'
...
end
post_params
=> {"base64"=>""}
Also, I read that an option could be to make an AJAX request. However, I'm not sure how to proceed with that, yet.
At some point, I tried with a text_area instead of a hidden_field. The text_area got populated with the right data. However, params never got the data. If I got back via the browser button, the data was in the text_area, and clicking on submit one more time, populates the params as expected.
Thanks in advance!
Short answer: Ajax.
The goal was to send the value of a variable (a base64 image) to my rails controller, and once there, keep going just with Ruby.
At the end, I created a simple Ajax function to send data from my client (Image from browser) to my server (Rails Controller) via params
save_canvas.js
$(document).on('click', '.save_canvas', function() {
event.preventDefault()
var base64Data = canvas.toDataURL('png')
$.ajax({
type: "POST",
url: "http://localhost:3000/pictures/",
data: { image: base64Data },
success: function(post){ console.log('success') },
error: function(post){ console.log(this) }
})
})
pictures_controller.rb
def create
#picture = Picture.new(image: params[:image])
#picture.save
redirect_to #picture
end
I got support to achieve this here

How to post javascript data to a rails controller action?

I am using jQuery Shapeshift for drag and drop ordering for some lists that i have. All i need is to send or post this data below to my rails controller action so i can update the order.
This is what i get in my console each time i drag a list.
list_46
0
list_45
1
list_38
2
list_44
3
list_39
4
list_37
5
This is the exact path that i need to send that data above to. I have my routes setup correctly.
sortlists_boards POST /boards/sortlists(.:format)
Javascript Code
jQuery(function() {
$('.listwrap').shapeshift();
return $('.listwrap').on('ss-rearranged', function(e) {
$(this).children().each(function() {
#I need to send/post these two lines below to sortlists_boards_path
console.log($(this).attr("id"))
console.log($(this).index())
});
});
});
Some Github issues that might help
https://github.com/McPants/jquery.shapeshift/issues/64
https://github.com/McPants/jquery.shapeshift/issues/88
https://github.com/McPants/jquery.shapeshift/issues/48
First, modify your Javascript to create an array of ordered pairs and send it to your endpoint:
jQuery(function() {
$('.listwrap').shapeshift();
$('.listwrap').on('ss-rearranged', function(e) {
ordered_items = [];
$(this).children().each(function() {
ordered_items.push([$(this).attr("id"), $(this).index()]);
});
$.post('/boards/sortlists',
{ordered_items: JSON.stringify(ordered_items)},
function(data, status, jqXHR) {
// This is what gets rendered from your rails controller + action
});
});
});
Then, review what it looks like on the Rails side and do something with it
class BoardsController < ApplicationController
# ...
def sortlists
logger.info params[:ordered_items]
end
# ...
end
The output of that will go to log/development.log
Create/Update a JavaScript object on each drag and drop and send an ajax request to the controller, where u can read the object and store in the database.

Recommended way to redirect to same view and perform server side code from a client side event in MVC

I am having a hard time deciding on an appropriate way to Perform some server side functionality and then redirecting to the same View in my ASP.Net MVC project.
I am trying to call an Action after the selected index changed client side event of my combobox.
One way I can think of is to change the window.location to the url of my Action and pass the data i need via the query string like this
function SelectedIndexChanged(s,e)
{
window.location.href = "/MyController/MyAction?" + s.GetValue();
}
I also see lots of people saying you should use jquery ajax for this
function SelectedIndexChanged(s,e)
{
$.ajax({
url: 'MyController/MyAction',
data: { value: s.GetValue() },
success: function(){
alert('Added');
}
});
}
My Action looks something like this where i set some cookie values using the value and Set View bags values depending on the selected index.
public ActionResult SelectedIndexChanged(string value)
{
//Do some processing
//Set cookie values
SetViewBags(value);
return Redirect(Request.UrlReferrer.ToString());
}
Is there a better approach to accomplish my task, I am leaning more towards changing the location.href as it is simpler, but i'm not sure if this is good practice?
EDIT
To Clarify this Combobox is a Devexpress MVC extension so I will have to handle the "SelectedIndexChanged" client side event.
This Combobox is also on my layout page so it appears on every view in my project. So when it is changed i will need to to call the same Action no matter what page it is on
As you've indicated that your form is in your layout (not a view), I recommend you look at using a view partial. Fortunately, MVC has already provided an example with their view partial (can't remember the name) that has the login and logout buttons. If a user clicks logout, some javascript is fired and the form is submitted. This will redirect the user; however, you could also send the original address (referrer) as a parameter to your server method and then redirect to that page afterward.
You could always use an Html.Action
function SelectedIndexChanged(s,e)
{
#Html.Action("ActionName", "ControllerName", {optional route values})
}

How to submit form and update element on the page without refresh, in Rails 4

I'm having a lot of trouble trying to do something that I imagine would be fairly simple.
I have a list of items, let's say, todos. At the bottom of that list I have a text field where I add new items to that list. I want to make it so that the new items are added to the bottom of that list dynamically, without a full page refresh, like in a chat window.
I made the submit form remote: true and it successfully submits without reloading the page, but I can't get the new item to appear at the bottom of the list at the same time. I have to refresh the page to see the changes.
I tried a few different approaches I found on SO (there's no shortage of similar questions here) and the web, and even a gem called Sync, but each of them had errors and problems of their own and I couldn't get any to work properly. Each of them could be its own SO question. So instead I ask: Is there a "recipe" that is sure to successfully implement this in Rails 4?
let's say, now you have a user form to submit,
<%=form_for #user,remote: true%><%end%>
And you also have a controller,
UsersController
In your controller, you have a function,
def create
#something
end
which is for the form.
the only thing you need is to modify the function like
def create
#something
respond_to do |format|
format.js
format.html
end
end
then in your view side, under directory of view/users/ , create a create.js file, in the file, you can do the js action, like get the new record, and append the new record to the users list.
reference:
http://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#form-for
There are various ways to do what you are asking. My approach would be:
Create an AJAX call to the controller that passes the parameters of the form
Inside the controller, you save/update things and then return a JSON object
On the success callback of the AJAX function, you append a list item/table row, using the object values
The code could be something like this:
model.js
$(function() {
$("#submit_button").on("click", function(event) {
event.preventDefault();
$.ajax({
type: "POST",
url: "your_controller_url",
data: "your_form_data"
success: function(result) {
// Append the result to a table or list, $("list").append(result)
},
});
});
});
controller.rb
def your_action
# Do your stuff
# return JSON to the ajax call
end
Well, this is just a skeleton. I prefer doing things this way. (Because i hate the js.erb approach)
Here is rails 5, hope it will help someone ( it still works on rails 4 ):
Try this ajax example:
In 'routes.rb':
# set the route that ajax can find the path to what controller in backend
get '/admin/some_great_flow', to: 'great_control#great_flow'
In 'great_control_controller.rb' controller:
# this function in controller will response for ajax's call
def great_flow
# We can find some user or getting some data, model here.
# 'params[:id]' is passed by ajax that we can use it to find something we want.
#user = User.find(params[:id])
# print whole data on terminal to check it correct.
puts YAML::dump(#user.id)
# transform what you want to json and pass it back.
render json: {staff_info: #user }
end
In 'app/views/great_control/index.html.erb' view:
<div>
<label>Staffs</label>
<%=select_tag(:staff, options_from_collection_for_select(#staffs, :id, :name), id:"staff_id", required: true)%>
</div>
<script>
//every time if option change it will call ajax once to get the backend data.
$("#staff_id").change(function(event) {
let staff_id = $("#staff_id").val()
$.ajax({
// If you want to find url can try this 'localhost:prot/rails/info/routes'
url: '/admin/some_great_flow',
type: 'GET',
dataType: 'script',
data: { id: staff_id },
// we get the controller pass here
success: function(result) {
var result = JSON.parse(result);
console.log(result['staff_info']);
// use the data from backend for your great javascript.
},
});
});
</script>
I write it for myself.
You can see the changes using javascript.
For eg lets consider a controller Mycontroller with action index and you are submitting form on index.
Then create a file in views my_controller/index.js.erb
To reflect changes use javascript in this template.
Definately remote sends the ajax call, so to see the changes you need some manipulation using javascript.
Thanks

Categories