To efficiently display the list of students every time the selection option changes, I suggest incorporating ajax into your setup. This will require making a few modifications.
Firstly, pinpoint where in your view you want to showcase the students. For example, consider adding a div
within your form:
<%= simple_form_for(@exam) do |f| %>
<%= f.error_notification %>
<div class="field">
<%= f.label :Year %>
<%= f.collection_select :year_id, Year.order(:name), :id, :name, prompt: true %>
</div>
<div id="students"><!-- Students will be listed here --></div>
<div class="form-inputs">
<%= f.input :marks_secured %>
</div>
<div class="form-actions">
<%= f.button :submit, "Submit" %>
</div>
<% end %>
Next, include a script (within the same view as your form
) to detect when the select
changes and dynamically update the students list using ajax:
<script type="text/javascript">
$(function () {
function getStudents() {
var year = $('#exam_year_id').val();
$.ajax({
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},
type: "GET",
url: "<%= students_url %>",
data: { year: year },
success: function(response) {
$('#students').html(html);
}
});
}
$('#exam_year_id').on('change', getStudents );
getStudents();
});
</script>
In this scenario, the function getStudents
is invoked whenever the select
changes (
$('#exam_year_id').on('change', getStudents );
) and upon page load (
getStudents();
), listing the default year's selected students upon initial page load.
Note that we are replacing the content of the recently added div
with a variable named html
, which will be generated within a view by your students controller (next step).
Subsequently, update your students controller to fetch the student list for the chosen year:
def index
@Students = Student.where(year: params[:year])
end
Create the corresponding view displaying the student list:
var html = "<select name='exam[student_id]' id='exam_student_id'>";
<% @Students.each do |student| %>
html = html + "<option value='<%= student.id %>'><%= student.name %></option>"
<% end %>
html = html + "</select>";
The view should be named index.js.erb
instead of
index.html.erb</code and will contain javascript. In this example, it only comprises the variable <code>html
with the student list (presented as another
select
box but customizable).
Lastly, add an update
action to your exams controller to modify the exam details:
def update
exam = Exam.find(params[:id])
exam.student_id = exam_params[:student_id]
exam.year_id = exam_params[:year_id]
exam.save!
end
private
def exam_params
params.require(:exam).permit(:year_id, :student_id)
end
And there you have it! I hope this explanation proves useful.