How to access Observable in nativescript-drop-down UI?


#1

Previously, I was using ListView to show all the ‘names’ in a list and now I want to put all names into a DropdownList and that means my Observable is working fine and I am getting data to the UI.

I tried this code

<StackLayout>
    <GridLayout rows="auto, auto, *" columns="auto, *">
        <DropDown #dd backroundColor="red" [items]="names$ | async"
                  (selectedIndexChanged)="onchange($event)" (opened)="onopen()"
                  row="0" colSpan="2">
        </DropDown>
    </GridLayout>
</StackLayout>

It shows a dropdownlist of Objects in Observable. how can I read values from that Object ?

I tried different combinations using names$. but it didn’t worked.

  1. Is it even possible to get data out of Observable in Dropdownlist ?
  2. am I missing something with the tags or attributes here ?

#2

So you are trying to get the selected value of your dropdown list, if I am reading you correctly?

I did it with a ListPicker (not using an Observable in this case):

<ListPicker #picker [items]="instruments" [selectedIndex]="instrument" 
    		verticalAlignment="center" horizontalAlignment="center" 
    		(selectedIndexChange)="selectedIndexChanged(picker)"></ListPicker>

and in the component file:

public selectedIndexChanged(picker: any) {
    this.selectedInstrumentIndex = picker.selectedIndex;
  }

hope that helps. Here’s the full code: https://github.com/jlooper/practicebuddy/blob/master/app/student-admin/student-admin.component.ts


#3

Firstly, Thanks for you answer.
but I guess it might be a little bit confusing for you with the ‘names’ Observable to understand. Let me rephrase my question for your example.

Assume I have an Observable
public student: Observable<any>;

and the student Observable have sonething like [{student_name:'a', age:2},{student_name:'b', age:3}].
Now my problem is that, it shows [Object object],[Object object] in the dropdownlist . Instead I want to have just ‘student_name’ property in the dropdownlist.


<StackLayout>
    <GridLayout rows="auto, auto, *" columns="auto, *">
        <DropDown #dd backroundColor="red" [items]="students$ | async"
                  (selectedIndexChanged)="onchange($event)" (opened)="onopen()"
                  row="0" colSpan="2">
        </DropDown>
    </GridLayout>
</StackLayout>

I hope this might give you clear idea about my question


#4

Looks like you are using this plugin: https://www.npmjs.com/package/nativescript-drop-down. Maybe @peter.staev would be able to help. But I think the answer is changing your creation of [items] - you may need to loop through your students$ observable and extract the student name and push it to a new array, and then inject that into your dropdown.


#5

If you have complex objects then you need to put those in either a simple string array or use the ValueList sample code in the readme for the DropDown repository. So what Jen suggested is the way to go.


#6

As @jen.looper & @peter.staev suggested, I simplified the Observable into a separate array of firstName.

I did it with this.store.subscribe() but I am not sure if it’s a good practice.


<!--html file-->
<StackLayout>
    <GridLayout rows="auto, auto, *" columns="auto, *">
        <DropDown #dd backroundColor="red" [items]="firstName"
                  (selectedIndexChanged)="onchange($event)" (opened)="onopen()"
                  row="0" colSpan="2" hint="Select ">
        </DropDown>
    </GridLayout>
</StackLayout>
/* Component file*/
public names$: Observable<any>;
public firstName: Array<string>;

ngOnInit() {
    this.names$ = this.store.let(getNames); 
      this.store.subscribe(data => {
        this.firstName = [];
        for (let i in data.sample.names)
          {
            console.log(data.sample.names[i].first_name);
            this.firstName.push(data.sample.names[i].first_name);
          }
        });
    }

#7

This is one way to do it. Or you can use the map operator of the observable so your component file will look something like:

/* Component file*/
public names$: Observable<any>;
public firstNames$: Observable<string[]>;

ngOnInit() {
    this.names$ = this.store.let(getNames); 
    this.firstNames$ = this.names$.map(data => {
        const result: string[] = []
        for (const item of data.sample.names) {
            result.push(item.first_name);
        }
        return result;
    });
}

And then in your html to bind it like firstNames$ | async.


#8

Yes, this is also possible.
but, I was just wondering how can I get the selected value from the index?

    public onchange(args: SelectedIndexChangedEventData) {
          console.log(`Drop Down selected index changed from ${args.oldIndex} to ${args.newIndex}`);
          var firstNameIndex = `${args.newIndex}`;
          console.log('index : '+firstNameIndex);

          var firstNameArray = this.names$.map(firstNameData => {
              const result: string[] = []
              //console.log(JSON.stringify(firstNameData));
              for (const item of firstNameData) {
                  result.push(item.first_name);
              }
              return result;
          });
          console.log('selected firstname : '+firstNameArray[firstNameIndex]);
          //this.print(this.firstNames$[firstNameIndex]);


      }