I have a Modal with form and after submitting it with no validation error i'm trying to close Modal and refresh page with new results. But i can't get it to work. I have this code (Rails 3):
My Controller:
def create
#stuff = Stuff.new(params[:stuff])
respond_to do |format|
if #stuff.save
format.js
else
format.js
end
end
end
_addModal.html.erb
<div id="addModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Label</h3>
</div>
<div class="modal-body">
<p>
<fieldset>
<label></label>
<%= render 'form2' %>
</fieldset>
</p>
</div>
</div>
_form2.html.erb
%= form_for(#stuff, :remote => true) do |f| %>
<% if #stuff.errors.any? %>
<div id="error_explanation">
<div class="alert">
<h2><%= #stuff.errors.count %></h2>
<ul>
<% #stuff.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
</div>
<% end %>
<%= f.label :name %><br />
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
create.js.erb
<%- if #stuff.errors.any? %>
$('#addModal').html('<%= escape_javascript(render :partial => "form2") %>');
<%- else %>
$('#addModal').modal('hide').empty();
<%- end %>
Any ideas how I can get this to work?
Thanks!
Update:
Also i got few quetions:
1) In case there are validation errors create.js.erb returns new Modal with 'form2' content only- without #addModal layout. How can i fix it?
2) How can clear form after successful submision?
add this in your js.erb file to reload the page automatically
<%- if #stuff.errors.any? %>
$('#addModal').html('<%= escape_javascript(render :partial => "form2") %>');
<%- else %>
$('#addModal').modal('hide').empty();
window.location.reload();
<%- end %>
Related
I am using Rails-6, with Bootstrap-4.
I am using Bootstrap Card to display my form.
The form is simple with a lable,text field, file upload and submit button.
here is the outout
Here is code for my form:
<%= javascript_pack_tag 'photo', 'data-turbolinks-track': 'reload' %>
<div class="card text-center">
<div class="card-header">
Add New Photo
</div>
<div class="card-body">
<%= form_for #photo do |f| %>
<%= render "shared/errors", object: #photo %>
<%= f.hidden_field :image, value: #photo.cached_image_data %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :image %>
<%= f.file_field :image %>
<% if #photo.image_data? %>
<%= image_tag #photo.image_url(:medium) %>
Remove attachment: <%= f.check_box :remove_image %>
<% end %>
<%= f.submit %>
<% end %>
</div>
<div class="card-footer text-muted">
</div>
</div>
In my Javascript pack I have intercepted form submit event by using the javascript.
$(document).ready(function(){
function processForm(e) {
if (e.preventDefault) e.preventDefault();
alert('intercepted form submission');
/* do what you want with the form */
// You must return false to prevent the default form behavior
return false;
}
var form = document.getElementById('new_photo');
if (form.attachEvent) {
form.attachEvent("submit", processForm);
alert('attachEvent');
} else {
form.addEventListener("submit", processForm);
alert("addEventListener");
}
});
I noticed that when I put my complete form in Bootstrap-Card-Body (as in above code)then the event works as desired and the attached function executes on clicking submit button.
But when I put the Form-Submit button in Bootstrap-Card-Footer (as per code below) then on clicking the submit button the attached function does not execute.
<%= javascript_pack_tag 'photo', 'data-turbolinks-track': 'reload' %>
<div class="card text-center">
<div class="card-header">
Add New Photo
</div>
<div class="card-body">
<%= form_for #photo do |f| %>
<%= render "shared/errors", object: #photo %>
<%= f.hidden_field :image, value: #photo.cached_image_data %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :image %>
<%= f.file_field :image %>
<% if #photo.image_data? %>
<%= image_tag #photo.image_url(:medium) %>
Remove attachment: <%= f.check_box :remove_image %>
<% end %>
</div>
<div class="card-footer text-muted">
<%= f.submit %>
<% end %>
</div>
</div>
here is what it looks like.
moved form submit button in card-body
Why it happen? What concept I am missing? How do I make the attached event listner to fire when I Click Submit button placed in Card-Footer?
In this part of your example:
<div class="card-body">
<%= form_for #photo do |f| %>
<%= render "shared/errors", object: #photo %>
<%= f.hidden_field :image, value: #photo.cached_image_data %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :image %>
<%= f.file_field :image %>
<% if #photo.image_data? %>
<%= image_tag #photo.image_url(:medium) %>
Remove attachment: <%= f.check_box :remove_image %>
<% end %>
</div>
<div class="card-footer text-muted">
<%= f.submit %>
<% end %>
</div>
After Rails done compiling your view template to html it will look (roughly) like below:
<div class="card-body">
<form method="post" action="/photos" ...>
<input ... />
<input ... />
</div>
<div class="card-footer text-muted">
<input type="submit" ... />
</form>
</div>
It will not be a valid HTML at all. The first div (.card-body) lacks the closing </form> tag. But the second div (.card-footer) has an unexpected closing </form> tag. Browsers still gracefully handle this by closing the <form> tag before the first </div> for you, but the <input type="submit" ... /> button will be outside the form and so the submit button won't work anymore.
I recommend you to change your code like below. Just let the <form> tag surround your whole card:
<%= javascript_pack_tag 'photo', 'data-turbolinks-track': 'reload' %>
<div class="card text-center">
<%= form_for #photo do |f| %>
<div class="card-header">
Add New Photo
</div>
<div class="card-body">
<%= render "shared/errors", object: #photo %>
<%= f.hidden_field :image, value: #photo.cached_image_data %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :image %>
<%= f.file_field :image %>
<% if #photo.image_data? %>
<%= image_tag #photo.image_url(:medium) %>
Remove attachment: <%= f.check_box :remove_image %>
<% end %>
</div>
<div class="card-footer text-muted">
<%= f.submit %>
</div>
<% end %>
</div>
From my homepage I go to the register page by clicking "register" button, I will end up by a registration form. There, if mandatory fields are not filled out correctly, a modal would pop up and list the errors. Problem is, that the first try to register causes the modal like this :
However, if I refresh the page, modal works perfectly as supposed to. This is only happening when redirected through a register-button from a home page.
Here is my code: devise/registrations/new.html.erb
<div class="container">
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-content">
<div class="modal-body">
<button type="button" class="btn btn-secondary dismiss-close" data-dismiss="modal">Close</button>
</div>
</div>
</div>
<div class="center-items-register">
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), remote: true) do |f| %>
<%= render "devise/shared/error_messages" %>
<div class="row 1">
<div class="column">
<div class="field">
<%= f.label :first_name, class: 'required' %><br />
<%= f.text_field :first_name, class: 'form-control' %>
</div>
</div>
<div class="column">
<div class="field">
<%= f.label :last_name, class: 'required' %><br />
<%= f.text_field :last_name, class: 'form-control' %>
</div>
</div>
</div>
<div class="row 2">
<div class="column">
<div class="field email">
<%= f.label :email, class: 'required' %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: 'form-control' %>
</div>
</div>
</div>
<div class="row 3">
<div class="column">
<div class="field">
<%= f.label :password, class: 'required' %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %>
<%= f.password_field :password, autocomplete: "new-password", class: 'form-control' %><br />
</div>
</div>
<div class="column">
<div class="field">
<%= f.label :password_confirmation, class: 'required' %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password", class: 'form-control' %>
</div>
</div>
</div>
<div class="row buttons">
<div class="column buttons">
<div class="actions">
<%= f.submit "Sign up", class: 'btn form margin', data: { toggle: "modal", target: "#myModal" } %>
</div>
</div>
<% end %>
<div class="column buttons">
<% if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
<% end %>
<%= link_to fa_icon("facebook", text: "Sign up with facebook"), user_facebook_omniauth_authorize_path, class: "btn btn-lg btn-social btn-facebook" %>
</div>
</div>
</div>
</div>
Here is devise/registrations/failed_modal.js.erb
var errors = <%= error_messages.to_json.html_safe %>;
var errorForm = document.querySelector('#myModal');
var modalBody = errorForm.querySelector('.modal-body');
var alertElement = document.createElement('div')
alertElement.id = "alertElement";
alertElement.classList.add('alert');
alertElement.classList.add('alert-danger');
modalBody.appendChild(alertElement);
var errList = document.createElement('ul');
alertElement.appendChild(errList)
errors.forEach(function(error) {
var errElement = document.createElement('li');
errElement.innerText = error;
errList.appendChild(errElement)
})
errorForm.style.display = "block";
And assets/javascripts/new.js
document.addEventListener("DOMContentLoaded", function() {
var modal = document.getElementById("myModal");
if (!modal) return;
var close = modal.querySelector(".dismiss-close");
var modalBody = modal.querySelector(".modal-body");
var modalContent = modal.querySelector(".modal-content");
window.onclick = function(event) {
if (event.target == modal) {
$('#myModal').modal('hide');
$('body').removeClass('modal-open');
$('.modal-backdrop').remove();
modalBody.removeChild(modalBody.querySelector('#alertElement'));
}
}
function closeModal() {
$('#myModal').modal('hide');
$('body').removeClass('modal-open');
$('.modal-backdrop').remove();
modalBody.removeChild(modalBody.querySelector('#alertElement'));
}
modalContent.addEventListener("click", function(event) {
event.stopPropagation();
});
close.addEventListener("click", closeModal);
modal.addEventListener("click", closeModal);
});
Before I had the problem, that "close" button in my modal disappeared : here. Also backround didn't disappear, this is why I added this jQuery bit in my code:
function closeModal() {
$('#myModal').modal('hide');
$('body').removeClass('modal-open');
$('.modal-backdrop').remove();
In the console I only see the error related to autocomplete with "Algolia Places", but it should't even be here, as I actually use this autocomplete function on the next page. Here is my application.html.erb just in case. Thanks!
<!DOCTYPE html>
<html>
<head>
<title>Neigbornow</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= yield :meta %>
<%= yield %>
<%= javascript_include_tag 'application' %>
<%= javascript_pack_tag 'application' %>
<%= javascript_pack_tag 'autocomplete' %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= yield :css %>
</head>
<body>
<% if #user.nil? %>
<%= render 'layouts/header' %>
<% elsif user_signed_in? && #user.street.nil? %>
<%= render partial: "layouts/header_address" %>
<% else %>
<%= render 'layouts/header_rest' %>
<% end %>
<%= render 'layouts/flash' %>
<div id="main">
</div>
</body>
</html>
I need help, I have tried in many ways (several of them are in the forum and nothing)
In the index I have a link_to where I open the modal and below is the div with the id of the modal.
index.html.erb
<%= link_to 'Nuevo equipo', new_team_path, {class:"btn btn-success",:remote => true, 'data-toggle' => "modal", 'data-target' => '#modal-window-new' } %>
...
<div id="modal-window-new" class="modal hide fade" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"></div>
new.js.erb
<% #tipo = 'Nuevo Equipo'
js = escape_javascript(
render(partial: 'teams/form', locals: { team: #team })
) %>
$("#modal-window-new").html("<%= js %>");
_form.html.erb
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" ><%= #tipo %></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</div>
<%= form_for team, remote: true do |form| %>
<div class="modal-body">
<%= form.label "Obligatorio (*)", class: "col-form-label" %>
<div class="modal-body">
<% if team.errors.any? %>
<div class="form-group">
<strong><%= pluralize(team.errors.count, "error/es") %> antes de agregar un equipo:</strong><br>
<% team.errors.full_messages.each do |message| %>
<%= message %><br>
<% end %>
</div>
<% end %>
</div>
<div class="form-group">
<%= form.label :nombre_equipo, "Nombre Equipo*", class: "col-form-label" %>
<%= form.text_field :nombre_equipo, class: "form-control", id: :team_nombre_equipo %>
</div>
<div class="form-group">
<%= form.label :ciudad_equipo, "Ciudad Equipo*", class: "col-form-label" %>
<%= form.text_field :ciudad_equipo, class: "form-control", id: :team_ciudad_equipo %>
</div>
<div class="form-group">
<%= form.label :restriccion_horario, "Restricción Horario", class: "col-form-label" %>
<%= form.text_field :restriccion_horario, class: "form-control", id: :team_restriccion_horario %>
</div>
<div class="form-group">
<%= form.label :camiseta, class: "col-form-label" %>
<%= form.text_field :camiseta, class: "form-control", id: :team_camiseta %>
</div>
<div class="form-group">
<%= form.label :pantaloneta, class: "col-form-label" %>
<%= form.text_field :pantaloneta, class: "form-control", id: :team_pantaloneta %>
</div>
<div class="form-group">
<%= form.label :medias, class: "col-form-label" %>
<%= form.text_field :medias, class: "form-control", id: :team_medias %>
</div>
<script>
$(document).ready(function() {
$("select#team_select").select2();
}); </script>
<div class="form-group">
<%= form.label :delegate_id, "Delegado:*" %>
<%#= form.select(:delegate_id, Delegate.all, :id, :nombre, {include_blank: "None"}, {id: "team_select"}) %>
<%= collection_select(:team, :delegate_id, Delegate.all, :id, :nombre_del_completo, {:multiple => false, :include_blank => true}, {class: "form-control", id: "team_select"})%><br><br>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cerrar</button>
<%= form.submit "Guardar", class: "btn btn-success"%>
</div>
<% end %>
</div>
</div>
And he tried with
$('#modal-window-new').modal('hide');
in no way the modal is closed, by the way we already have the app on a server.
thank you very much!
----------------------------------------------
Upgrade
update.js.erb
<% if not #team.errors.any? %>
$('#modal-window-new').modal('hide');
console.info($('#modal-window-new'));
<% else %>
<% #tipo = 'Editar Equipo'
js = escape_javascript(
render(partial: 'teams/form', locals: { team: #team })
) %>
$("#modal-window-edit").html("<%= js %>");
<% end %>
After the form is getting submitted the update.js is getting rendered. You have to put the js statement in there:
$('#modal-window-new').modal('hide');
If a new model is getting created you have to add it to the create.js file.
in your case maybe located under /app/views/teams/...
A better update.js or create.js is to handle the model is:
<% if not #team.errors.any? %>
$('#modal-window-new').modal('hide');
// do other updates here
<% else %>
$('#modal-window').show();
// todo: render partial again into the modal
<% end %>
// todo: show some errors
So I basically want the current_user to be able to blacklist users. So I created a search for the users and a form which gets the selected checkboxes and blacklists or whitelists them. The search is done through AJAX but the problem is that after the search is done the checkbox ( if checked ) becomes unchecked. How do I keep the checkbox value as it is:
Controller:
def show
#b_page = BPage.find(params[:id])
if params[:search221]
#users = User.search(params[:search221])
respond_to do |format|
format.js
end
else
#users = User.all
end
end
Show Page:
<div class="modal fade" id="myModal5541" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h1> Privacy Settings</h1>
</div>
<div class="modal-body">
<%= form_tag b_page_path, :method => 'get', :id => "users_search", :remote => true do %>
<p>
<%= text_field_tag :search221, params[:search221], class: 'form-control', autofocus: true, placeholder: 'Search for users'%>
<div class="text-center">
<%= submit_tag "Search", class:"btn btn-primary"%>
</div>
<% end %>
<%= form_tag({:controller=>"b_pages",:action=>"change_privacy_settings"} , method: :put) do %>
<ul id="yolo"> <%= render "losers"%> </ul>
</div>
<div class="modal-footer">
<%= submit_tag "Update Privacy Settings"%>
<% end %>
</div>
</div>
</div>
</div>
losers partial:
<% #users.each do |user| %>
<div id="<%= user.id%>">
<div class="panel">
<%= check_box_tag "user_ids[]", user.id%>
<%= image_tag(user.avatar.url(:thumb))%>
<%= user.username %>
</div>
</div>
<% end %>
<div class="center">
<%= will_paginate #users, renderer: BootstrapPagination::Rails %>
</div>
show.js.erb:
$("#yolo").html("<%= escape_javascript(render 'losers', :locals => {:users=> #users}) %>")
How do I not loose the checkbox value(losers partial) even after the search?
So I am having an issue creating a user in a modal from my navbar. I want to add the link to allow an administrator to create a new user from a link as opposed to going to users index and use the modal button there.
My nav-bar link:
<li><%= link_to "Add User", new_user_path, remote: true %></li>
My Modal so far:
found in: _create.html.erb
<%= content_tag :div, class: "modal fade", id: "createUser" do %>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<%= form_for(#user, remote: true) do |f| %>
<div class="modal-body">
<div class="row">
<div class="col-xs-12">
FORM HERE
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<%= f.submit "Create New User", :class => 'btn btn-primary' %>
</div>
<% end %>
</div>
</div>
</div>
my create.js.erb
$('#createUser').modal('hide');
$(".email").val('');
$(".password").val('');
$(".f_name").val('');
$(".l_name").val('');
$(".primary_tel").val('');
$('#table_body').prepend('<%= j render partial: 'user_row', locals: {user: #user} %>');
$('#user_row_<%= #user.id %>').hide().fadeIn(1000);
users controller / new action
def new
#user = User.new
end
User form I want to turn into a modal:
<%= form_for(user) do |f| %>
<% if user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :user_ident %>
<%= f.text_field :user_ident %>
</div>
<div class="field">
<%= f.label :f_name %>
<%= f.text_field :f_name %>
</div>
<div class="field">
<%= f.label :l_name %>
<%= f.text_field :l_name %>
</div>
<div class="field">
<%= f.label :primary_tel %>
<%= f.text_field :primary_tel %>
</div>
<div class="field">
<%= f.label :role_id %>
<%= collection_select(:user, :role_id, Role.all, :id, :name, {prompt: true}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I assume you want to display the modal in the index view of UsersController. Add your code in _create.html.erb to the top of users/index.html.erb. Your modal won't display unless you explicitly ask it to. Since you're rendering a form in the modal for #user, you need to define what #user is in index action.
# users_controller.rb
def index
#users = User.all
#user = User.new
end
You have specified remote:true in your link to new_user_path, you have to render a js response in the new action.
def new
#user = User.new
respond_to do |format|
format.js #Looks for `users/new.js.erb`
#other formats
end
end
Since we already have the modal template in index.html.erb, all you need to do in new.js.erb is to display the modal.
# new.js.erb
$("#createUser").modal('show');
Since you have create.js.erb ready, thats all to be done.
EDIT: If you want to place this link in the navigation bar, you should add the modal template to a partial(say layouts/_new_user_modal.html.erb) and render it in application.html.erb which is common to all the views. Also, you need to make a change to your form. Instead of
<%= form_for(#user, remote: true) do |f| %>
use
<%= form_for(User.new, remote: true) do |f| %>
This way you don't have to define #user in every action of your application (DRY).
Hope this helps!