質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

89.63%

フォームの表示非表示の切り替え

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 141

asako1010

score 44

質問の内容 課題内容

javaScriptでtodoListを作っています。
ラジオボタンには、すべて/作業中/完了の3つチェックボタンがあり、それぞれチェックするとそれに合った配列が表示される様な仕組みを作っています。チェックは1つしか選択できません。

現在、以下のコードでは「ラジオボタンの作業中を押したときに完了が消え、ラジオボタンの完了を押したときに作業中が消えるという仕組み」を作ろうとしています。 

試したこと

以下のコードの「button-done」「button-working」が間違っているというのは分かるのですが、どう書き換えればいいかが分かりりません。

      //フォーム
      document.getElementById('button-done').style.display = "";
      document.getElementById('button-working').style.display = "none";
    } else if (radio[1].checked) {
      //フォーム
      document.getElementById('button-done').style.display = "none";
      document.getElementById('button-working').style.display = "";
    }

以下、現在のコードです。

<!DOCTYPE html>
<html lang="ja"><head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>ToDoリスト</title>
  <link rel="stylesheet" href="css/style.css"></head><body>
  <h1>ToDoリスト</h1><div class="radiobutton">
    <label for="button-1" ><input type="radio" id="button-1" name="radio1" value="1" checked="checked" />すべて</label>
    <label for="button-2"><input type="radio" id="button-done" name="radio1" value="2" onclick="entryChange1();" />完了中</label>
    <label for="button-3"><input type="radio" id="button-working" name="radio1" value="3" onclick="entryChange1();" />作業中</label><table>
      <thead>
        <tr>
          <th>ID</th>
          <th>コメント</th>
          <th>状態</th>
        </tr>
      </thead>
      <tbody id="idTbody">
      </tbody>
    </table><h2>新規タスクの増加</h2><p id=id_p>
      <input type="text" id="id_text" value="">
      <button id="btn" type="btn" class="button" value=""> 追加</button>
    </p>
  </div><script src="js/main.js"></script>
</body>

</html>
'use strict'
let taskid = 0;
//イベントリスナ―を登録
const add_btn = document.getElementById('btn');
add_btn.addEventListener('click', () => {
  const id_td = document.createElement("td");
  id_td.textContent = taskid;
  const comment = document.getElementById("id_text").value;
  const commentEl = document.createElement("td");
  commentEl.textContent = (comment);


  const createWorkingBtn = function () {
    //作業中ボタンを生成する処理
    const workingBtn = document.createElement("button");
    workingBtn.textContent = "作業中";
    workingBtn.addEventListener('click', () => {
      console.log('表示を変更');
      if (workingBtn.textContent === "作業中") {
        workingBtn.textContent = "完了";
      } else {
        workingBtn.textContent = "作業中";
      }
    })
    //生成した作業中ボタンを返す処理
    return workingBtn;
  }
  const workingBtn = createWorkingBtn();


  const createDelBtn = function () {
    //削除ボタンを生成する処理
    const delBtn = document.createElement("button");
    delBtn.textContent = "削除";
    delBtn.addEventListener('click', () => {
      idTbody.removeChild(trEl);
    })
    //生成した削除ボタンを返す処理
    return delBtn;
  }
  const delBtn = createDelBtn()


  const trEl = document.createElement("tr");
  trEl.appendChild(id_td);
  trEl.appendChild(commentEl);
  trEl.appendChild(workingBtn);
  trEl.appendChild(delBtn);
  const todoEl = document.getElementById("idTbody");

  todoEl.appendChild(trEl);
  taskid++;
}, false); 

  /*ラジオボタン作業中、完了を押下時の処理*/
  function entryChange1() {
  const radio = document.getElementsByName('radio1')
    if (radio[0].checked) {
      //フォーム
      document.getElementById('button-done').style.display = "";
      document.getElementById('button-working').style.display = "none";
    } else if (radio[1].checked) {
      //フォーム
      document.getElementById('button-done').style.display = "none";
      document.getElementById('button-working').style.display = "";
    }
  }

  //オンロードさせ、リロード時に選択を保持
  window.onload = entryChange1;

##編集後のコード

<!DOCTYPE html>
<html lang="ja"><head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>ToDoリスト</title>
  <link rel="stylesheet" href="css/style.css"></head><body>
  <h1>ToDoリスト</h1><div class="radiobutton">
    <input type="radio" id="filter-all" name="radio1" value="1" checked="checked" />
    <label for="filter-all">すべて</label>
    <input type="radio" id="filter-done" name="radio1" value="2" />
    <label for="filter-done">完了中</label>
    <input type="radio" id="filter-working" name="radio1" value="3" />
    <label for="filter-working">作業中</label><table>
      <thead id>
        <tr>
          <th>ID</th>
          <th>コメント</th>
          <th>状態</th>
        </tr>
      </thead>
      <tbody id="idTbody">
      </tbody>
    </table><h2>新規タスクの増加</h2><p id=todo-form>
      <input type="text" id="todo-comment" value="">
      <button id="btn" type="btn" class="button" value=""> 追加</button>
    </p>
  </div><script src="js/main.js"></script>
</body>

</html>
'use strict'
let taskid = 0;
function entryChange() {
  radio = document.getElementsByName('radio1')
  //ラジオボタンの0(すべて)がチェックされたとき
  if (radio[0].checked) {
    document.getElementsByClassName('done').style.display = "";
    document.getElementsByClassName('doing').style.display = "";
    //ラジオボタンの1(完了)がチェックされたとき
  } else if (radio[1].checked) {
    //フォーム
    doing.forEach(done => {
      console.log(done);
      document.getElementsByClassName('done').styledisplay = "";
      document.getElementsByClassName('doing').style.display = "none";
    })
    //ラジオボタンの2(作業中)がチェックされたとき
  } else if (radio[2].checked) {
    //フォーム
    doing.forEach(work => {
      console.log(work);
      document.getElementsByClassName('done').style.display = "none";
      document.getElementsByClassName('doing').style.display = "";
    })
  }
}
//オンロードさせ、リロード時に選択を保持
window.onload = entryChange;

//イベントリスナ―を登録
const add_btn = document.getElementById('btn');
add_btn.addEventListener('click', () => {
  const id_td = document.createElement("td");
  id_td.textContent = taskid;
  const comment = document.getElementById("todo-comment").value;
  const commentEl = document.createElement("td");
  commentEl.textContent = (comment);

  const createWorkingBtn = function () {
    //作業中ボタンを生成する処理
    const workingBtn = document.createElement("button");
    workingBtn.classList.add("doing");
    workingBtn.textContent = "作業中";
    workingBtn.addEventListener('click', () => {
      console.log('表示を変更');
      if (workingBtn.textContent === "作業中") {
        workingBtn.classList.add("doing");
        workingBtn.textContent = "完了";
        // ボタン押下で生成されたdomの中の親要素へclassNameをつける処理
        const doneParent = workingBtn.parentNode;
        doneParent.className = 'workDone';
      } else {
        workingBtn.classList.add("done");
        workingBtn.textContent = "作業中";
        // ボタン押下で生成されたdomの中の親要素へclassNameをつける処理
        const workParent = this.parentNode;
        workParent.className = 'work';
      }
    })
    //生成した作業中ボタンを返す処理
    return workingBtn;
  }
  const workingBtn = createWorkingBtn();


  const createDelBtn = function () {
    //削除ボタンを生成する処理
    const delBtn = document.createElement("button");
    delBtn.textContent = "削除";
    delBtn.addEventListener('click', () => {
      idTbody.removeChild(trEl);
    })
    //生成した削除ボタンを返す処理
    return delBtn;
  }
  const delBtn = createDelBtn()

  const trEl = document.createElement("tr");
  trEl.appendChild(id_td);
  trEl.appendChild(commentEl);
  trEl.appendChild(workingBtn);
  trEl.appendChild(delBtn);
  const todoEl = document.getElementById("idTbody");

  todoEl.appendChild(trEl);
  taskid++;

}, false); 
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

過去のご質問からも 徐々にTODOリストを形にしていることが伺えますが、正直、「仕様が纏まってないのではないか?」と思います。というのは、ご質問の本質であるイベントリスナを考える以前の問題として、正しいマークアップができていないからです。

  1. label 要素の for 属性を指定する時は 対応する input 要素の id と同じでなければならない(MDN label)。
  2. 各要素の id属性には 意味付けされた言葉が用いられておらず、可読性に欠けます(MDN セマンティクス)。

例えば、

  • button-1 / button-1 -> filter-all
  • button-2 / button-done -> filter-done
  • button-3 / button-working -> filter-working
  • idTbody -> todo-items
  • id_p -> todo-form
  • id_text -> todo-comment
  • btn -> todo-append

属性値だけでなく、Javascript の変数名や関数名にも命名規則を定めるように心がけないと、回答者は匙を投げることになりかねません。

ご質問のタイトル

フォームの表示非表示の切り替え

「フォーム」という言葉だけでは不明瞭に感じます。

現状、初期のご質問と比べても3つの「フォーム」があるはずです。

  1. 登録用
  2. 項目変更用(状態変更/削除)
  3. フィルタ用(再表示)

各フォームに、表示に対応した変化を期待する機能があると思いますが、機能に応じたイベントリスナを書く前に、考えることが 表示の方法と対応したデータ になります。

table を利用したデータの取り扱いにも、2つが考えられます。

  1. table 要素の属性だけで行う。
  2. 別途、javascript の Arrayで管理し、table 要素に差し込む。

「データの扱い方」を定めないと、作用するイベントリスナは構築できません。


回答は、「まずは正しいマークアップをしてください」ということになりますが、javascript 内で多用する document.getElementById() の代わりに CSSのセレクタで取得する方法があります。

  1. MDN querySelector()
  2. MDN querySelectorAll()

javascript 内で多用するからこそ、次のように短く書く例は役立つかもしれません。

const qs = selector => document.querySelector(selector);
const qsa = selector => document.querySelectorAll(selector);

// document.querySelectorAll("input[name=radio1]") を短くできる
let filterButtons = qsa("input[name=radio1]");

直接的な回答には至りませんが、参考になればと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/15 21:53

    ありがとうございます。
    可読性については全く意識していませんでした。
    気をつけます。

    マークアップから勉強し直します。

    キャンセル

+1

'use strict'を使うなら宣言していない変数を使わない。

// radio = document.getElementsByName('radio1')
// ↓
   const radio = document.getElementsByName('radio1')

動くサンプル:https://jsfiddle.net/n65jbs92/

【【初心者向け】コンソールによるJavascriptのエラー表示方法】
https://eng-entrance.com/javascript-display-error

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/15 18:44

    コメントありがとうございます。
    「確認」というのはどういう意味でしょうか?
    飲み込み悪く、すみません。

    キャンセル

  • 2019/12/15 19:06

    if (radio[0].checked) {} else if (radio[1].checked) {} と、2要素しか見ていない。ラジオボタンは3つ。

    キャンセル

  • 2019/12/15 21:53

    「すべて」についても見るということですね。
    ありがとうございます。

    キャンセル

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

  • ただいまの回答率 89.63%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる