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

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

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

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

JavaScript

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

HTML

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

Q&A

解決済

1回答

1181閲覧

(JavaScript)Arrayがundefinedとなるのを解消したい

minari766

総合スコア17

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

JavaScript

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

HTML

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

0グッド

0クリップ

投稿2021/11/05 19:29

編集2021/11/06 09:57

###実現したいこと
下記URLを参考に、1つ目のプルダウンの選択肢に合わせ、2つ目のプルダウンの選択肢をフィルタリングしようと考えております。
https://blog.narito.ninja/detail/50

エリアで"選択肢A"を選んだらアトラクションで"選択肢a〜c"が表示され、
エリアで"選択肢B"を選んだらアトラクションで"選択肢d〜h"が表示されるというイメージです。
イメージ説明

しかしながら、現状エリアを選択してもアトラクションの選択肢が何も表示されません。
なお、post_form.htmlに記載しているの下記JavaScriptコードを削除すると、アトラクションの選択肢が全て表示されるようになることから、アトラクションのプルダウンにデータは渡されている状態ではあります。

JavaScript

1attractionElement.children().remove();

###発生中のエラー
エリアとアトラクションの情報が入っているArray(変数名:categoryList)からfor文でkeyと値をループして抽出するコードにて、「Uncaught TypeError: Object.key is not a function or its return value is not iterable」が発生しています。

検証画面で確認したところ、エラーの直前にてcategoryList配列がundefinedとなっていることが原因かと考えております。

ただし、なぜこの様になってしまうのかがわからないため、お気づきの点についてご教示いただけますと幸いです。

※console.logでの変数確認結果と表示されているエラー画面を添付します
イメージ説明

###関連コード
必要と思われる箇所のみ記載いたします。不足等ありましたらご指摘願います。
post_form.html(JavaScript併記)

html

1<form method="post" enctype="multipart/form-data"> 2 <div class="formpost"> 3 <div>エリア<span>※必須</span></div> 4 <select name="area" placeholder="選択してください" class="form-control" id="id_area"> 5 <option value="1">----選択してください</option> 6 <option value="2">ワールドバザール</option> 7 <option value="3">アドベンチャーランド</option> 8 <option value="4">ウエスタンランド</option> 9 <option value="5">クリッターカントリー</option> 10 <option value="6">ファンタジーランド</option> 11 <option value="7">トゥーンタウン</option> 12 <option value="8">トゥモローランド</option> 13 </select> 14 </div> 15 <div class="formpost"> 16 <div>アトラクション<span>※必須</span></div> 17 <select name="attraction" placeholder="選択してください" class="form-control" id="id_attraction"> 18 <!-- JavaScriptのattractionElement.children().remove();を消すと下記optionが現れますが、左記を記述するとoptionが全て非表示となります --> 19 <option value="1">----エリアを選択してください</option> 20 <option value="2">オムニバス</option> 21 <!-- 中略 --> 22 <option value="48">モンスターズ・インク“ライド&amp;ゴーシーク!”</option> 23 <option value="49">トゥモローランド(その他)</option> 24 </select> 25 </div> 26</form>

JavaScript

1 <script> 2 const areaElement = $('#id_area'); 3 const attractionElement = $('#id_attraction'); 4 const area_attraction = { 5       //一部のみ記載 6 '----選択してください': [ 7 { 8 'value': '----エリアを選択してください', 9 'name': '----エリアを選択してください' 10 }, 11 ], 12 'ワールドバザール': [ 13 { 14 'value': 'オムニバス', 15 'name': 'オムニバス' 16 }, 17 { 18 'value': 'ペニーアーケード', 19 'name': 'ペニーアーケード' 20 }, 21 { 22 'value': 'ワールドバザール(その他)', 23 'name': 'ワールドバザール(その他)' 24 }, 25 ], 26 }; 27 console.log("area_attraction", area_attraction) 28 29 const changeArea = (select) => { 30 attractionElement.children().remove(); 31 const parentId = areaElement.val(); 32  console.log("parentId", parentId) 33 const categoryList = area_attraction[parentId]; 34  console.log("categoryList", categoryList) 35 for (const category of Object.key(categoryList)) { 36  console.log("category", category) 37 const option = $('<option>'); 38 option.val(category['value']); 39 option.text(category['name']); 40 attractionElement.append(option); 41 } 42 if (select !== undefined) { 43 attractionElement.val(select); 44 } 45 }; 46 47 $('#id_area').on('change', () => { 48 changeArea(); 49 }); 50 51 if (areaElement.val()) { 52 const selectedCategory = attractionElement.val(); 53 changeArea(selectedCategory); 54 } 55 </script>

forms.py

python

1from .models import Area, Attraction, Category 2 3class PostForm(forms.Form): 4 5 title = forms.CharField(max_length=50, label='タイトル') 6 area = forms.ModelChoiceField(queryset=Area.objects.all(), label='エリア', widget=forms.Select, initial="----選択してください") 7 attraction = forms.ModelChoiceField(queryset=Attraction.objects.all(), label='アトラクション', widget=forms.Select, initial="----エリアを選択してください") 8 category = forms.ModelChoiceField(queryset=Category.objects.all(), label='カテゴリ', widget=forms.Select, initial="----選択してください") 9 content = forms.CharField(label='内容', widget=forms.Textarea()) 10 image = forms.ImageField(label='イメージ画像', required=False)

models.py

python

1class Area(models.Model): 2 name = models.CharField("エリア", max_length=100) 3 slug = models.SlugField("スラッグ") 4 5 def __str__(self): 6 return str(self.name) 7 8class Attraction(models.Model): 9 name = models.CharField("アトラクション", max_length=100) 10 slug = models.SlugField("スラッグ") 11 12 def __str__(self): 13 return str(self.name) 14 15class Category(models.Model): 16 name = models.CharField("カテゴリ", max_length=100) 17 slug = models.SlugField("スラッグ") 18 19 def __str__(self): 20 return str(self.name) 21 22class Post(models.Model): 23 author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) 24 area = models.ForeignKey(Area, verbose_name='エリア', on_delete=models.CASCADE) 25 attraction = models.ForeignKey(Attraction, verbose_name='アトラクション', on_delete=models.CASCADE) 26 category = models.ForeignKey(Category, verbose_name='カテゴリ', on_delete=models.CASCADE) 27 title = models.CharField("タイトル", max_length=200) 28 image = models.ImageField(upload_to='images', verbose_name='Image画像', null=True, blank=True) 29 content = models.TextField("本文") 30 created = models.DateTimeField("作成日", default=timezone.now) 31 public = models.BooleanField("公開フラグ", default=False) 32

###開発環境
・Visual Studio Code 1.59
・mac OS Catalina 10.15.7
・Github
・Python 3.8.3
・Django 2.2.10
・PostgreSQL

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

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

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

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

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

k4a

2021/11/06 08:01

1. `area_attraction`のオブジェクト構造が破綻しています。一部のみ記載とのことですが、省略する場合でも正しい形式で記載して下さい。 2. javascriptの問題であればPythonではなく素のHTMLにレンダリングされたコードを記載したほうが回答が集まりやすいかと思います。
minari766

2021/11/06 09:55

ご助言有難うございます! 1. 余分な"],"を削除いたしました。 2. おっしゃる通りです!HTML上のレンダリングフィールドをHTMLに変換し、JSと分割いたしました。 また何かわかりづらい所や不備等ありましたらご指摘いただけますと幸いです。
guest

回答1

0

ベストアンサー

js

1 const area_attraction = { 2 //一部のみ記載 3 '----選択してください': [{ 4 'value': '----エリアを選択してください', 5 'name': '----エリアを選択してください' 6 }, ], 7 'ワールドバザール': [{ 8 'value': 'オムニバス', 9 'name': 'オムニバス' 10 }, 11 { 12 'value': 'ペニーアーケード', 13 'name': 'ペニーアーケード' 14 }, 15 { 16 'value': 'ワールドバザール(その他)', 17 'name': 'ワールドバザール(その他)' 18 }, 19 ], 20 };

area_attractionは連想配列です。配列(リスト風オブジェクト)ではありません。
オブジェクトへのアクセスはobject[key]です。object[index]ではありません。

<option value="1">のようにインデックス風のvalueを設定して、以下のようにオブジェクトへアクセスをするのは間違いです。

const parentId = areaElement.val(); const categoryList = area_attraction[parentId];

インデックスでのアクセスをするならObject.entries(object)[index]のようになりますが、今回の場合は(本投稿でobjectが省略されているのもあり)不適合です。

optionのvalueにワールドバザール等の文字列を設定するか、以下のようにワールドバザール等のテキストparentIdにする必要があります

const parentId = $('#id_area option:selected').text(); const categoryList = area_attraction[parentId];

上の処置で取得できるcategoryListは以下の構造を持ちます。

[ { 'value': 'オムニバス', 'name': 'オムニバス' }, { 'value': 'ペニーアーケード', 'name': 'ペニーアーケード' }, { 'value': 'ワールドバザール(その他)', 'name': 'ワールドバザール(その他)' }, ],

これは配列です。したがってfor-ofでのObject.key(categoryList)は間違いです。
配列であるcategoryListに対して直接for-ofを回すことができます。

diff

1- for (const category of Object.key(categoryList)) { 2+ for (const category of categoryList) { 3

どのようなデータ構造か、何をどう処理するのかを考えれば分かる問題ですので、丁寧に構造を把握することをおすすめします。

投稿2021/11/06 10:29

k4a

総合スコア983

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

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

minari766

2021/11/06 15:56

ご教示いただいた方法でエラー解決できました! 各種データ構造について理解が全く足りていないので、改めて確認してみたいと思います。 有難うございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問