emadalam / atvjs

Blazing fast Apple TV application development using pure JavaScript
https://emadalam.github.io/atvjs
MIT License
311 stars 49 forks source link

Refreshing app #35

Closed tortillaj closed 7 years ago

tortillaj commented 7 years ago

@emadalam this isn't an issue so much as a question - How would you go about refreshing the UI when you need new data to populate? For example, if you have a movie listing page, periodically the list of movies changes. I'd like to cause the UI to refresh periodically. Thanks in advance 😄

emadalam commented 7 years ago

@tortillaj You can use the afterReady callback configuration to start the timed update of your rendered page document.

const UPDATE_INTERVAL = 10000;
const fetching = false;

const HomePage = ATV.Page.create({
    name: 'home',
    template: template,
    ready(options, resolve, reject) {
        // normal resolve/reject
    },
    afterReady(doc) {
        // document instance is available
        // as `doc` variable
        setInterval(() => {
            if (fetching) return;
            fetching = true;
            ATV.Ajax.get('path/to/fetch/data')
                .then(results => {
                    fetching = false;
                    // update tvml document
                    // using the `doc`
                }).catch(xhr => {
                    fetching = false;
                    // error catching
                });
        }, UPDATE_INTERVAL);
    }
});

I have created a very verbose example in the appletv-demo app for your use case, have a look. I'm doing a dirty replacement of the whole tvml template on result update, but obviously for any live application you would want to elegantly update only the specific dom elements from the tvml document. Nevertheless, it should be a good starting point for your use case.

Feel free to close this issue once you have tested this solution to be working. Also if you ever feel like documenting or sharing anything related to the library, please do so, I'd be more that happy to accept those in form of PRs of even reference points that I can include in the wikis and docs. Also you may post on the gitter group.

Branch: AutoRefresh-Demo File: https://github.com/emadalam/appletv-demo/blob/AutoRefresh-Demo/web/app/pages/home/index.js

tortillaj commented 7 years ago

@emadalam - thanks a lot! This is very helpful.

tortillaj commented 7 years ago

@emadalam this is working well. I did a few extra steps to reduce the polling where possible. Basically I set the interval ID to a property of the page. Then, listening on the appear and disappear events, I can disable or restart the interval. That way, when the user navigates off the page, the polling stops.

const UPDATE_INTERVAL = 10000;
const fetching = false;

const HomePage = ATV.Page.create({
    name: 'home',
    template: template,
    events: {
        appear: 'onAppear',
        disappear: 'onDisappear'
    },
    ready(options, resolve, reject) {
        // normal resolve/reject
    },
    afterReady(doc) {
        // document instance is available
        // as `doc` variable
        this.setRefreshTimer(doc);
    },
    refreshTimerId: null,
    setRefreshTimer(doc) {
        this.refreshTimerId = setInterval(() => {
            if (fetching) return;
            fetching = true;
            ATV.Ajax.get('path/to/fetch/data')
                .then(results => {
                    fetching = false;
                    // update tvml document
                    // using the `doc`
                }).catch(xhr => {
                    fetching = false;
                    // error catching
                });
        }, UPDATE_INTERVAL);
    },
    clearRefreshTimer() {
        clearInterval(this.refreshTimerId);
        this.refreshTimerId = null;
    },
    onAppear() {
        if (this.refreshTimerId) return;

        let doc = getActiveDocument();
        this.setRefreshTimer(doc);
    },
    onDisappear() {
        if (!this.refreshTimerId) return;
        this.clearRefreshTimer();
    }
});

This is just pseudo-code mostly, but you get the idea! I will add some more checking to ensure the fetched data does not match the current data. No need to interact with the DOM again if I don't have to.

Thanks again for the help!

emadalam commented 7 years ago

Perfect! I'm glad it helped :) Closing this issue now.