متغيران متتبعان لا يُحدّثان

لدي الكود التالي:

import Component from "@glimmer/component";
import { apiInitializer } from "discourse/lib/api";
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { inject as service } from "@ember/service";
import { defaultHomepage } from "discourse/lib/utilities";


/*
const xhr = new XMLHttpRequest();
xhr.open("GET", "/cakeday/anniversaries/today.json");
xhr.send();
xhr.responseType = "json";
xhr.onload = () => {
    if (xhr.readyState == 4 && xhr.status == 200) {
        let resp = xhr.response;
        let numberOfAnns = resp['total_rows_anniversaires'];
        let allAnns = resp['anniversaries']; // Is a list of dicts
        console.log(allAnns);
        let allAnnsUsernames = [];
        for (var annUserdata in allAnns) {
            console.log(allAnns[annUserdata]['username']);
            allAnnsUsernames.push(allAnns[annUserdata]['username']);
        }
        var annsOfData = {'num_anns': numberOfAnns, 'anns_users': allAnnsUsernames};
        
    }
};
return annsOfData;
*/


export default apiInitializer("1.14.0", (api) => {
    //const banner_location = settings.banner_location
    api.renderInOutlet(
        settings.banner_location,
        class BdaysAnnsBanner extends Component {
            @tracked annsDataFinal = null;
            @tracked bdaysDataFinal = null;
            @tracked areBothBannersVisible = true;
            @tracked isAnnsVisible = null;
            @tracked isBdaysVisible = null;

            @service router;

            constructor() {
                super(...arguments);
                this.fetchAnnsData(); // Automatically fetch on initialization
                this.fetchBdaysData();
            }
        
            // Asynchronously fetch the data and update tracked property
            @action
            async fetchAnnsData() {
                const response = await fetch("/cakeday/anniversaries/today.json");
                const json = await response.json();
        
                let numberOfAnns = parseInt(json['total_rows_anniversaries']);
                let allAnns = json['anniversaries']; // Is a list of dicts
                let allAnnsUsernames = [];
        
                for (let annUserdata of allAnns) {
                    allAnnsUsernames.push(annUserdata['username']);
                }
        
                this.annsDataFinal = {'num_anns': numberOfAnns, 'anns_users': allAnnsUsernames, 'visible': true, 'isFilled': true};
                this.updateBothBannersVisibility(this.annsDataFinal);
            }

            // Asynchronously fetch the data and update tracked property
            @action
            async fetchBdaysData() {
                 // Declare bdaysDataFinal here
                let bdaysDataFinal;
            
                // Fetch birthdays data
                const response = await fetch("/cakeday/birthdays/today.json");
                const json = await response.json();
            
                // Run the logic to process the data
                let numberOfBdays = parseInt(json['total_rows_birthdays']);
                let allBdays = json['birthdays']; // Is a list of dicts
                let allBdaysUsernames = [];
            
                for (let bdayUserdata of allBdays) {
                    allBdaysUsernames.push(bdayUserdata['username']);
                }
            
                this.bdaysDataFinal = {'num_bdays': numberOfBdays, 'bdays_users': allBdaysUsernames, 'visible': true, 'isFilled': true};
                this.updateBothBannersVisibility(this.bdaysDataFinal);
                //console.log(annsDataFinal);  // Just to verify the result
            }


            @action
            updateBothBannersVisibility(bannerData) {
                console.log(bannerData.num_anns);
                // Check if it's anns or bdays
                if (bannerData.num_anns) { // It's anns
                    console.log('Anns:')
                    console.log(bannerData.num_anns);
                    if (bannerData.num_anns == 0 && settings.hide_unused_data) {
                        console.log(`Anns+setting: ${bannerData.num_anns == 0 && settings.hide_unused_data}`);
                        this.isAnnsVisible = false;
                        console.log(`isAnnsV: ${this.isAnnsVisible}`);
                        //console.log(this.isBdaysVisible);
                    }
                } else { // It's bdays  
                    console.log(bannerData.num_bdays);
                    if (bannerData.num_bdays == 0 && settings.hide_unused_data) {
                        console.log(`Bdays+setting: ${bannerData.num_bdays == 0 && settings.hide_unused_data}`);
                        this.isBdaysVisible = false;
                        console.log(`isBdaysV: ${this.isBdaysVisible}`);
                        //console.log(this.isAnnsVisible);
                    }
                }
                console.log(`isAnnsV: ${this.isAnnsVisible}`);
                console.log(`isBdaysV: ${this.isBdaysVisible}`);
                // Uses an inequality. If not the same (true), banner is shown. If it is the same, inequality is not satisfied, and the banner will be hidden.
                this.areBothBannersVisible = !(this.isAnnsVisible === false && this.isBdaysVisible === false); // Or: this.areBothBannersVisible = this.isAnnsVisible || this.isBdaysVisible;
                console.log(this.areBothBannersVisible);
            }

            
            // Getter for the data
            get annsData() {
                //return this.annsDataFinal;
                if (this.annsDataFinal !== null) {
                    if (this.annsDataFinal.num_anns == 0) {
                        if (settings.hide_unused_data) {
                            this.annsDataFinal.isFilled = false;
                            this.annsDataFinal.visible = false;
                        } else {
                            this.annsDataFinal.isFilled = false;
                        }
                    } else {
                        this.annsDataFinal.isFilled = true;
                        this.annsDataFinal.visible = true;
                    }
                    
                    //this.updateBothBannersVisibility(this.annsDataFinal);
                    // If the data is not loaded yet, return null or any default value
                    return this.annsDataFinal;
                }
            }
        
            // Getter for the data
            get bdaysData() {
                //return this.bdaysDataFinal;
                if (this.bdaysDataFinal !== null) {
                    if (this.bdaysDataFinal.num_bdays == 0) {
                        if (settings.hide_unused_data) {
                            this.bdaysDataFinal.isFilled = false;
                            this.bdaysDataFinal.visible = false;
                        } else {
                            this.bdaysDataFinal.isFilled = false;
                            this.bdaysDataFinal.visible = true;
                        }
    
                    } else {
                        this.bdaysDataFinal.isFilled = true;
                        this.bdaysDataFinal.visible = true;
                    }

                    //this.updateBothBannersVisibility(this.bdaysDataFinal);
                    // If the data is not loaded yet, return null or any default value
                    return this.bdaysDataFinal;
                }
            }

            get isHomepage() {
                const { currentRouteName } = this.router;
                return currentRouteName === `discovery.${defaultHomepage()}`;
            }
            //console.log(this.areBothBannersVisible);

            <template>
                {{#if this.areBothBannersVisible}}
                    {{#if this.isHomepage}}
                        <div class='bdaysannsbanner' id='bdaysannsbanner'>
                            {{#if this.annsData.visible}}
                                <div class='anns'>
                                    {{#if this.annsData.isFilled}}
                                        <p>{{this.annsData.num_anns}} users are celebrating their anniversary!</p>
                                        <!-- Display the anniversaries data -->
                                        {{#each this.annsData.anns_users as |username|}}
                                            <span><a class='mention'>{{username}}</a></span>
                                        {{/each}}
                                    {{else}}
                                        <p>No one has their anniversary today!</p>
                                    {{/if}}
                                </div>
                            {{/if}}
                            <br />
                            {{#if this.bdaysData.visible}}
                                <div class='bdays'>
                                    {{#if this.bdaysData.isFilled}}
                                        <p>{{this.bdaysData.num_bdays}} users are celebrating their birthday!</p>
                                        <!-- Display the birthday data -->
                                        {{#each this.bdaysData.bdays_users as |username|}}
                                            <span><a class='mention'>{{username}}</a></span>
                                        {{/each}}
                                    {{else}}
                                        <p>No one is celebrating their birthday today!</p>
                                    {{/if}}
                                </div>
                            {{/if}}
                        </div>
                    {{/if}}
                {{/if}}
            </template>
        }
    );
});

الجزء الذي لا يعمل هو المتغيرات this.isAnnsVisible و this.isBdaysVisible. لا يبدو أنها يتم تحديثها، مما يتسبب في عرض اللافتة.

إعجاب واحد (1)

من الغريب أن هذه المتغيرات لا يتم تحديثها. هل يمكن أن يكون ذلك بسبب عدم استخدامها بشكل صحيح؟

أعتذر عن إعادة فتح هذا الموضوع، لكنني ما زلت لا أعرف سبب حدوث ذلك.
الكود الخاص بي الآن:

import Component from "@glimmer/component";
import { apiInitializer } from "discourse/lib/api";
import { ajax } from "discourse/lib/ajax";
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { inject as service } from "@ember/service";
import { defaultHomepage } from "discourse/lib/utilities";
import { getOwner } from '@ember/application';


export default apiInitializer("1.14.0", (api) => {
    //const banner_location = settings.banner_location

    api.renderInOutlet(
        settings.banner_location,
        class BdaysAnnsBanner extends Component {
            @tracked annsDataFinal = null;
            @tracked bdaysDataFinal = null;
            @tracked areBothBannersVisible = true;
            @tracked isAnnsVisible = null;
            @tracked isBdaysVisible = null;

            @service router;

            constructor() {
                super(...arguments);
                this.fetchAnnsData(); // جلب تلقائي عند التهيئة
                this.fetchBdaysData();
            }

            // جلب البيانات بشكل غير متزامن وتحديث خاصية التتبع
            @action
            async fetchAnnsData() {
                const response = await fetch("/cakeday/anniversaries/today.json");
                const json = await response.json();
                console.log(json);
                let numberOfAnns = parseInt(json['total_rows_anniversaries']);
                let allAnns = json['anniversaries']; // قائمة من القواميس
                let allAnnsUsernames = [];

                for (let annUserdata of allAnns) {
                    allAnnsUsernames.push(annUserdata['username']);
                }

                this.annsDataFinal = {'num_anns': numberOfAnns, 'anns_users': allAnnsUsernames, 'visible': true, 'isFilled': true};
                this.updateBothBannersVisibility(this.annsDataFinal);
            }

            // جلب البيانات بشكل غير متزامن وتحديث خاصية التتبع
            @action
            async fetchBdaysData() {
                 // تعريف bdaysDataFinal هنا
                let bdaysDataFinal;

                // جلب بيانات أعياد الميلاد
                const response = await fetch("/cakeday/birthdays/today.json");
                const json = await response.json();

                // تشغيل المنطق لمعالجة البيانات
                let numberOfBdays = parseInt(json['total_rows_birthdays']);
                let allBdays = json['birthdays']; // قائمة من القواميس
                let allBdaysUsernames = [];

                for (let bdayUserdata of allBdays) {
                    allBdaysUsernames.push(bdayUserdata['username']);
                }

                this.bdaysDataFinal = {'num_bdays': numberOfBdays, 'bdays_users': allBdaysUsernames, 'visible': true, 'isFilled': true};
                this.updateBothBannersVisibility(this.bdaysDataFinal);
                //console.log(annsDataFinal);  // للتحقق من النتيجة فقط
            }


            @action
            updateBothBannersVisibility(bannerData) {
                console.log(bannerData.num_anns);
                // التحقق مما إذا كانت الذكرى السنوية أم أعياد الميلاد
                if (bannerData.num_anns) { // إنها الذكرى السنوية
                    console.log('Anns:')
                    console.log(bannerData.num_anns);
                    if (bannerData.num_anns == 0 && settings.hide_unused_data) {
                        console.log(`Anns+setting: ${bannerData.num_anns == 0 && settings.hide_unused_data}`);
                        this.isAnnsVisible = false;
                        console.log(`isAnnsV: ${this.isAnnsVisible}`);
                        //console.log(this.isBdaysVisible);
                    }
                } else { // إنها أعياد الميلاد
                    console.log(bannerData.num_bdays);
                    if (bannerData.num_bdays == 0 && settings.hide_unused_data) {
                        console.log(`Bdays+setting: ${bannerData.num_bdays == 0 && settings.hide_unused_data}`);
                        this.isBdaysVisible = false;
                        console.log(`isBdaysV: ${this.isBdaysVisible}`);
                        //console.log(this.isAnnsVisible);
                    }
                }
                console.log(`isAnnsV: ${this.isAnnsVisible}`);
                console.log(`isBdaysV: ${this.isBdaysVisible}`);
                // يستخدم عدم المساواة. إذا لم تكن متساوية (صحيح)، يتم عرض اللافتة. إذا كانت متساوية، لا يتم تحقيق عدم المساواة، وسيتم إخفاء اللافتة.
                this.areBothBannersVisible = !(this.isAnnsVisible === false && this.isBdaysVisible === false); // أو: this.areBothBannersVisible = this.isAnnsVisible || this.isBdaysVisible;
                console.log(this.areBothBannersVisible);
            }


            // Getter للبيانات
            get annsData() {
                //return this.annsDataFinal;
                if (this.annsDataFinal !== null) {
                    if (this.annsDataFinal.num_anns == 0) {
                        if (settings.hide_unused_data) {
                            this.annsDataFinal.isFilled = false;
                            this.annsDataFinal.visible = false;
                            this.isAnnsVisible = false;
                        } else {
                            this.annsDataFinal.isFilled = false;
                        }
                    } else {
                        this.annsDataFinal.isFilled = true;
                        this.annsDataFinal.visible = true;
                    }

                    //this.updateBothBannersVisibility(this.annsDataFinal);
                    // إذا لم يتم تحميل البيانات بعد، أرجع null أو أي قيمة افتراضية
                    return this.annsDataFinal;
                }
            }

            // Getter للبيانات
            get bdaysData() {
                //return this.bdaysDataFinal;
                if (this.bdaysDataFinal !== null) {
                    if (this.bdaysDataFinal.num_bdays == 0) {
                        if (settings.hide_unused_data) {
                            this.bdaysDataFinal.isFilled = false;
                            this.bdaysDataFinal.visible = false;
                            this.isBdaysVisible = false;
                            console.log(`this.isAnnsVisible: ${this.isAnnsVisible}`);
                            console.log(`this.isBdaysVisible: ${this.isBdaysVisible}`);
                        } else {
                            this.bdaysDataFinal.isFilled = false;
                            this.bdaysDataFinal.visible = true;
                        }

                    } else {
                        this.bdaysDataFinal.isFilled = true;
                        this.bdaysDataFinal.visible = true;
                    }

                    //this.updateBothBannersVisibility(this.bdaysDataFinal);
                    // إذا لم يتم تحميل البيانات بعد، أرجع null أو أي قيمة افتراضية
                    return this.bdaysDataFinal;
                }
            }

            get isHomepage() {
                const { currentRouteName } = this.router;
                return currentRouteName === `discovery.${defaultHomepage()}`;
            }
            //console.log(this.areBothBannersVisible);

            <template>
                {{#if this.areBothBannersVisible}}
                    {{#if this.isHomepage}}
                        <div class='bdaysannsbanner' id='bdaysannsbanner'>
                            {{#if this.annsData.visible}}
                                <div class='anns'>
                                    {{#if this.annsData.isFilled}}
                                        <p>{{this.annsData.num_anns}} users are celebrating their anniversary!</p>
                                        <!-- Display the anniversaries data -->
                                        {{#each this.annsData.anns_users as |username|}}
                                            <span><a class='mention'>{{username}}</a></span>
                                        {{/each}}
                                    {{else}}
                                        <p>No one has their anniversary today!</p>
                                    {{/if}}
                                </div>
                            {{/if}}
                            <br />
                            {{#if this.bdaysData.visible}}
                                <div class='bdays'>
                                    {{#if this.bdaysData.isFilled}}
                                        <p>{{this.bdaysData.num_bdays}} users are celebrating their birthday!</p>
                                        <!-- Display the birthday data -->
                                        {{#each this.bdaysData.bdays_users as |username|}}
                                            <span><a class='mention'>{{username}}</a></span>
                                        {{/each}}
                                    {{else}}
                                        <p>No one is celebrating their birthday today!</p>
                                    {{/if}}
                                </div>
                            {{/if}}
                        </div>
                    {{/if}}
                {{/if}}
            </template>
        }
    );
});

مستودعي:

لست متأكدًا تمامًا بعد ولكن …

هذه الكلمة await غير ضرورية.

يجب أن يكون الرد بالفعل كائنًا لذلك لست متأكدًا لماذا تحتاج إلى .json() وما إلى ذلك؟ يمكنك على الأرجح تبسيط هذا كثيرًا.

لا تحتاج إلى تمرير هذا لأن المتغيرات المتعقبة موجودة في النطاق طوال المكون، لذا قم فقط باستدعائها والإشارة إليها في الإجراء.

بعض النصائح الأسلوبية:

  • لا تغمر الكود المشترك الخاص بك بـ console.logs، فهذا يجعل من الصعب رؤية الغابة من الأشجار
  • استخدم مسافتين للمسافة البادئة وليس 4، وهو معيار discourse. انظر القالب الخاص بك
  • فكر في نقل هذا إلى ملف .gjs مخصص
  • يمكنك النقر على الأرقام في github والحصول على رابط قابل للمشاركة يعرض الكود إذا احتجت إليه.

متقدم:

  • قم بإعداد Prettier و ESlint … الأول للأسلوب والثاني لكل من الأسلوب وقد يساعدك في اكتشاف بعض الأخطاء.
إعجابَين (2)

ليس هذا، أليس كذلك؟

ليس عليك الذهاب إلى هذا الحد، ولكن هذا خيار.
يكفي القيام بذلك يدويًا في البداية.

إعجاب واحد (1)

من المحتمل أن هذا النوع من الأشياء لا يعمل.

لا أعتقد أن EmberJS سيراقب الخصائص المتداخلة.

يجب عليك إنشاء وتتبع واختبار الخصائص على نفس المستوى.

لذا قم بإنشاء خاصية متتبعة تسمى مثلاً annsDataVisible، قم بتحديث قيمتها واستخدمها في عبارة if الخاصة بك.

إعجاب واحد (1)

يمكنك أيضًا إعادة تعيين الكائن بالكامل في كل مرة بدلاً من مجرد قيمة سمة فرعية قد تؤدي إلى إعادة رسم.

إعجابَين (2)