連続発火させるイベントのid取得(attr)

こんにちは、daissh04です。2回目の執筆になります。

今回もプログラミングスクールの最終課題で詰まったとこの備忘録をつけていきます。

 

今回は$(this)を使用するケースについてメモしたいと思います。

 

以下のような方向けに記事書きます。

・$(this)の使い方がよくわからない。

 

この記事を最後まで読んでいただくと、

・$(this)の使い方が何となくイメージできる

・$(this)を使用しないとどうなるかがわかる

を目指して書きたいと思います。

 

【今回やりたいこと】

今回実装しようとしている機能は下記画像のようなものです。

f:id:daissh04:20200222133812p:plain

カテゴリークラスにマウスオーバーすると

1. 親要素をリスト表示

2. 親要素にマウスオーバーするとその子要素を表示

3. 子要素にマウスオーバーするとその孫要素を表示

俗に言うアコーディオンメニューと言うやつです。

 

親、子、孫の多階層カテゴリーについて詳しく知りたい方は下記の記事を参考にどうぞ

参考記事:

https://qiita.com/Sotq_17/items/120256209993fb05ebac

https://qiita.com/ATORA1992/items/bd824f5097caeee09678

https://qiita.com/ATORA1992/items/03eb78e212080072ab9f

 

今回私が$(this)の重要性を痛感したのは、

親をマウスオーバーした時に、選択された親のカテゴリIDを取得し、ajax送信。

そしてコントローラーでその子要素を取得しビューに返すと言う処理です。

 

`<div class = 'categorySearch__parentitem'>
<a href= "/items/search/${categoryParent.id}",
id = "${categoryParent.id}", class = "category_link">${categoryParent.name}</a>
</div>`

 

親要素のhtmlです。各親要素をaタグで表示、各々IDに自分のカテゴリーIDを持たせています。

各aタグにマウスオーバーした時にidである各々のカテゴリーIDを取得したい!

$('.categorySearch').on("mouseenter", ".category_link", function(){
var parentID = '';
parentID = $(".category_link").attr('id')
console.log(parentID)

当初私は上記のコードを書いてました、categorySearchにマウスエンターした際にcategory_linkのidをparentIDに格納する。

var parentID = '';はカーソルが違う親をマウスオーバーした際にすでに格納されてるidをリセットし上書きする為です。

 

これでconsole.logでparentIDに格納されるデータを吐き出したところ、レディースをマウスオーバーしたら1が出力されました!

やった!うまく取得できたとぬか喜びし、そのまま次のメンズにカーソルを移したところまた1が取得されました。

 

ん?何かがおかしい

 

ベイビー・キッズ、本にカーソル当てても全部1が取得されました。

なぜやーー!!idはそれぞれ違うはずなのに、なぜ常に1なのだー!

 

悩んでも、ふて寝しても解決できない為、チームメンバーに聞きました。

メンターさんにも聞きました。

 

すると、親カテゴリーはidは異なってるけど、classは一緒になってませんか?と言う質問。。。はい、そうなってます。

 

メンターさん:その場合この記述だとidが複数あったとしても最初idを常に取得してしまいます。

parentID = $(".category_link").attr('id')

メンターさん:その場合は$(this)を使用して下さい。発火した要素をちゃんと捉えてくれます。

私は速攻で下記コードに修正しました

$('.categorySearch').on("mouseenter", ".category_link", function(){
var parentID = '';
parentID = $(this).attr('id')
console.log(parentID)

そうすると、見事にレディース選択時は1、メンズは219とconsoleで吐き出せたのです。メンターさん見事、感服しました

 

まず一般的に$(this)はイベントの発生元になった要素を取得することができる。

参考記事:

https://www.sejuku.net/blog/6436

ふむふむ、よく言われるやつですね。

今回の例で同一クラスで異なるidを連続で取得したい場合、クラス名.attr('id')だと最初のidのみが取得されます。

その解決方法は$(this)だと言うことを身を以て学びました。もう忘れません。

 

みなさん$(this)の理解が深まればと思います

 

まただらだらとすみません。次回は完結に書きたいと思います

 

 

【Rails】配列の中で異なる配列に合致する要素を表示

こんにちは、daissh04です。

Railsの勉強を初めて約半年になりますが初めてブログ書きます。

知識至らぬ点多々あると思いますが、もっといいやり方等あれば

ご指摘、コメントください。

 

プログラミングスクールの最終課題でフリマアプリを熱烈作成中です。

そこで実装に困ったことを中心に備忘録としてブログに残して行きたいと思います

 

【概要】

この記事ではフリマアプリのトップページにて、カテゴリ毎に商品を表示したい。

のやり方について説明します

 

例えば下記画像のようにレディース欄にはitemテーブルのcategory_idがレディース系のIDを持っているitemのみ表示するといった具合です。

f:id:daissh04:20200222041705j:plain

⬆️レディースの欄には

f:id:daissh04:20200222041924p:plain

⬆︎category_idがレディース系のitemを表示

f:id:daissh04:20200222042130p:plain

この記事では詳しく触れませんがカテゴリはRailsのgem ancestryを使用しています。

上画像のようにNullクラスが親、1桁のカテゴリはその子、親/子は孫といった具合に多階層の関係をもつことができます。

 

レディース系のカテゴリというのは、レディースを親にもつ全カテゴリという訳です。

 

ancestryについては以下の記事を参考にしました。

参考記事:

https://qiita.com/Sotq_17/items/120256209993fb05ebac

https://qiita.com/ATORA1992/items/bd824f5097caeee09678

https://qiita.com/ATORA1992/items/03eb78e212080072ab9f

 

【詳細】

まずはトップメニューに表示する全商品を@itemsに格納します

@item = Item.new
@items = Item.all

そしてレディース系のカテゴリを持つ商品を@ladies_grandchildに格納します

@ladies = Category.find(1)
@ladies_grandchild = @ladies.indirects

indirectsはancestryが持つメソッドで指定した親が持つ孫要素を全て抽出するという超便利メソッドです。

ancestryは色々なメソッドがあるので調べてみて下さい。

 

やりたいことは、

全アイテムの@itemsの中で、cateogry_idが@ladies_grandchildのcategory_idとイコールのitemのみ表示することです。

 

私は何の疑いもなく下記のようにコードしました

- @items.order('created_at DESC').each do |item|
- if item.category_id == @ladies_grandchild.id

頭に描いていたのはitemのcategory_idとレディース系のidがイコールにあるものを表示

することでしたがうまくいきませんでした。

 

ここで理由がわからず、サイトやチームメンバーと議論したところ、@ladies_grandchildrenが配列のままであり、中の要素まで比較できてないのでは?という指摘でした。

コントロールにbinding.pryを入力し、データを調べると

gyazo.com

 

5行目のに [  で始まってます。今更ですが、Railsのハッシュをもつ複数のデータを格納させると連想配列として格納されます。

 

つまり連想配列である@ladies_grandchildに@ladies_grandchild.idとしても取得できな訳です。

 

基本に帰ります。配列の中の要素を抽出したい時はeachです。 

- @items.order('created_at DESC').each do |item|
-@ladies_grandchild.each do |lady|
- if item.category_id == lady.id

 

@itemsはeachで展開されているので、eachの中にさらにeachでバラしてみました。

そうするとうまく表示することができました。

 

@itemsの数だけさらに@ladies_grandchildをeach展開しているので、レスポンスが心配でしたが、一応やりたいことはできました。

 

ただ、出品数が増えるとレスポンスの影響が必ず出るので、ほかのやり方調べてます。

 

参考書で配列はeachで展開すると頭では知ってたのですが、いざ実装し変化球でくるとそこまで頭で辿りつけませんでした。

 

アウトプットが大事って言われるのはそういう気づきの為かもしれませんね、

まだまだ頑張ります。

 

だらだらと書いて申し訳ありません。最後までお付き合いありがとうございました