javascripthtmlfirebase-realtime-databaseonsen-ui

HTML object "list" is not updating after switching between sites


What am I trying to achieve:

Where is the problem:

If you could point me somewhere where I could find answers or point the problem out, I would really appreciate it! Already tried to search on internet for “HTML list is not updating” and similar searches but could not find anything.

I have also tried switching "let" for "var" on line 25. Didn't notice any diffrence.

“main.html” and console after FIRST login:

App 1 Console 1

“main.html” and console after SECOND login (as you can see in console data is successfully downloaded from Firebase – but HTML isn’t updated):

App 2 Console 2

Minimal reproducible code:

<!DOCTYPE html>
<html>
    <head>

    <!-- The core Firebase JS SDK is always required and must be listed first -->
    <script src="https://www.gstatic.com/firebasejs/7.14.2/firebase-app.js"></script>

    <script src="https://www.gstatic.com/firebasejs/7.14.2/firebase-auth.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.14.3/firebase-database.js"></script>

    <meta charset="UTF-8">
    <link rel="stylesheet" href="https://unpkg.com/onsenui/css/onsenui.css">
    <link rel="stylesheet" href="https://unpkg.com/onsenui/css/onsen-css-components.min.css">
    <script src="https://unpkg.com/onsenui/js/onsenui.min.js"></script>
    <script src="https://unpkg.com/jquery/dist/jquery.min.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <script>
    // Your web app's Firebase configuration
    var firebaseConfig = {
      //MY FIREBASE CONFIG DATA
    };
    //Other vars.
    var currentPage = "register.html";
    let myListener;
    var email, family, password;

    // Initialize Firebase
    firebase.initializeApp(firebaseConfig);
    var auth = firebase.auth();
    var db = firebase.database();

    function login(){
        firebase.auth().signInWithEmailAndPassword(email, password).then(function(user){
                // user signed in
                goToPage('main.html'); 

                firebase.database().ref('/users/' + auth.currentUser.uid).once('value').then(function(snapshot) {
                    family = snapshot.val().family;
                    addDataListener();
                });

            }).catch(function(error) {

                // Handle Errors here.
                var errorCode = error.code;
                console.log(errorCode);

                if (errorCode){
                    ons.notification.alert('Error!');
            }
        });
    }

    function logout(){
        goToPage('login.html'); 

        firebase.auth().signOut().then(function() {
            console.log("I just log out");
            }, function(error) {
             console.log("Some error: ", error);
        });    
    }

    function addDataListener(){
        console.log("Listener is set up!");

        myListener = firebase.database().ref('families/' + family).on('value', function(snapshot) {
            if (currentPage !== "main.html") return;
            console.log(snapshot.val());

            var list = document.getElementById('list'); 

            //Empty list
            while (list.hasChildNodes()) {  
                list.removeChild(list.firstChild);
            }

            //Read all items in firebase and add them to the list
            Object.keys(snapshot.val()).forEach(function(k){
                console.log(k + ' - ' + snapshot.val()[k]);

                var onsItem = document.createElement('ons-list-item');    
                onsItem.innerHTML = snapshot.val()[k]; 
                onsItem.setAttribute('id', k);
                list.appendChild(onsItem);  
            });

        });
    }

    function goToPage(newPage){
        currentPage = newPage;

        var myNavigator = document.getElementById('myNavigator');
        myNavigator.pushPage(newPage);   
    }
    </script>



    </head>

    <body>
    <ons-navigator swipeable id="myNavigator" page="login.html"></ons-navigator>


    <template id="login.html">
    <ons-page id="login">
    <!--Page name-->
        <ons-toolbar>
          <div class="center">Login page</div>
        </ons-toolbar>

    <!--Inputs-->    
    <ons-list>       
        <ons-list-item tappable>
            <div class="center">
            Email: 
                <ons-input id="email_login" type="email" onchange = "email = this.value"></ons-input>
            </div> 
        </ons-list-item>   

        <ons-list-item tappable>
            <div class="center">
            Password: 
                <ons-input id="password_login" type="password" onchange = "password = this.value"></ons-input>
            </div> 
        </ons-list-item>
    </ons-list>

    <!--Buttons -->  
        <p style="text-align: center"> <ons-button modifier="material" id="login" onclick="login();">Login</ons-button> </p>

    </ons-page>
    </template>

    <template id="main.html">
    <ons-page id="main">
    <!-- Page name -->
        <ons-toolbar>
          <div class="center">Main page</div>
        </ons-toolbar>

    <!--List-->
        <ons-list id="list"></ons-list>

    <!--Buttons -->  
        <p style="text-align: center"> <ons-button modifier="material" id="logout" onclick="logout();">Log out</ons-button> </p>

    </ons-page>
    </template>
    </body>
</html>

Solution

  • I played with the code a bit and did 2 minor changes.

    The thing was addDataListener() did not run after myNavigator.pushPage

    Additionally myNavigator.replacePage literally added pages/section to the DOM instead of replacing them. That caused #list element to render on the old page instead of the new one ( id should be unique ) so I replaced that with myNavigator.replacePage

    Seems to work now

    goToPage('main.html')
              .then(_ => {
                firebase.database().ref('/users/' + auth.currentUser.uid).once('value').then(function(snapshot) {
                  family = snapshot.val().family;
                  addDataListener();
                });
              })
    
     function goToPage(newPage) {
          currentPage = newPage;
    
          var myNavigator = document.getElementById('myNavigator');
          return myNavigator.replacePage(newPage);
        }
    

    var currentPage = "register.html";
    let myListener;
    var email, family, password;
    
    const mockFirebase = {
      initializeApp: () => {},
      auth() {
        return {
          currentUser: {
            uid: 1
          },
          signInWithEmailAndPassword: () => Promise.resolve({}),
          signOut: () => Promise.resolve()
        }
      },
      database() {
        return {
          ref(path) {
            let value = {
              family: 'One'
            }
            if (path.includes("families")) {
              value = ['One', 'Two', 'Three']
            }
    
            return {
              once: () => Promise.resolve({
                val: () => value
              }),
              on: (prop, callback) => callback({
                val: () => value
              })
            }
          }
        }
      },
    }
    
    window.firebaseConfig = {}
    window.firebase = mockFirebase;
    
    firebase.initializeApp(firebaseConfig);
    var auth = firebase.auth();
    var db = firebase.database();
    
    function login() {
      firebase.auth().signInWithEmailAndPassword(email, password).then(function(user) {
    
        goToPage('main.html')
          .then(_ => {
            firebase.database().ref('/users/' + auth.currentUser.uid).once('value').then(function(snapshot) {
              family = snapshot.val().family;
              addDataListener();
            });
          })
    
      }).catch(function(error) {
    
        var errorCode = error.code;
        console.log(errorCode);
    
        if (errorCode) {
          ons.notification.alert('Error!');
        }
      });
    }
    
    function logout() {
      goToPage('login.html');
    
      firebase.auth().signOut().then(function() {
        console.log("I just log out");
      }, function(error) {
        console.log("Some error: ", error);
      });
    }
    
    function addDataListener() {
      console.log("Listener is set up!");
    
      myListener = firebase.database().ref('families/' + family).on('value', function(snapshot) {
        if (currentPage !== "main.html") return;
        console.log(snapshot.val());
    
        var list = document.getElementById('list');
    
        while (list.firstChild) {
          list.removeChild(list.firstChild);
        }
        Object.keys(snapshot.val()).forEach(function(k) {
          console.log(k + ' - ' + snapshot.val()[k]);
    
          var onsItem = document.createElement('ons-list-item');
          onsItem.innerHTML = snapshot.val()[k];
          onsItem.setAttribute('id', k);
          list.appendChild(onsItem);
        });
    
      });
    }
    
    function goToPage(newPage) {
      currentPage = newPage;
    
      var myNavigator = document.getElementById('myNavigator');
      return myNavigator.replacePage(newPage);
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <script src="https://www.gstatic.com/firebasejs/7.14.2/firebase-app.js"></script>
      <script src="https://www.gstatic.com/firebasejs/7.14.2/firebase-auth.js"></script>
      <script src="https://www.gstatic.com/firebasejs/7.14.3/firebase-database.js"></script>
      <meta charset="UTF-8">
      <link rel="stylesheet" href="https://unpkg.com/onsenui/css/onsenui.css">
      <link rel="stylesheet" href="https://unpkg.com/onsenui/css/onsen-css-components.min.css">
      <script src="https://unpkg.com/onsenui/js/onsenui.min.js"></script>
      <script src="https://unpkg.com/jquery/dist/jquery.min.js"></script>
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    
    <body>
      <ons-navigator swipeable id="myNavigator" page="login.html"></ons-navigator>
    
    
      <template id="login.html">
        <ons-page id="login">
        <!--Page name-->
            <ons-toolbar>
              <div class="center">Login page</div>
            </ons-toolbar>
    
        <!--Inputs-->    
        <ons-list>       
            <ons-list-item tappable>
                <div class="center">
                Email: 
                    <ons-input id="email_login" type="email" onchange = "email = this.value"></ons-input>
                </div> 
            </ons-list-item>   
    
            <ons-list-item tappable>
                <div class="center">
                Password: 
                    <ons-input id="password_login" type="password" onchange = "password = this.value"></ons-input>
                </div> 
            </ons-list-item>
        </ons-list>
            <p style="text-align: center"> <ons-button modifier="material" id="login" onclick="login();">Login</ons-button> </p>
        </ons-page>
        </template>
      <template id="main.html">
        <ons-page id="main">
            <ons-toolbar>
              <div class="center">Main page</div>
            </ons-toolbar>
            <ons-list id="list"></ons-list>
            <p style="text-align: center"> <ons-button modifier="material" id="logout" onclick="logout();">Log out</ons-button> </p>
    
        </ons-page>
        </template>
    </body>
    
    </html>