🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

2回答

2450閲覧

【Rails】Javascriptで作ったカレンダーに、保存したイベント情報を表示させたい

tekeTECH

総合スコア8

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2020/12/09 22:38

編集2020/12/11 12:59

前提・実現したいこと

Railsで、予定やTodoをカレンダーに表示できるシステムを作っています。
カレンダーはJavascriptを使ってなんとか表示することができました。
簡単な予定入力フォームも作り、フォーム情報が保存できることも確認できています。
そこで、保存したイベントのタイトルをカレンダー上の該当日に表示させる記述をしたいのですが、どう記述したら良いのか分かりません。ネットで記事も探しましたがfullcalendarを取り扱ったものが多く、自分のようにGemやライブラリを使わずにイベント表示するパターンはなかなか見つけられませんでした。1つだけ、ヒントになりそうなサイトを見つけ、demo.jsファイルを作って同じように記述してみましたが、ダメでした。どなたか解決方法をご教授頂けないでしょうか。よろしくお願い致します。

該当のソースコード

index.html.erb

ruby

1<%= render "shared/header" %> 2<div class="todo-countdown"> 3 カウントダウン表示 4</div> 5<table> 6 <thead> 7 <tr> 8 <th id="prev">&laquo;</th> 9 <th id="title" colspan="5">2020/05</th> 10 <th id="next">&raquo;</th> 11 </tr> 12 <tr> 13 <th>Sun</th> 14 <th>Mon</th> 15 <th>Tue</th> 16 <th>Wed</th> 17 <th>Thu</th> 18 <th>Fri</th> 19 <th>Sat</th> 20 </tr> 21 </thead> 22 <tbody> 23 <tr> 24 <th> 25 <% @events.each do |event| %> 26 <div> 27 <%= event.title %> 28 </div> 29 <% end %> 30 </th> 31 </tr> 32 </tbody> 33 <tfoot> 34 <tr> 35 <td id="today" colspan="7">Today</td> 36 </tr> 37 </tfoot> 38</table> 39<footer> 40 フッター部分 41</footer>

main.js

ruby

1'use strict'; 2 3console.clear(); 4 5{ 6 const today = new Date(); 7 let year = today.getFullYear(); 8 let month = today.getMonth(); 9 10 function getCalendarHead() { 11 const dates = []; 12 const d = new Date(year, month, 0).getDate(); 13 const n = new Date(year, month, 1).getDay(); 14 15 for (let i = 0; i < n; i++) { 16 // 30 17 // 29, 30 18 // 28, 29, 30 19 dates.unshift({ 20 date: d - i, 21 isToday: false, 22 isDisabled: true, 23 }); 24 } 25 26 return dates; 27 } 28 29 function getCalendarBody() { 30 const dates = []; // date: 日付, day: 曜日 31 const lastDate = new Date(year, month + 1, 0).getDate(); 32 33 for (let i = 1; i <= lastDate; i++) { 34 dates.push({ 35 date: i, 36 isToday: false, 37 isDisabled: false, 38 }); 39 } 40 41 if (year === today.getFullYear() && month === today.getMonth()) { 42 dates[today.getDate() - 1].isToday = true; 43 } 44 45 return dates; 46 } 47 48 function getCalendarTail() { 49 const dates = []; 50 const lastDay = new Date(year, month + 1, 0).getDay(); 51 52 for (let i = 1; i < 7 - lastDay; i++) { 53 dates.push({ 54 date: i, 55 isToday: false, 56 isDisabled: true, 57 }); 58 } 59 60 return dates; 61 } 62 63 function clearCalendar() { 64 const tbody = document.querySelector('tbody'); 65 66 while (tbody.firstChild) { 67 tbody.removeChild(tbody.firstChild); 68 } 69 } 70 71 function renderTitle() { 72 const title = `${year}/${String(month + 1).padStart(2, '0')}`; 73 document.getElementById('title').textContent = title; 74 } 75 76 function renderWeeks() { 77 const dates = [ 78 ...getCalendarHead(), 79 ...getCalendarBody(), 80 ...getCalendarTail(), 81 ]; 82 const weeks = []; 83 const weeksCount = dates.length / 7; 84 85 for (let i = 0; i < weeksCount; i++) { 86 weeks.push(dates.splice(0, 7)); 87 } 88 89 weeks.forEach(week => { 90 const tr = document.createElement('tr'); 91 week.forEach(date => { 92 const td = document.createElement('td'); 93 94 td.textContent = date.date; 95 if (date.isToday) { 96 td.classList.add('today'); 97 } 98 if (date.isDisabled) { 99 td.classList.add('disabled'); 100 } 101 102 tr.appendChild(td); 103 }); 104 document.querySelector('tbody').appendChild(tr); 105 }); 106 } 107 108 window.addEventListener("DOMContentLoaded", function () { 109 // DOMの準備が出来たら実行 110 createCalendar(); 111 }) 112 function createCalendar() { 113 clearCalendar(); 114 renderTitle(); 115 renderWeeks(); 116 } 117 118 window.addEventListener("DOMContentLoaded", function () { 119 document.getElementById('prev').addEventListener('click', () => { 120 month--; 121 if (month < 0) { 122 year--; 123 month = 11; 124 } 125 createCalendar(); 126 127 }) 128 129 }); 130 131 window.addEventListener("DOMContentLoaded", function () { 132 document.getElementById('next').addEventListener('click', () => { 133 month++; 134 if (month > 11) { 135 year++; 136 month = 0; 137 } 138 createCalendar(); 139 }) 140 141 }); 142 143 144 window.addEventListener("DOMContentLoaded", function () { 145 document.getElementById('today').addEventListener('click', () => { 146 year = today.getFullYear(); 147 month = today.getMonth(); 148 createCalendar(); 149 }) 150 151 }); 152 153}

demo.js(エラーが出たため、コメントアウト中)

ruby

1var events = [ 2 {'Date': new Date(2020, 12, 7), 'Title': '資格取得セミナー午後2時からセンタービル'}, 3 {'Date': new Date(2020, 12, 18), 'Title': '●●イベント開催', 'Link': 'https://yahoo.co.jp/'}, 4 {'Date': new Date(2020, 6, 27), 'Title': '〇〇企画創業20周年記念', 'Link': 'https://www.google.com/'}, 5]; 6 7var settings = {}; 8var element = document.getElement('caleandar'); 9caleandar(element, events, settings);

events_controller.rb

ruby

1class EventsController < ApplicationController 2 def index 3 @events = Event.all 4 end 5 6 def new 7 @event = Event.new 8 end 9 10 def create 11 @event = Event.new(event_params) 12 @event.save 13 redirect_to root_path 14 end 15 16 private 17 18 def event_params 19 params.require(:event).permit(:title, :detail, :event_date, :start_date, :end_date, :category_id) 20 end 21 22 23end 24

マイグレーションファイル

ruby

1class CreateEvents < ActiveRecord::Migration[6.0] 2 def change 3 create_table :events do |t| 4 t.string :title 5 t.text :detail 6 t.date :event_date 7 t.datetime :start_date 8 t.datetime :end_date 9 t.integer :category_id 10 11 t.timestamps 12 end 13 end 14end

試したこと

・index.htmlにあるように、<tbody>内の<th>要素にイベントタイトルを表示する記述をしてみる。→どこにも表示されず。→Javascriptで上書きされていると考えています。
・demo.jsの読み込み→エラーが出たのと、コードの意味が理解できず、コメントアウトにして保留中です。

補足情報(FW/ツールのバージョンなど)

Railsのバージョン 6.0.0

カレンダー内のどこかに表示することができれば、保存したデータの日付情報とカレンダーの日付情報を照らし合わせて表示させるといったやり方でできるのかなと思ったり、<th>要素にid属性やclass属性を付加できれば、GetElementById等で取り出しできるのにと思ったりしていますが、難航しています。そもそものアルゴリズムが間違っている可能性もあるので、様々な角度からのご指摘・ご助言等頂けたら幸いです。
イメージ説明

現状のブラウザ画面


2020/12/11追記
main.jsに以下のコードを加えることで、日付1つ1つの要素にid属性を付加することができました。後は、この要素を親要素として「子要素1(日付表示)」、「子要素2(イベント名)」を作り、カレンダーの日付情報と登録したイベントの日付が同じ時に、その場所にイベント名を表示させる記述ができればと思っていますが、要素の追加、JavascriptでRailsのインスタンス変数を受け渡しにつまづいています。gonというGemを導入してevents.controller.rbに「gon.events = @events」と設定しましたが、「@events.each do」のJavascript版の記述が分からず、サイトを彷徨っています。参考サイトの紹介などでも構いませんので、解決の糸口を一緒に探して頂けないでしょうか?よろしくお願い致します。

ruby

1〜省略〜 2 weeks.forEach(week => { 3 const tr = document.createElement('tr'); 4 week.forEach(date => { 5 const td = document.createElement('td'); 6 7 td.textContent = date.date; 8 if (date.isToday) { 9 td.classList.add('today'); 10 } 11 if (date.isDisabled) { 12 td.classList.add('disabled'); 13 } 14 15 td.setAttribute('id', 'event_box') #ここに追加 16 17 tr.appendChild(td); 18 }); 19 document.querySelector('tbody').appendChild(tr); 20 }); 21 } 22〜省略〜

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

main.jsを以下のように編集することで、カレンダーの任意の場所に文字を表示させることができました。ただ、新たな課題が出てきたので、改めて質問をしようと思います。

ruby

1〜省略〜 2 weeks.forEach(week => { 3 const tr = document.createElement('tr'); 4 week.forEach(date => { 5 const td = document.createElement('td'); 6 7 8 9 td.textContent = date.date; 10 if (date.isToday) { 11 td.classList.add('today'); 12 } 13 if (date.isDisabled) { 14 td.classList.add('disabled'); 15 } 16 17 td.setAttribute('id', 'event_box') #td要素にevent_boxというid属性を付加 18 const title_box = document.createElement('div'); #div要素を生成 19 title_box.setAttribute('id', 'title_box') #div要素にtitle_boxというid属性を付加 20 title_box.textContent = ''; 21 22 const div = document.querySelector('td'); #td要素を選択 23 td.appendChild(title_box); #選択したtd要素に、子要素としてdiv要素を追加 24 25 const get_disabled = document.getElementsByClassName('disabled') 26 27 console.log(date.date, month + 1, year); // 日付要素確認用 28 29 30 if (`${year}-${month + 1}-${date.date}` === '2020-12-12') { 31 title_box.textContent = "タイトル表示" 32 } 33 34 tr.appendChild(td); 35 }); 36 document.querySelector('tbody').appendChild(tr); 37 }); 38 } 39 40 window.addEventListener("DOMContentLoaded", function () { 41 // DOMの準備が出来たら実行 42 createCalendar(); 43 }) 44 function createCalendar() { 45 clearCalendar(); 46 renderTitle(); 47 renderWeeks(); 48 } 49 50 window.addEventListener("DOMContentLoaded", function () { 51 document.getElementById('prev').addEventListener('click', () => { 52 month--; 53 if (month < 0) { 54 year--; 55 month = 11; 56 } 57 createCalendar(); 58〜省略〜

イメージ説明

投稿2020/12/12 10:51

tekeTECH

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

JavaScriptで非同期でサーバーからデータ取得してきて、JavaScriptでカレンダー作ってるロジックに入れ込むことになるのではと。
なので、カレンダー作ってるロジックを正しく理解し、どこにどのように入れれば任意の場所に情報を表示させられるか考えて検証するところから始めてください。

投稿2020/12/10 00:28

m.ts10806

総合スコア80875

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tekeTECH

2020/12/11 12:44

アドバイスありがとうございます。main.jsで記述を入れるべき場所が分かり、そこに「td.setAttribute('id', 'event_box')」と記述してみると、カレンダーの日付1つ1つにid属性を付加することができました。「td.textContent = "ok"」などと入れると、日付の部分が全てokに変えることもできました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問