CRUD model in a bootstrap modal with jquery, ajax - best practice - ruby-on-rails

i have a model, which i want to show edit and update in a dialog via ajax.
What i do at the moment:
To open the Modal and render the partial, i send an ajax request to controller#show with ujs
this is the link:
<a class="person-dialog" data-remote="true" data-type="script" href="/en/people/32"
onclick="return false">Fidel Markus Armstrong</a>
this runs the script in new.js.erb which renders the show partial inside the dialog and opens it.
To get the edit form, i do the same
<a class="person-dialog" data-remote="true" data-type="script"
href="/en/people/32/edit" onclick="return false">Fidel Markus Armstrong</a>
this runs edit.js.erb
Now: To update my model, i send the form data as json to the controller#update
<form accept-charset="UTF-8" action="/en/people/32" class="form-horizontal"
data-remote="true" data-type="json" id="edit_person_32" method="post">
if there is an error in the form, i do render_to_string(form_partial) inside the controller and respond with this inside of the json response.
Now i have the partial html inside of the json object. I do this, to get the rails error messages and fields_with_errors.
Is there a better way to do it? all the mix between script and json format and the partial html inside the json doesn't feel right.
This is the ajax.success for the form submit:
$('#dialog').on('submit', ->
$(this).find('form').bind('ajax:success',(evt, data, status, xhr) ->
if xhr.status == 201 # :created
url = data.url #this is en/people/:id
#Load show dialog on success - runs show.js.erb
$.ajax({
url: url,
type: 'get',
dataType: 'script'
})
else
#Render the dialog html including the error messages and fields with errors
#data.error is the partial
$('#person-dialog').html(data.error)
$('.field_with_errors input').first().trigger('focus')
$('.modal-header').prepend('edit')
)
please comment, if the question is not clear enough

Related

How do I use some inputted text in a html form to query a SQLite database?

How do I use some inputted text in a html form to query a SQLite database?
Forgive me, I am very new to Ruby on Rails (couple of days).
I am getting a user to enter a number followed by enter, I then want to query my SQLite db and return results to a variable. I am working in a Ruby on Rails project. Here is the code in my home.html.erb file.
<form name="myform" action="" method="get">
<input type="text" name="CardNumber" onkeypress="if(event.keyCode==13) {javascript:form.submit();>
<input type="submit" onClick="javascript:form.submit();"/>
<br>
</form>
<br>
<br>
<script type="text/javascript" language="JavaScript">
document.forms['myform'].elements['CardNumber'].focus();
</script>
First I think you'll want to do a post instead of a get. Then you need to point action to the correct route.
Usually in rails you'll have a model object instantiated on the action that renders the view with the form. Like if it's a form for creating a new User, on the controller#new action you'll have something like:
def new
#user = User.new
end
then on the view you'll have <%= form_for(#user) ... %>
Since you instantiated #user, form_for will be able to render correctly the path and action when you give it that object as a parameter. It won't be able to figure out if it's a multipart or whatever else, but the basis of routing it will.
But you don't need it obviously. Going back to your sample.
Imagine you have a route
post "save_payment_info", to: "payments#save_cc", as: :cc_save
Then a controller:
payments_controller.rb
def save_cc
cc_number_from_form = params[:CardNumber]
end
So you'll be able to access your form fields (as long as they're named correctly) on the params hash inside the controller.
You can do the same with Ajax and return a JSON response, etc.

Using devise gem, how does it prefill form values in the edit form and how can this be replicated elsewhere?

I am attempting to place the sign in, sign up and edit forms (from devise) into Bootstrap modals using partials. I have successfully done this by creating partials for the forms (wrapped in the modal code) and rendering them in application.html.erb as follows:
<%= render 'articles/sign_up_modal' %>
<%= render 'articles/sign_in_modal' %>
<%= render 'articles/edit_profile_modal' %>
At the top of application.html.erb I have:
<script type="text/javascript"> $(function () { $("#sign_up").modal({show:false });</script>
<script type="text/javascript"> $(function () { $("#sign_in").modal({show:false });</script>
<script type="text/javascript"> $(function () { $("#edit_profile").modal({show:false });</script>
Where "sign_up", "sign_in" and "edit_profile" represent the id's of the modals from the partials. The modal is then displayed by clicking a button in the _header.html.erb partial:
<%= link_to '<button type="button" class="btn btn-primary">Edit Profile</button>'.html_safe, "#edit_profile", "data-toggle" => "modal" %>
Everything works great except the Edit Profile modal form does not prefill the form with the appropriate values unless I am also on the edit page when I click the button to display the modal. How can I get the Edit Profile modal form to prefill the users data no matter which page they are on in the background?
Does this make sense? Please tell me how I might clarify my question. Thanks!
The answer was provided to me by u/alec5216 on reddit.
He said:
Take a look at the devise source.
https://github.com/plataformatec/devise/blob/master/app/views/devise/registrations/edit.html.erb
You'll see the form is bound to the "resource" variable which is going to be an instance of a user model. I bet if you use current_user in the partial instead of resource you'll have the desired effect.
This worked. See HERE for the full conversation.
In this case you will probably have to make an AJAX call to fetch the required data.
The data itself can either be JSON (for client-side rendering) or the complete html form rendered with the layout: false option. I usually go for the former because it is faster and easier to implement, unless your project is a single-page js application.
You can find more information on bootstrap ajax modals here on StackOverflow.

Submitting form with Html.ActionLink submit inside an Ajax Form

I have an AJAX.BeginForm() form and I want to submit an Html post as the final post. Here's my form
#using (Ajax.BeginForm("createSet", "Workout",
new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "divs",
HttpMethod = "POST"}, new { id = "myForm" }))
{
<div id="divs">
#Html.Partial("WorkoutSet", Session["WorkoutSetList"])
</div>
#Html.ActionLink("Submit", "SavePlan", "Workout", new { type = "submit" });
//<input type="submit" value="Submit" id="submit" name="command" />
<input type="submit" value="Create Set" name="command" />
}
Basically my "create set" button is used a lot for ajax calls which is working fine. I'm able to bind the model rendered from the partial view and update my model to session on every ajax call.
For my final step, I want to submit the whole form to the SavePlan Action along with the model values and then redirect to home page after that.
Problems faced:
First I tried the Ajax Submit button(the code commented out), a script redirects it to the SavePlan along with the model values rendered from partialview. Only problem is I could not redirect to HomePage and I've read that redirection cannot be done on an ajax call.
Second, I've tried the #Html.ActionLink which does goes to the SavePlan action and then proceeds to redirect to HomePage, BUT the model values were never passed. I've tried FormCollection but the values don't get passed either.
Please provide some advise on how to solve this? I've already spent 2 days on it and I'm tearing myself on it.
To recap:
Trying the Ajax way allows me to pass the model values but does not redirect to home page
Trying the Html way doesn't allow me to pass the model values but does redirect to home page.
You can redirect from an ajax POST - in your controller, you need to return a window.location javascript snippet:
return JavaScript(string.format("window.location = '{0}'", Url.Action("Index")));
There is an article here: Breaking out of an AJAX POST

rails controller action not being called

The problem I'm running into deals with rendering a partial. I basically have a link which should get updated after the user puts some text in a text field. The first time it works fine. The user types in the text, the link gets updated and then when the link is clicked the partial is rendered with the correct information. However when the text is changed the link also gets update with the new parameters to pass to the action but when the link is clicked it still renders the old partial and no call to the corresponding action is made. Here is my view code:
label.control-label for="color_servers" Colors
.controls
input.input-xxlarge type="text" name="colors" id="project_colors" placeholder="comma separated colors" onblur="getColors(this)"
a data-toggle="modal" id="color_target" href="#" data-target="#color_modal" (Show colors)
.modal.hide#color_modal
.modal-header
button.close type="button" data-dismiss="modal" aria-hidden="true" ×
h3 Color list
.modal-body
.modal-footer
a.btn href="#" data-dismiss="modal" aria-hidden="true" Close
And this is my partial which I am rendering:
ul
- for color in #colors
li #{color}
I'm displaying the partial with the information in a lightbox type display. Here is my javascript code for the onBlur event of the text field:
function getColors(elem){
if(elem.value.trim()){
$.ajax({
url: "/project/check_colors",
type: "GET",
dataType: "json",
data:{
colors: elem.value
},
success: function(data){
$('#color_target').attr('href','/project/show_colors?colors=' + data.color_list)
console.log(document.getElementById("color_target").href)
console.log(data.input)
console.log(data.color_list)
}
});
}
}
So in the javascript code when I look at the output of the href attribute in the console, it shows the correct link. And finally here is my controller code:
def check_colors
colors = params[:colors].gsub(/\s+/, "").gsub(/,+/,",")
colors = colors.chomp(",")
color_list = Color.expand_colorset(colors).map(&:fullname)
render 'index', :json => {
:servers => color_list,
:input => colors
}
end
def show_colors
colors_string = params[:colors]
#colors = colors_string.split(",")
puts #colors
render partial: 'color_list'
end
The color_list variable is an array of colors which I send back in order to update the link with. I know that the show_colors action gets called called the first time because the #colors variable's value is printed in my terminal however when I update the text in the textfield and I click on the link again the action is not being called even though the link gets updated because nothing is printed in the terminal. It seems as if the partial is being cached, if that is the problem how can I prevent that. Also when I try to render my partial as a full fledged view rather than a partial, the action is called correctly every time and it renders the correct information even after changing the text field contents, but when I do that then my lightbox functionality does not work correctly. Any help will be appreciated, thank you.
hi guys for anyone who is interested I figured it out. It is kind of hacky but it works for me. I added this piece of code in my javascript outside of all functions, and it cleared the cached ajax.
$('body').on('hidden', '.modal', function(){$(this).removeData('modal');});
Hopefully it will save someone time in the future.

binding remote form to bootstrap modal

I have a form in a bootstrap modal window that works perfectly - results are posted to the window upon form submission. This form is hardcoded into the html for the page.
Now i'm trying to load the form remotely. It loads the form just fine (puts it into modal-body). However, now when I click submit the modal goes away and the whole page goes to the form url.
Do i need to define my binding on the parent page, or in the remote url? My thought is that on pageload the id of the remote form is not known to the DOM. Also not sure if the remote url can reference a div on the parent page.
So it seems I'm out of sync - the parent DOM doesn't recognize the form since it's remote, and not sure that the remote form can bind to modal defined in the parent.
Any thoughts?
thanks!
from parent page:
<div class="modal hide fade in" id="mymodal">
<div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button></div>
<div class="modal-body"></div>
</div>
load remote url here:
<a class="tip" data-toggle="modal" data-target="#mymodal" href="/index.php/change_delivery/change/2" rel="tooltip" title="Change Delivery Date"><i class="icon-calendar"></i></a>
form from remote url:
<form class="form-horizontal" id="delivery_date_form" action="/change_delivery/submit_change">
....
</form>
and at the end of the remote url/form:
<script>
$(function() {
$('#delivery_date_form').bind('submit', function() {
$.ajax({
url: "change_delivery/submit_change",
type: "POST",
dataType: "html",
contentType: "application/html",
success: function(msg) {
// this is returned value from your PHP script
//your PHP script needs to send back JSON headers + JSON object, not new HTML document!
// update your "message" element in the modal
$("#modal-body").text(msg);
}
});
});
});
</script>
This is how I do it:
$(function(){
var $mymodal = $('#mymodal');
$('[data-toggle=modal]').click(function() {
$mymodal.attr('data-form-action', $(this).attr('data-remote'));
});
$mymodal.find('.save-button').click(function() {
$.post($mymodal.attr('data-form-action'), function(data) {
$mymodal.find('.modal-body').html(data);
});
});
});

Resources