1

I want to create a radio button alert by using the data in fireStore. I generated an observable by valueChanges() but console.log returns Undefined when I used it in the function that can't read the data and eventually cannot insert the values for radio button. I am new to fireStore and ionic.

I have also tried using .get().then(function(doc) but returns error as not a function. I have also tried using subscribe() but also not able to give me the actual data, or I have missed something. I have google for many days but just can't find the solution. I hope somebody could help.

myMemberList = [];

constructor(public navCtrl: NavController, 
       public alertCtrl: AlertController,
       public firestore: AngularFirestore, 
       public afAuth: AngularFireAuth,
    ) { }

ionViewDidEnter() {
  this.afAuth.authState.subscribe(user => {
     if (user) {
      this.userId = user.uid;
      this.fireStoreTaskList = this.firestore.doc<any>('users/' + 
      this.userId).collection('Member').valueChanges();
     }
  });
}

// create the inputs for radio button //
createInputs() {
    const theNewInputs = [];
 for (let i = 0; i < this.fireStoreTaskList.length; i++) { // undefined
    theNewInputs.push(
      {
        type: 'radio',
        label: this.fireStoreTaskList.memberName,     // undefined
        value: this.fireStoreTaskList.memberId,       // undefined
        checked: false      
      }
    );

  } {
  console.log(theNewInputs);
  }
  return theNewBeneInputs;
}

// Radio button alert to choose data //
async selectMember() {
  this.myMemberList = this.createInputs();
  const alert = await this.alertCtrl.create({
    header: 'Member',
    inputs: this.myMemberList,

    buttons: [{ text: 'Cancel', role: 'cancel' },
              { text: 'OK',
                 handler: data => {
                 console.log(data)
                }
              }
              ]
  });
  await alert.present();
}
Kwong
  • 98
  • 1
  • 6

2 Answers2

1

I have been working with Ionic 4 for some time now and I have also integrated Firebase Firestore in my app. I didn't really understand the whole description, but I have a solution for you initial question "I want to create a radio button alert by using the data in Firestore"

I assume that you have already setup your application with your Firebase app, if not then I suggest following the How to Build An Ionic 4 App with Firebase and AngularFire 5.

My example has 1 button, that whenever you click it, it will do the following:

  1. Access the Firestore database.
  2. Download the Firestore documents.
  3. Get the field memberName of each document.
  4. Add those names in an array of names
  5. Create an Alert of Radio Buttons.
  6. For the radio buttons it will create a list of radio buttons that will have the names of the members.
  7. Display the array.

For my code to work, this is the Firestore database structure that I have followed:

.
└── collection: "users"
    └── document: "autogenerated_id"
    |   ├── memberID: "user_id"
    |   └── memberName: "Name 01"
    └── document: "autogenerated_id"
        ├── memberID: "user_id"
        └── memberName: "Name 02"

When clicking the button you will see an alert with radio buttons e.g. Name 01 and Name 02

As I have mentioned above, this is my example code. It loads data from Firestore and Creates an alert with radio buttons using that data, as you have described in your question. I have added a lot of comments for you in the code. If this is not exactly what you were looking for, take a look at the code and modify it according to your needs.

Andrei Cusnir
  • 2,735
  • 1
  • 14
  • 21
  • Excellent. It works!. This is exactly what I am looking for. The example code is very good and the footnote is very detailed. Thanks a million :) – Kwong Sep 27 '19 at 14:50
  • I am glad that this resolved your issue. Please mark the answer as solution to give the question more visibility, as it might also help other members of the community! – Andrei Cusnir Sep 27 '19 at 18:27
  • Hi Andrei, is there any way I can capture the values of both memberID and memberName (maybe some more values) at the same time, so that I can deploy later in the data handler? – Kwong Oct 01 '19 at 10:39
  • Hey there! You will have to use an [array element of interfaces](https://stackoverflow.com/questions/25469244/how-can-i-define-an-interface-for-an-array-of-objects-with-typescript). e.g. Add `interface Data { memberID?: string; memberName?: string; }` then add `data: Data[] = [];` within the main class and then you can `this.data.push( { memberID: doc.data().memberID, memberName: doc.data().memberName});` in the part where you are loading the data. Hope it helps! – Andrei Cusnir Oct 01 '19 at 13:13
  • @ Andrei Cusnir I am not familiar with the usage of interface. Based on your comments, I have made changes to your example code as below but can't get the values of memberID and memberName in the console.log. Did I put the codes in the wrong place? Can you help to correct it? Thanks. – Kwong Oct 01 '19 at 16:32
  • You did some minor mistakes in the code. I have fixed your [answer](https://stackoverflow.com/a/58188997/4037220), however as this might me a question for other members of the community, I believe that further interactions must be done in a new Stackoverflow question. – Andrei Cusnir Oct 02 '19 at 09:23
0

UPDATED CODE FOR LOADING memberID and memberName into the array of type interface.

    import { Component, OnInit } from '@angular/core';
    
    //Import AngularFirestore to access Firestore database
    import { AngularFirestore } from '@angular/fire/firestore';
    //Import AlertControll to display alerts
    import { AlertController } from '@ionic/angular';


    //You have to add the interface, before the calss' declaration
    interface Data { 
      memberID?: string; 
      memberName?: string; 
    }
    
    @Component({
      selector: 'app-home',
      templateUrl: 'home.page.html',
      styleUrls: ['home.page.scss'],
    })
    export class HomePage implements OnInit {
    
      //List that will be used to load the data from Firestore into it
      //members = []; //You don't this anymore
      //Just the array of type interface that you created.
      data: Data[] = [];
    
      //Constractor: add AngularFirestore and AlertController
      constructor(private db: AngularFirestore, public alertController: AlertController) { }
    
      ngOnInit() {
      }
    
      //Load data and create the alert

      showAlert(){
    
        //Clear the array before loading again
        this.members = [];
    
        //Access the Collection "users" in Firestore and load all the documents
        this.db.collection("users").ref
        .get()
        .then(async (querySnapshot) => {
    
          //Parse through all the loaded documents
          querySnapshot.forEach((doc) => {
            //Add the loaded name to the list
            //this.members.push(doc.data().memberName) // You don't need this anymore as you are going to push the loaded data in the new array
            //Pushing the data in the new array or logging it if you want
            this.data.push( { 
              memberID: doc.data().memberID,      //This is how you get the memberID from Firestore document
              memberName: doc.data().memberName}  //This is how you get the memberName from Firestore document
              );
          });
    
          //Create an array of Radio Buttons to be used in the alert
          var newInputs = [];
          
          //Parse through all memebers in the loaded array from Firestore
          for (const d of this.data){
            newInputs.push({
              name: 'radio1', //You can costumize those as well to cast the clicked once afterwards
              type: 'radio',
              label: "ID: " + d.memberID + " name: " + d.memberName, //Add the member and the ID as label
              value: 'value1',
              checked: false
            })
          }
      
          //Create an alert
          const alert = await this.alertController.create({
            header: 'Radio',
            inputs: newInputs, //Add the dynamically  generated array of radio buttons.
            buttons: [
              {
                text: 'Cancel',
                role: 'cancel',
                cssClass: 'secondary',
                handler: () => {
                  console.log('Confirm Cancel');
                }
              }, {
                text: 'Ok',
                handler: () => {
                  console.log('Confirm Ok');
                }
              }
            ]
          });
      
          //Present the alert
          await alert.present();
    
    
        })
        .catch(function(error) {
            console.log("Error getting documents: ", error);
        });
    
      }
Community
  • 1
  • 1
Kwong
  • 98
  • 1
  • 6