How to create a registration / update function where the table crosses

Background of creation

Currently, we are creating an app that records baseball scorebooks. If you want to register the results of the first and first at-bats of baseball I decided to create a mini app and check the behavior, thinking that there is a function that can display the registration form by clicking the place where 1 at bat and 1 at bat cross in the scorebook.

Mini app specifications

We have created a matrix table that shows how many points students have scored in which subjects. You can enter the score by clicking the crossed part of the table. Also, for the items that have already been entered, the input values ​​can be updated.

DB design

Image from Gyazo

Completion image diagram

Image from Gyazo

How to make

  1. Create a routing
  2. Creating a controller
  3. Create view
  4. Creating Javascript

1. Create a routing

routes.rb


Rails.application.routes.draw do
  root to: 'cross_answers#index' 
  resources :students, only: [:index, :new, :create]
  resources :lessons, only: [:index, :new, :create]
  resources :cross_answers, only: [:index, :create, :update, :destroy]
end

2. Creating a controller

cross_answers_controller.rb


class CrossAnswersController < ApplicationController
  def index
    @lessons = Lesson.all
    @students = Student.all
    @cross_answers = CrossAnswer.all
If the parameter is displayed, the data of the specified cross answer is displayed.
    if params[:lesson_id] && params[:student_id]
      set_cross_answer
    else
    @cross_answer = CrossAnswer.new
    end

  end
  def create
    @cross_answer = CrossAnswer.new(cross_answer_params)
    if @cross_answer.save
      redirect_to root_path
    else
      render :index
    end
  end

  def update
    @cross_answer = CrossAnswer.find(params[:id])
    if @cross_answer.update(cross_answer_params)
      redirect_to root_path
    else
      render :index
    end
  end

  private
  def cross_answer_params
    params.require(:cross_answer).permit(:lesson_id, :student_id, :writing, :mark)
  end

  def set_cross_answer
    @cross_answer = CrossAnswer.find_by(lesson_id: params[:lesson_id], student_id: params[:student_id])
  end

end

Supplement

It should be noted that the process is branched from the case where the parameter is sent at the time of the index action. When there is no parameter, the value stored in the instance variable is changed in order to execute the registration and the update process in some cases. At the time of update, student_id and lesson_id are sent as parameters, and unique data that matches the ID is stored in a variable and used in the view.

3. Create view

cross_answers/index.html


<div id="cross-matrix">
  <table class="matrix">
    <thead>
      //Display subject names in the matrix table at the top
      <tr class="matrix">
        <td class="matrix"></td>
        <% @lessons.each do |lesson| %>
          <td class="matrix">
            <%= lesson.name %>
          </td>
        <% end %>
      </tr>
    <thead>
    <tbody>
      //Output items for student names
      <% @students.each do |student| %>
        <tr class="matrix">
          //Display student name on the left
          <th class="matrix">
            <%= student.name %>
          </th>
          //Display subject item sequence
          <% @lessons.each do |lesson| %>
            <td class="grade-info matrix">
             //Stores hidden student table and subject table IDs
              <div class="hidden lesson-num">
                <%= lesson.id%>
              </div>
              <div class="hidden student-num">
                <%= student.id %>
              </div>
              //If there is a cross answer table with student ID and subject ID, two test scores will be displayed.
              <% if @cross_answers.find_by(lesson_id: lesson.id, student_id: student.id).present? %>
                <% cross_answer = @cross_answers.find_by(lesson_id: lesson.id, student_id: student.id) %>
                //When the score is displayed, launch the edit form instead of the registration form.
                <%= link_to cross_answers_path(lesson_id: cross_answer.lesson_id, student_id: cross_answer.student_id) do %>
                  <%= cross_answer.writing %>
                  <%= cross_answer.mark %>
                <% end %>
              <% end %>
            </td>
          <% end %>
        </tr>
      <% end %>
    </tbody>
  </table>
</div>
//If the parameters do not have a student ID and subject ID, click the cross section to launch the registration form.
<% unless params[:lesson_id] && params[:student_id] %>
  <div id="mask" class="hidden">
    <section id="modal" class="hidden">
      <div id="close">
close
      </div>
      <%= form_with model: @cross_answer, local: true do |f| %>
        <%= f.text_field :lesson_id, class:"hidden",id:"lesson_id-input"%>
        <%= f.text_field :student_id, class:"hidden", id:"student_id-input" %>
        <div>
          <label>Written score</label> 
          <%= f.text_field :writing %>
        </div>
        <div>
          <label>Mark score</label>
          <%= f.text_field :mark %>
        </div>
        <%= f.submit %>
      <% end %>
    </section>
  </div>
<% else %>
  //If the parameters include student ID and subject ID, the edit form will remain displayed.
  <div id="edit-mask">
    <section id="modal">
      //Click Close to move to the page without cross answer parameters
      <%= link_to cross_answers_path do %>
        <div id="edit-close">
close
        </div>
      <% end %>
      <%= form_with model: @cross_answer, url:cross_answer_path(@cross_answer.id), local: true do |f| %>
        <%= f.hidden_field :id %>
        <%= f.text_field :lesson_id, class:"hidden",id:"lesson_id-input"%>
        <%= f.text_field :student_id, class:"hidden", id:"student_id-input" %>
        <div>
          <label>Written score</label> 
          <%= f.text_field :writing %>
        </div>
        <div>
          <label>Mark score</label>
          <%= f.text_field :mark %>
        </div>
        <%= f.submit %>
      <% end %>
    </section>
  </div> 
<% end %>

Supplement

__ How to make a matrix table __ We are creating a table with the table tag. The first line uses the each method to increase the subject name sequence and display the subject name. From the second line onward, use the each method to increase the number of student name lines. The student name is displayed in the first column, and the subsequent columns use the each method again to increase the subject name segment. It has a nested structure in which each method is stored in each method. Now you can create a matrix table.

__ About the stored data in the table __ The table can store 4 data. ・ Hidden subject ID ・ Hidden student ID If there is data in the cross answer table with the above two IDs, it will be displayed. ・ Mark score ・ Writing points

When you click the crossed place, copy the student ID and subject ID in the table and paste it in the text box for entering the hidden subject ID and student ID on the registration form.

__ About switching between registration and update __ If there is no data, click the blank part of the matrix to display the registration form with JavaScript If there is data, click the numerical value to send the parameters of student ID and subject ID to the controller, store the unique cross-answer data that matches the two IDs as an instance variable, and return it to the client. Also, in the view settings, if there are parameters, the update form will always be launched.

__ About class name __ A common class name is given to all crossing points between subjects and students in the matrix table. This is so that the event can be fired at the clicked point in JavaScript.

__ About ID name __ Give an ID name to the HTML element you want to use in JavaScript.

4. Creating Javascript

modal.js


function modalAddJoin(){
  //Get all elements because the HTML element that inputs the form has a common class name
  let cross_info = document.querySelectorAll(".grade-info");
  let info_num = cross_info.length;
  //Make sure that the event occurs where you click.
  for(let i=0; i<=info_num - 1; i++){
    cross_info[i].onclick = function(){
      //Obtain the student ID and subject ID and post them to the input items on the registration form.
      let lessonId = this.children[0].innerHTML.trim();
      let studentId = this.children[1].innerHTML.trim();
      const modal = document.getElementById("modal");
      const mask = document.getElementById("mask");
      const close = document.getElementById("close");
      const studentInput = document.getElementById("student_id-input");
      const lessonInput = document.getElementById("lesson_id-input");
      studentInput.value = Math.floor(studentId);
      lessonInput.value = Math.floor(lessonId);
      //Remove hidden class names
      modal.classList.remove("hidden");
      mask.classList.remove("hidden")
      //When you press close, add the hidden class name
      close.onclick = function(){
        modal.classList.add("hidden");
        mask.classList.add("hidden");
      };
    }
  }
}
window.addEventListener("load", modalAddJoin);

About future prospects

By clicking on the crossed parts of the matrix table to register and display it, I felt that it could be used in a baseball scorebook in a production environment. However, if there is only one concern, the parameters are sent and the registration and update forms are switched, so extra page transitions may occur. We would like to improve this and register or update with asynchronous communication to solve the problem. I will try to write an improved article in the near future.

Finally

Thank you for reading this far. Since we are implementing the functions while exploring, I think that there are some inefficiencies. If you have any opinions or suggestions, please do not hesitate to contact us.

Recommended Posts

How to create a registration / update function where the table crosses
[Rails] How to create a table, add a column, and change the column type
How to create a method
How to create a form to select a date from the calendar
How to create a placeholder part to use in the IN clause
How to add columns to a table
[Java] How to create a folder
How to add the delete function
[Rails] How to put a crown mark on the ranking function
(Ruby on Rails6) Create a function to edit the posted content
[Java] How to use the hasNext function
How to create a Maven repository for 2020
[Swift] How to implement the countdown function
[Swift5] How to create a splash screen
[rails] How to create a partial template
[Processing × Java] How to use the function
How to implement the email authentication function at the time of user registration
How to create a database for H2 Database anywhere
[Rails] How to create a graph using lazy_high_charts
[Swift] How to implement the LINE login function
[swift5] How to implement the Twitter share function
How to create pagination for a "kaminari" array
How to implement the breadcrumb function using gretel
How to create a class that inherits class information
[For beginners] How to implement the delete function
How to create a theme in Liferay 7 / DXP
[1st] How to create a Spring-MVC framework project
How to easily create a pull-down in Rails
[Swift] How to implement the fade-in / out function
[Rails] How to create a Twitter share button
How to make a follow function in Rails
How to create a route directly from the URL you want to specify + α
How to make a unique combination of data in the rails intermediate table
How to clear all data in a particular table
3. Create a database to access from the web module
How to create a Java environment in just 3 seconds
How to delete / update the list field of OneToMany
How to run the SpringBoot app as a service
[Rails] How to create a signed URL for CloudFront
How to update devise user information without a password
How to create a JDBC URL (Oracle Database, Thin)
How to create a Spring Boot project in IntelliJ
[Spring Boot] How to create a project (for beginners)
How to create a data URI (base64) in Java
[Rails] How to change the column name of the table
How to store Rakuten API data in a table
How to create docker-compose
How to make a mod for Slay the Spire
[Apple Subscription Offer] How to create a promotional offer signature
Create a login authentication screen using the session function
I want to add a delete function to the comment function
[Rails] Processing after adding a column to the devise table
SDWebImage: How to clear the cache for a particular UIImageView
How to create a lightweight container image for Java apps
[iOS] [Objective-C] How to update a widget from an Objective-C app
[IOS] How to get the table name from AWS DynamoDB
I want to create a form to select the [Rails] category
Create a method to return the tax rate in Java
[Ruby] How to retrieve the contents of a double hash
A validation error occurred when saving to the intermediate table.
How to add the same Indexes in a nested array