Im using devise for user registration with the fields: email, password, and role.
When the user selects a role from a select box (Student, Teacher, Admin), I want the app to render the nested fields for one of these roles. Each role stores different information and exists as a model in its own right.
I have a javascript which shows and hides the appropriate divs based upon the current selection.
The problem is, the form fails to submit unless I complete the fields for ALL models, rather than just the currently selected model. I realise this is because I am rendering all the partials and then simply hiding them with the javascript.
Question: How do I use the javascript to dynamically render ONLY the partial containing the model fields for the currently selected model?
New Registrations View
h2>Sign up</h2>
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<h3>Login Details</h3>
<br />
<div class = "row">
<div class = "col-md-3"></div>
<div class = "col-md-6"><div class = "panel panel-midnight">
<div class = "panel-heading"><h3 class = "panel-title">Create an account</h3></div>
<div class = "panel-body">
<div class="form-inputs">
<%= f.input :email, :required => true, :autofocus => true, :placeholder => "Enter email address" %>
<br />
<%= f.input :password, :required => true, :placeholder => "Password" %>
<br />
<%= f.input :password_confirmation, :required => true, :placeholder => "Confirm Password" %>
<br />
<%= f.input :role, :label => "I am a:", :collection => ["Student","Teacher","Admin"], :required => true %>
</div>
<h3>Profile</h3>
<div id = "student_fields">
<%= render partial: "student_fields", locals: {:f => f} %>
</div>
<div id = "teacher_fields">
<%= render partial: "teacher_fields", locals: {:f => f} %>
</div>
<div id = "admin_fields">
Admin
</div>
<br />
<% end %>
<br />
</div>
<div class = "col-md-3"></div>
</div>
</div>
</div>
<! Javascript to show/hide specific fields for each role>
<script>
$(document).ready(function(){
if($('#user_role').val() != "Student"){
$("#student_fields").css('display','none');
}
else{
$("#student_fields").css('display','block');
}
$('#user_role').change(function(){
if($(this).val() != "Student"){
$("#student_fields").css('display','none');
}
else{
$("#student_fields").css('display','block');
}
})
});
$(document).ready(function(){
if($('#user_role').val() != "Teacher"){
$("#teacher_fields").css('display','none');
}
else{
$("#teacher_fields").css('display','block');
}
$('#user_role').change(function(){
if($(this).val() != "Teacher"){
$("#teacher_fields").css('display','none');
}
else{
$("#teacher_fields").css('display','block');
}
})
});
$(document).ready(function(){
if($('#user_role').val() != "Admin"){
$("#admin_fields").css('display','none');
}
else{
$("#admin_fields").css('display','block');
}
$('#user_role').change(function(){
if($(this).val() != "Admin"){
$("#admin_fields").css('display','none');
}
else{
$("#admin_fields").css('display','block');
}
})
});
</script>
JavaScript cannot "render" only the fields that you want. It can either show/hide (as you're attempting to do) or request a dynamic load of content (aka, AJAX). If you'd like to go the latter route then consider changing your profile section to look like this:
Then you'll need to set up the javascript to make a request to a unique url based on which role is selected and fill the #profile section with the results. Here's a jquery-based idea...
A word of warning: it's often best to try to get things working without ajax and then add the ajax later, especially if you're just starting out. You might want to consider a slightly modified registration that acts more like a wizard -- the user could first provide the user details (including role) and the response could be to ask the user to provide their role-specific details when the user is successfully created.