Using same form as local and remote both in rails for filtering purposes - ruby-on-rails

Scenario:
I have a form that does some filtering. For the sake of simplicity, let's assume I have a form that has three input options:
<%= form_tag(some_path,method: :get) do %>
#..checkboxes for option 1
#..radiobuttons for option 2
#..checkboxes for option 3
<%= submit_tag "submit" %>
<% end %>
<p>You have a total of: COUNT results.</p>
Required Output:
What I want is the functionality when a user clicks on any checkbox or radio button, (essentially a change in any input field), by ajax request should be generated to a path that returns a COUNT of total results, and I will update the COUNT inside p tag with that returned count number.
And when the user clicks on submit button, the default GET request should be generated.

I added this script for ajax request, and it is working perfectly fine.
<script>
$(".option").change(function(){
var type = $("input[name='type[]']:checked").map(function () {
return this.value;
}).get();
$.ajax({
url: "/gre",
type: "put",
dataType: "json",
data: {custom: 'true',type: type},
success: function (response) {
var count = response["count"];
$('#count').html('Your session will have a total of '+ count + ' questions.');
}
});
});

Related

How to use Ajax for nested form on active admin rails

Please help me out with this problem. I am new on rails
I am trying to use the ajax method to get values on the active admin nested form. But only the top of the form gets dynamic values. After changing values on the top one form on the nested form then ajax makes a request then it changes the values(i.e. update the form values).
But after adding a new buy line item then ajax makes a request but doesn't update the values on the form i.e.same values for every new buy line item.
my js code
app/assets/javascripts/buys.js
// for nested buyline items of buys resources
$('.lineItem').change(function () {
$.ajax({
url: '/admin/get_buys_buy_line_item',
type: 'GET',
dataType: "json",
data: {
product_id: $('.lineBuyProduct').val(),
buy_quantity: $(".lineBuyQuantity").val(),
buy_quantity_unit: $(".lineBuyUnit").val(),
buy_price: $(".lineBuyAmount").val(),
},
success: (data) => {
alert(data);
// if (data == null) {
// document.getElementById('lineQuantity').value = ' ';
// document.getElementById('lineAmount').value = ' ';
// }
// else {
// document.getElementsByClassName("linebuyQuantity").value = data['1'];
// document.getElementsByClassName('linebuyAmount').value = data[0];
// console.log("Dynamic select OK!")
// }
}
});
});
});
My active admin forms
f.inputs 'Line Items', class: "lineItem" do
table do
thead do
tr do
th 'S.N', class: 'form-table__col'
th 'Product', class: 'form-table__col'
th 'Quantity', class: 'form-table__col'
th 'Unit', class: 'form-table__col'
th 'Amount', class: 'form-table__col'
th 'Expiry Date', class: 'form-table__col'
th 'Destroy', class: 'form-table__col'
end
end
end
f.has_many :buy_line_items, new_record: 'Add Buy Line Item', heading: false, allow_destroy: true do |x|
x.input :sn, label: false
x.input :product, label: false, as: :select2, collection: Product.drop_down_options,
input_html: { required: true, class: 'lineBuyProduct' }
x.input :buy_quantity, label: false, input_html: { required: true, class: 'lineBuyQuantity' }
x.input :buy_quantity_unit, label: false, collection: Unit.all.pluck(:name),
input_html: { class: 'lineBuyUnit' }
x.input :buy_price, label: false,
input_html: { required: true, class: 'lineBuyAmount' }
x.input :expiry_date, as: :date_picker, input_html: { style: 'width:auto' }, label: false
end
end
Some of my screenshots of how my program behaves and what my expectations are
In this image my first selection of product on buy line iteme then on request we can see json are renderd
But in this image after selecting another product again same json data are rendered that means doesn't update with different respective product values
And there are also some problems on active admin blaze theme, after adding class on form then it changes to legend color and add item button colors to light brown
This picture is about after removing custom class name lineItem.But, after removing this class then ajax doesn't hit for that form
Might be i faced such problem due to nested form's class on active admin.While i used default class of those form from inspect then it even doesn't hit to that form for ajax request.
So, please expert team help me to slove this problem.
If you want to send the data to create a new entity(record), you need to use the http POST method: https://api.jquery.com/jquery.post/
The GET request it just retrieves an already existing entity. Probably that's why you can read some data after an ajax call, but it's not updated.
More about the differences between GET and POST methods:
When should I use GET or POST method? What's the difference between them?
If this fix doesn't work, check the rails logs.
I have never used anything related to Ruby, and I'm not completely sure if I understood your question. I'm assuming you have problems with the AJAX behavior for new items in the list. Considering that, I think your problem could be related to attaching the "change" event to the new items. I think there might be many different other ways to get the behavior you want, but I will just elaborate on your solution using JS.
From the activeAdmin's code you can see they trigger an event called "has_many_add:after" when a new item was successfully added to its parent. Considering that, I would try changing your Javascript code to:
// for nested buyline items of buys resources
$("#buy_line_items").on("has_many_add:after", function(event, fieldset, parent){
fieldset.change(function () {
$.ajax({
url: '/admin/get_buys_buy_line_item',
type: 'GET',
dataType: "json",
data: {
product_id: $(this).find('.lineBuyProduct').val(),
buy_quantity: $(this).find(".lineBuyQuantity").val(),
buy_quantity_unit: $(this).find(".lineBuyUnit").val(),
buy_price: $(this).find(".lineBuyAmount").val()
},
success: (data) => {
alert(data);
// if (data == null) {
// document.getElementById('lineQuantity').value = ' ';
// document.getElementById('lineAmount').value = ' ';
// }
// else {
// document.getElementsByClassName("linebuyQuantity").value = data['1'];
// document.getElementsByClassName('linebuyAmount').value = data[0];
// console.log("Dynamic select OK!")
// }
}
});
});
});
I'm very confident that this will work, mainly because I don't have how to try it (if you give me the generated HTML maybe it'd help me). You can try it and reach back to see if it worked or if any adjustment is required.
You might want to change your commented lines accordingly. Also about the identifier "#buy_line_items" I'm not sure if it exists in the rendered HTML so you might need to adjust that as well.

Rails check_box_tag - get all the values checked in view(haml) file

So I have multiple checkboxes on my page. I collect all of them like shown in the code below. I would like to access the values of the array before passing it on to the controller
= check_box_tag "names[]", ob.name, false, class: 'cbx'
I am able to pass them with my older code
%fieldset.actions
= form.submit "Upgrade", :class => 'button'
Logs:
Processing by SomeController#create as HTML Parameters:
{"utf8"=>"✓",
"names"=>["ron", "jacob"], "commit"=>"NameButton"}
Ok. So i would like to access all values in my haml files. Is there a way before i submit my form, I can access which checkboxes are selected.
I would like to pass the names[] to my controller as a parameter.
=link_to script_name1, { :action => 'create', :names => 'dontknowhowtopassnames[]' }, :method => :post
Rails version - 3.2.17
You can do that using Javascript.
The exact implementation depends on what exactly you want to do with those values, but you could, for example, use the change event to track and maintain an array of all checked values :
/*
* should properly init this array if some of your checkboxes are already
* checked when the form is loaded
*/
var names = [];
$(document).ready(function() {
$(document).on('change', '.cbx', function() {
var name = $(this).val();
var idx = names.indexOf(name);
if ($(this).prop('checked') && idx === -1) {
names.push(name);
} else if (!($(this).prop('checked')) && idx >= 0) {
names.splice(idx, 1);
}
});
});
Updated with complementary answer:
To submit a form with a link instead of a button:
In your view, replace
%fieldset.actions
= form.submit "Upgrade", :class => 'button'
with
= link_to "Submit", "#", :class => 'submit_link'
Then in your Javascript, add the following inside the $(document).ready body:
$(document).on('click', 'a.submit_link', function(e) {
$(this).closest('form').submit();
e.preventDefault();
});
And that's it. You're making your life very complicated by trying to serialize the form data on your own while the form's submit() method can take care of it for you. You can serialize data on your own, and it's sometimes useful, for instance when dealing with AJAX, but in your case the default submit() is perfect for the job.

Auto refresh <div> without reload entire page

I'm trying to update the content of "mydiv" without refreshing the entire index page.
#mydata is given by mycontroller. I need to recalculate it every n seconds and pass it to "mydiv"
With "link_to" it works!
index.html.erb
<%=
link_to('refresh', '/mycontroller/index', :remote => true)
%>
<div id="mydiv">
<%=
#mydata
%>
</div>
index.js.erb
$('#mydiv').html('<%= escape_javascript(#mydata) %>')
Now I need to refresh the content of "mydiv" automatically every n seconds (so without click on the link). I have tried solutions from:
First Link
Second Link
but no luck.
In my application.js I have writed this:
function executeQuery() {
$.ajax({
//url: '/index',
success: function(data) {
$('#mydiv').html(data)
}
});
setTimeout(executeQuery, 500);
}
$(document).ready(function() {
setTimeout(executeQuery, 500);
});
For who is facing my same problem, I solved it by replacing
$('#mydiv').html(data)
with
$('#mydiv').load('/mycontroller/index #mydiv')
Use setInterval() instead of using setTimeout().
Ref: https://www.w3schools.com/jsref/met_win_setinterval.asp
function executeQuery() {
$.ajax({
type: 'GET',
url: 'example.com/url/', // Provide your response URL here.
success: function(data) {
$('#mydiv').html(data);
}
});
}
setInterval(executeQuery(), (n * 1000)); // Replace 'n' with how many seconds you want.
This code will run the executeQuery() method in every 'n' seconds interval. So that your requirement is accomplished.
Set layout to false in the action and just pass on the relevent content, not the entire page
def action1
<your code here>
end
def action2
<your code here>
render :layout => false
end
Your view for action2 should have content pertaining only to #mydiv.
A better solution would be to use a single action and change render options based on type of request. (Ajax or non ajax)

How to Access ajax call data in jqGrid

I have a ajax call to fetch data from server for the jqGrid in my rails application.
$(document).ready(function() {
colNamesData = ['Project', 'Activity', 'Description', 'Hours', 'Date','']
colModelData = [
{name:'projects.name',index:'projects.name', width:130, sorttype:"text"},
{name:'creation_date',index:'creation_date', width:130, sorttype:"date"},
{name:'buttons', index:'buttons', width:270, align:'center', search:false}
]
$("#time_sheet_table").jqGrid({
datatype: 'json',
colNames: colNamesData,
colModel: colModelData,
url: 'timesheets/timesheet_index_jqgrid?table_name = timesheet_index_jqgrid&',
mtype: "Get",
jsonReader: {
root: "rows",
page: "page",
total: "total",
records: "records",
id: "id",
repeatitems: true,
cell: 'cell',
button: "buttons",
},
Here's my controller code:
if timesheet.deletable?(#user)
#buttons = 1
buttons += "<div style='margin-right:55px'>"
buttons += "<a class='button delete-button' href='#' onclick=\"jQuery('#time_sheet_table').jqGrid('delGridRow', #{timesheet.id}, {});\"><span class='link'>Delete</span></a>" + "</div>"
end
#cell << {
:id => timesheet.id,
:cell => [timesheet.project_name,timesheet.creation_date.strftime("%Y-%m-%d"),buttons]
}
end
list_of_resources = {
"total" => total_page(timesheets.count,grid_id),
"page" => session[:page][:time_sheet_table],
"records" => timesheets.count,
"rows" => #cell
}
I want to access the value of #buttons from controller but unable to guess how to pass and access in my view so that i can put conditions like for ex...
<% if #buttons == 1 %>
colNamesData.splice(1,1);
colModelData.splice(1,1);
<% end %>
thanx
I am not Ruby on Rail developer, but if you work with jqGrid with any server technology, the best way would be to send only data and no HTML markup in the server response. jqGrid has custom formatter which allows you to construct any HTML fragmant which will be placed in the column. Instead of the current HTML fragment you could just send from the server the boolean value timesheet.deletable (as "true" and "false" or "1" and "0"). Inside of the custom formatter you have access to the whole row of data send from the server per rowObject parameter. Depend on the format of the data which you return from the server you should use named properties like rowObject.creation_date or array index rowObject[2].
One more remark. I don't recommend you to use any special characters in the name property of colModel. Instead of name:'projects.name' you should use name:'name' or name:'projects_name'. If the dot character will be do placed in the property names of the row of JSON data (it seems me not in your case) you should use jsonmap: 'projects.name' (see here).
The last remark: sorttype in the colModel will be used only for local data and will be ignored in case of datatype:'json'.

How can I update a page content with jQuery Ajax and ASP.NET MVC?

I have a ActionResult named "MyPeriods(string dateSelected)" and in the end of it, I have a ViewData["periods"] = listOfPeriods (and after that, I have my return View(), fininshing up my method). When no "date" is passed, "date" is today, otherwise, "date" is the date passed as argument. And this "date" is important to select all the periods and events relationed to it.
So, my ActionResult is sending a list of periods to my View. In my View, I have:
<div id="divEventsPeriods">
<% foreach(UserPeriod period in in (IEnumerable)ViewData["periods"])
Response.Write("<div>PERIOD: " + period.hourBeg + " - " + period.hourEnd + "</div>");
foreach(UserEvents event in period.UserPeriod) {
Response.Write("<div>EVENT: " + event.date + "<br />");
Response.Write("DESCRIPTION: " + event.description + "</div>");
}
%>
</div>
So, when I select a date in jQuery DatePicker, this selected date is passed as an argument to my ActionResult and all the process occurs. And, in the end of all, my page refreshes rendering all the Periods and Events of the selected date. One Period may have many Events.
So, the question is: how can I pass this selected date to my ActionResult, making all process occurs and the page becomes updated without refreshing?
I've tried this on DatePicker onSelect option:
$.ajax({
type: 'GET',
url: '/Admin/Schedule/MyPeriods/?dateSelected=' + dateSelected,
data: dateSelected
});
When I select a date, the $.ajax is called and debugging I could see that the selected date is passed correctly to my ActionResult and process occurs, but the page is not updated.
What am I doing wrong??
Thanks in advance!!
You need to add a success callback to the ajax call that will accept the returned data and update your page via DOM manipulation, for example, by replacing the contents of a DIV with the HTML (presumably) returned by your action. I'm assuming here that your action returns a ContentResult. If you are returning a JsonResult instead, then you'll need use the result and do what is necessary to update the DOM.
Take a look at the jQuery AJAX options page for more information.
EDIT I decided to do this in one method, but using IsAjaxRequest(). Your client side code may not need to change at all with the exception of using the partial as noted below.
public ActionResult ViewPage(DateTime dateSelected)
{
....do some stuff...
ViewData["dateSelected"] = GetPeriods( dateSelected );
if (Request.IsAjaxRequest()) {
return PartialView("PeriodDisplay", ViewData["dateSelected"]);
}
else {
return View();
}
// common code to populate enumerable
public IEnumerable<Period> GetPeriods( DateTime selected )
{
return ...data based on date...
}
PeriodDisplay.ascx : this should be a strongly typed ViewUserControl using a model of IEnumerable.
<%# Page ... %> /// page definition...
<% foreach(UserPeriod period in Model) { %>
<div>PERIOD: <%= period.hourBeg + " - " + period.hourend %> </div>
<% foreach(UserEvents event in period.UserPeriod) { %>
<div>
EVENT: <%= event.date %><br/>
DESCRIPTION: <%= event.description %>
</div>
<% } %>
ViewPage.aspx
...
<div id="divEventsPeriods">
<% Html.RenderPartial( "PeriodDisplay", ViewData["periods"], null ); %>
</div>
Your action need to return either html or text or whatever you want to show, or JSON objects that you then process in your javascript. From the jQuery.ajax documentation:
$.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
}
});
The msg variable in this case is the html / text that you get back from your action. Your action can return a partial view or something as simple as <p>Date Selected feb 12th 2009</p>. You can also use ("#message").html(msg) to insert html into your webpage.

Resources