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

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

新規登録して質問してみよう
ただいま回答率
85.35%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

JavaScript

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

2回答

1356閲覧

非同期で読み込む外部JSONファイルの読込出力完了後に関数を実行したい

usk_155

総合スコア3

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

JavaScript

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2021/08/31 09:29

編集2021/08/31 09:37

前提・実現したいこと

fetch apiでJSONファイルを読込み出力し、さらに出力データをアコーディオンメニューにしようとしています。
JSONファイルの出力はできたのですがアコーディオンメニューの実装中にundefinedになっていまします。

fetch apiでJSONファイルを読込み出力

javascript

1let resortListUrl = "https://script.googleusercontent.com/macros/echo?user_content_key=UoVvVXWpytG2ol8Tsn8cuej65rsqHMqxtw5xG-HYXarMzbMMgWIUurmoy2I7CHC3ZxeFk3D9SZxSnnlWUx67KmryZ18v1yhJm5_BxDlH2jW0nuo2oDemN9CCS2h10ox_1xSncGQajx_ryfhECjZEnJ-UaAwDg0uRrxX2mlPzzQZYW-kH8X3RdXPvSR0p8JW5c0RmzB0v9RHe0Y0CjQWvjWSZiEOHtfR-16-v9YLNsT0kkYbkGyEe8Q&lib=Mra_Vp85i2zO-JFqqYajL2ey7DX5kpduB"; 2 3fetch(resortListUrl, { 4 method: "GET", 5}) 6 .then(response => response.json()) 7 .then(json => { 8 let listHtml = "<h2 class='sub-title'>都道府県 </h2><form name='form1'>"; 9 for (j = 0; j < (json.length) - 1; j++) { 10 listHtml += "<h3 class='region'>" + json[j]["area"] + "</h3><ul class='acc-contents'>"; 11 for (i = 0; i < (json[j]["detail"].length); i++) { 12 listHtml += "<li><input type='checkbox' value='" + json[j]["detail"][i]["place_detail"]["number"] + json[j]["detail"][i]["place_detail"]["name"] + "' name='checkBox'> " + json[j]["detail"][i]["place_detail"]["name"] + "</input></li>" 13 }; 14 listHtml += "</ul>"; 15 }; 16 listHtml += "</form>"; 17 let asideWrapper = document.getElementById("aside-wrapper"); 18 asideWrapper.innerHTML = listHtml; 19 })

HTML

1 <div class="main-content wrapper"> 2 <aside> 3 <div id="aside-wrapper"></div> 4 </aside> 5 </div>

試したこと

上記のJSONデータの読込と出力はうまくいきますが、下記のtoggleメソッドを追加してアコーディオンメニューを実装しようとするとundefinedeエラーが出てしまいます

上記にthenで繋いでアコーディオンメニュー追加したい

javascript

1 .then(listHtml => { 2 let asideWrapper = document.getElementById("aside-wrapper"); 3 asideWrapper.innerHTML = listHtml; 4 document.addEventListener("load", () => { 5 const region = document.getElementsByClassName('.region'); 6 for (let i = 0; i < region.length; i++) { 7 let regionEach = region[i]; 8 let content = regionEach.nextElementSibling; 9 regionEach.addEventListener('click', () => { 10 regionEach.classList.toggle('is-active'); 11 content.classList.toggle('is-open'); 12 }); 13 } 14 }) 15 });

CSS

1.region::after { 2 transform: rotate(90deg); 3 transition-duration: .3s; 4} 5 6.region.is-active::before { 7 opacity: 0; 8} 9 10.region.is-active::after { 11 transform: rotate(0); 12} 13 14.acc-contents { 15 height: 0; 16 overflow: hidden; 17 opacity: 0; 18 transition-duration: .3s; 19} 20 21.acc-contents.is-open { 22 line-height: normal; 23}

補足情報

実装方法お分かりになる方、ご教授ください。

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

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

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

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

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

guest

回答2

0

ベストアンサー

.then(json => {・・・})thenに設定している関数 json => {・・・} の本体の最後で、listHtml をreturnしないといかんやろと思いますわ。なので、以下の一行をとりあえず追加してみたらええかなと思いますわ。

diff

1.then(json => { 2 let listHtml = "<h2 class='sub-title'>都道府県 </h2><form name='form1'>"; 3 for (j = 0; j < (json.length) - 1; j++) { 4 5・・・略・・・ 6 7 listHtml += "</form>"; 8 let asideWrapper = document.getElementById("aside-wrapper"); 9 asideWrapper.innerHTML = listHtml; 10+ return listHtml; 11 })

そんで、この後に

javascript

1.then(listHtml => { ・・・

をつなげてやれば、後の then に設定している関数の引数 listHtml にHTMLの文字列が入ってくる想定や。この

diff

1+ return listHtml;

がない現状だと、次のthenのlistHtml => {listHtml に何も渡されてこない、つまり undefined になるやろな思いますわ。

うまくいくことを祈ってるで〜

続き:

よく見たら、ここがかなり怪しげなコードになってるゆうところがありましたわ。それは以下の部分

javascript

1.then(listHtml => { 2 let asideWrapper = document.getElementById("aside-wrapper"); 3 asideWrapper.innerHTML = listHtml; 4 document.addEventListener("load", () => { 5 const region = document.getElementsByClassName('.region'); 6 for (let i = 0; i < region.length; i++) { 7 let regionEach = region[i]; 8 let content = regionEach.nextElementSibling; 9 regionEach.addEventListener('click', () => { 10 regionEach.classList.toggle('is-active'); 11 content.classList.toggle('is-open'); 12 }); 13 } 14 }) 15 });

の中の

javascript

1document.addEventListener("load", () => { 2・・・ 3});

の部分。これ、なんでloadハンドラをここでaddEventListenerしてるんや? っていう。これだと、 loadのリスナーとして設定している関数() => { ・・・ }  は、一度も呼ばれないと思います。なので、試しに以下の2行を削除してみるとどないになりますやろ?

diff

1.then(listHtml => { 2 let asideWrapper = document.getElementById("aside-wrapper"); 3 asideWrapper.innerHTML = listHtml; 4- document.addEventListener("load", () => { 5 const region = document.getElementsByClassName('.region'); 6 for (let i = 0; i < region.length; i++) { 7 let regionEach = region[i]; 8 let content = regionEach.nextElementSibling; 9 regionEach.addEventListener('click', () => { 10 regionEach.classList.toggle('is-active'); 11 content.classList.toggle('is-open'); 12 }); 13 } 14- }) 15});

上の2行を削除すると、間に入っていた関数本体部分をインデント1個分左に寄せることになります。この修正で、すべてうまくいくかは分かりませんが、少なくとも、Promise の then に設定するコールバックの中に、documentのload リスナー関数を設定しても、設定した関数が呼ばれることは無いと思われるので、上記2行の削除は試してみる価値はあると思うてます。

投稿2021/08/31 10:03

編集2021/08/31 13:01
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

usk_155

2021/08/31 11:31

ありがとうございます。 return listHtml; を追記してみましたが、うまくいかないようです... 見出しのみ表示されますが、アコーディオン機能が実装されないようです。 エラーコードも表示されません。
退会済みユーザー

退会済みユーザー

2021/08/31 13:03

コメントおおきにです。よく見たら、他にも「明らかにここは変やろ?」と思うたところがありましたので、回答に続きを書きました。ちょっと試しにやってみたって。
usk_155

2021/08/31 13:56

再度ご確認いただき誠にありがとうございます。 ご指摘の箇所を直したところ実装できました(涙 初めてteratailを利用したのですが、suwmn50799さんのおかげで解決できました。ありがとうございました。 ベストアンサーにさせていただきます。 また機会がございましたら、よろしくお願いいたします。
guest

0

jsの部分は、(1)読み込み時にJSONデータをfetchしてHTMLを構築した後、(2)続けて、その構築済みのHTMLに対して加工していくわけですから、
あえてloadイベントのタイミングで(2)を行う必要はないと考えられます。
したがって

diff

1.then(listHtml => { 2 let asideWrapper = document.getElementById("aside-wrapper"); 3 asideWrapper.innerHTML = listHtml; 4- document.addEventListener("load", () => { 5- const region = document.getElementsByClassName('.region'); 6+ const region = document.getElementsByClassName('region'); 7 for (let i = 0; i < region.length; i++) { 8 let regionEach = region[i]; 9 let content = regionEach.nextElementSibling; 10 regionEach.addEventListener('click', () => { 11 regionEach.classList.toggle('is-active'); 12 content.classList.toggle('is-open'); 13 }); 14 } 15- }) 16 });

のようにしたらいかがでしょうか。

またCSSの部分は

diff

1.region::after { 2 transform: rotate(90deg); 3 transition-duration: .3s; 4} 5 6.region.is-active::before { 7 opacity: 0; 8} 9 10.region.is-active::after { 11 transform: rotate(0); 12} 13 14.acc-contents { 15 height: 0; 16 overflow: hidden; 17 opacity: 0; 18 transition-duration: .3s; 19} 20 21.acc-contents.is-open { 22- line-height: normal; 23+ height: auto 24+ opacity: 1; 25}

に直した場合いかがでしょうか。
(is-openのときに不透明度を戻す)

参考:
https://developer.mozilla.org/ja/docs/Web/CSS/opacity
https://developer.mozilla.org/ja/docs/Web/CSS/height

参照 codePen

投稿2021/08/31 13:53

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

usk_155

2021/08/31 13:59

コメントありがとうございます。 わかりやすい解説と参考ページもありがとうございます。 高評価させていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問