honapon
@honapon

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【初心者】JavaScript オブザーバパターンのコードがうまく機能しない

解決したいこと

現在Java Scriptのオブザーバパターンを使って以下の機能のコードを実装中です。

【機能】年・月・日のアイテムのあるカレンダー(当初は本日を表示)の
アイテムのいずれかが変更されたときに、その下にある
曜日の表示を連動して、変更する。

発生している問題・エラー

Subjectクラスを作成し、addObserverメソッド(オブザーバの追加機能)と
notifyObservers(オブザーバーに変更を知らせる機能(オブザーバのもつupdateメソッドの実行))を実装。

その後のオブザーバの追加、そしてnotifyObserversメソッドの発火が
上手く行っていないようで、コード最終部分にあるインスタンス構造の組み立て自体がうまく行っていない可能性があります。
Observerの追加、そしてインスタンスの生成部分について正しい考え方・書き方をご教示頂けると嬉しいです。
以下該当コードです。(約80行、HTMLは省略しております.)


    class Subject {
        observers = []

        addObserver(observer) {
            this.observers.push(observer)
            console.log(this.observers)
        }

        
          //オブザーバのupdate メソッドを呼び出す。
        notifyObservers() {
            this.observers.forEach((observer) => {
                observer.update(this)
            })
        }
    }
        //以下怪しいと思われるTargetDayクラスです。

    class TargetDay extends Subject {
        constructor(el) { 
            super()     
            this.el = el
            this.el.addEventListener('change', this.onChange.bind(this))
        }
        onChange() {
            // オブザーバに該当の要素が変更されたことを通知する。
            this.notifyObservers()
        }
    }
            class Observer {
        update(subject) {
            throw new Error('ここではなく子クラスで実装を行う')
        }
    }
       class MyCalendar extends Observer {
   ・・・・・カレンダーの表示機能・・・・・
}

    class DayOfWeek {
 ・・・・・曜日の表示機能・・・・・・・
      constructor(el, day) {
            this.el = el;//曜日の表示場所
            this.showDayOfWeek(day);//曜日の表示機能
        }
     ・・・
      update(calendar) { //日付が変わったときに呼び出したいメソッド。これがうまく機能しない
       this.showDayOfWeek(calendar.get())
     ・・・
        } }



・・・・・・・・・略・・・・・・・・・・・・・・・

//以下怪しいと思われるインスタンスのコードです。
 const today = new Date()
 const cal1 = new MyCalendar(document.getElementById('calender1'), today) //カレンダー
const targetday1 = new TargetDay(document.getElementById('calender1'))
const dayOfWeek1 = new DayOfWeek(document.getElementById("day-of-week"), cal1.get())//getは表示中の日付の取得メソッド。表示中の日付を使って曜日を所定の場所に表示

targetday1.addObserver(dayOfWeek1)//ここでカレンダーの日付が変わるたびに曜日を
変えるようにしたかったのですが、日付を変えても本日の曜日がずっと表示されている状況

自分で試したこと

オブザーバの追加まではコンソールで確認(DayOfWeekクラス)が出来たので、
最後の5行あるいは追加したTargetDayクラスのコードが違うのではないかと考えました。

0

2Answer

直接 targetday1.onChange() を呼び出してみたら updateメソッドが呼ばれたので、
this.el.addEventListener('change', this.onChange.bind(this))
による change イベントが発生しなくて onChangeメソッドが呼ばれていないのではありませんか?
だとしたら、GUIコンポーネント側の問題かイベント名指定ミスかと思われます。

class Subject {
    observers = [];

    addObserver(observer) {
        this.observers.push(observer);
        console.log(this.observers);
    }

    notifyObservers() {
        this.observers.forEach(observer => observer.update(this));
    }
}

class TargetDay extends Subject {
    onChange() {
        this.notifyObservers()
    }
}

class Observer {
    update(subject) {
        throw new Error('ここではなく子クラスで実装を行う')
    }
}

class MyCalendar extends Observer {
}

class DayOfWeek {
    update(calendar) { //日付が変わったときに呼び出したいメソッド。これがうまく>機能しない
        console.log("updated");
    }
}

const today = new Date();
const cal1 = new MyCalendar(today);
const targetday1 = new TargetDay();
const dayOfWeek1 = new DayOfWeek();
targetday1.addObserver(dayOfWeek1);
targetday1.onChange();
実行結果
[ DayOfWeek {} ]
updated
1Like

丁寧に解説頂き、ありがとうございます!仰っていただいた通りイベント発火の仕方に問題がありました。onChangeイベントを見直したところ、動くようになりました。ありがとうございます!

0Like

Your answer might help someone💌