Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a collapsible list with NativeScript

I am trying to create a FAQs type of screen in my app however am not finding a way to show questions and collapse the answers when someone tap in the item. I already tried using RadDataForm Groups and was able to do the collapsing but I was not able to resize the screen and elements so now am trying with Accordion. Still I am not able to collapse or even show the questions. I saw someone here saying they were able to make the list work without Accordion just by using collapse and visible attributes but they did not share how they did it. When I click in the names on the list nothing happens. I would like to find a simple and effective solution for this problem. My code:

    <Accordion [items]="myQuestions" itemTapped="tapped" headerTextBold="true" headerTextColor="white" headerColor="pink" headerTextColor="blue"
  allowMultiple="true">

  <ng-template accordionHeaderTemplate let-item="item" let-i="index">
      <GridLayout backgroundColor="blue" columns="auto,*">
          <Label [text]="item.question"></Label>
      </GridLayout>
  </ng-template>

  <ng-template accordionItemTemplate let-item="item" let-parent="parentIndex" let-even="even" let-child="childIndex">
      <StackLayout>
          <Label [text]="item.description"></Label>
      </StackLayout>
  </ng-template>

  <!-- IOS Only
  <ng-template accordionFooterTemplate let-item="item" let-i="index">
      <GridLayout backgroundColor="yellow" columns="auto,*">
          <Label [text]="hi"></Label>
          <Label col="1" text="-"></Label>
      </GridLayout>
  </ng-template> -->
</Accordion>

Component:

import { Component, OnInit, ViewChild} from "@angular/core";
import { Router } from "@angular/router";
import { Question } from "../../shared/question/question";
import { Observable } from "tns-core-modules/data/observable";
import { ObservableArray } from "tns-core-modules/data/observable-array";
// import { RadDataFormComponent } from "nativescript-ui-dataform/angular";

@Component({
  selector: "question",
  moduleId: module.id,
  templateUrl: "./question.html",
  styleUrls: ["./question-common.css", "./question.css"]
})
export class QuestionComponent extends Observable{ 
  public myQuestions: ObservableArray<any>;
  // @ViewChild('myRuntimeDataFormComp') myRuntimeDataFormComp: RadDataFormComponent;
  constructor(){
    super();
    this.myQuestions =new ObservableArray([
      new Question("Topic 1", "lorem ipsum lorem ipsum lorem ipsum"),
      new Question("Topic 2", "lorem ipsum lorem ipsum lorem ipsum"),
      new Question("Topic 3", "lorem ipsum lorem ipsum lorem ipsum"),
      new Question("Topic 4", "lorem ipsum lorem ipsum lorem ipsum"),
      new Question("Topic 5", "lorem ipsum lorem ipsum lorem ipsum"),
      new Question("Topic 6", "lorem ipsum lorem ipsum lorem ipsum")
      ]);   
  }

}

My screen:

enter image description here

like image 483
lumayara Avatar asked Mar 19 '18 18:03

lumayara


1 Answers

I was finally able to figure it out, but I had help from @manojdcoder's code in the nativescript forum. I used ListView and Observable arrays. This is my solution:

  import { Component, OnInit, ViewChild} from "@angular/core";
  import { Router } from "@angular/router";
  import { Question } from "../../shared/question/question";
  import { Observable } from "tns-core-modules/data/observable";
  import { ObservableArray } from "tns-core-modules/data/observable-array";
  import { RadListView, ListViewEventData } from "nativescript-ui-listview";
  // import { RadDataFormComponent } from "nativescript-ui-dataform/angular";

  import { isIOS, isAndroid } from "platform";
  import * as utils from "utils/utils";
  declare var UIView, NSMutableArray, NSIndexPath;


  @Component({
    selector: "question",
    moduleId: module.id,
    templateUrl: "./question.html",
    styleUrls: ["./question-common.css", "./question.css"]
  })
  export class QuestionComponent implements OnInit{ 
    public myQuestions: ObservableArray<any>;
    public isItemVisible: boolean;
    constructor(){
    }

    ngOnInit() {
      this.myQuestions =new ObservableArray([
        new Question("Topic 1", "lorem ipsum lorem ipsum lorem ipsum",false),
        new Question("Topic 2", "lorem ipsum lorem ipsum lorem ipsum",false),
        new Question("Topic 3", "lorem ipsum lorem ipsum lorem ipsum",false),
        new Question("Topic 4", "lorem ipsum lorem ipsum lorem ipsum",false),
        new Question("Topic 5", "lorem ipsum lorem ipsum lorem ipsum",false),
        new Question("Topic 6", "lorem ipsum lorem ipsum lorem ipsum",false)
        ]);  
    } 

    templateSelector(item: any, index: number, items: any): string {
      return item.expanded ? "expanded" : "default";
    }

    onItemTap(event: ListViewEventData) {
      const listView = event.object,
          rowIndex = event.index,
          dataItem = event.view.bindingContext;

      dataItem.expanded = !dataItem.expanded;
      if (isIOS) {
              var indexPaths = NSMutableArray.new();
              indexPaths.addObject(NSIndexPath.indexPathForRowInSection(rowIndex, event.groupIndex));
              listView.ios.reloadItemsAtIndexPaths(indexPaths);
      }
      if (isAndroid) {
          listView.androidListView.getAdapter().notifyItemChanged(rowIndex);
      }
    }

  }

And here is the view, using a RadListView:

<RadListView [items]="myQuestions" [itemTemplateSelector]="templateSelector" class="list-group" (itemTap)="onItemTap($event)">
    <ng-template tkListItemTemplate let-item="item">
        <GridLayout rows="auto,auto" columns="6*,*" class="add-dropdown">
            <Label [text]="item.question" class="list-group-item" col="0"></Label>
            <Image src="res://arrow" col="1"></Image>
        </GridLayout>

    </ng-template>
    <ng-template tkTemplateKey="expanded" let-item="item">
        <GridLayout rows="auto,auto" columns="6*,*" class="list-group-item add-dropdown">
            <Label row="0" col="0" [text]="item.question" class="font-weight-bold"></Label>
            <Image row="0" col="1" src="res://arrow_horizontal"></Image>
            <Label row="1" col="0" [text]="item.description" class="show-answer"></Label>
        </GridLayout>

    </ng-template>
</RadListView>

And here is my screen: enter image description here

like image 50
lumayara Avatar answered Nov 20 '22 10:11

lumayara