Mot Franc
Mot Franc

Reputation: 157

Angular - *ngFor: Passing i from index in ts file

I'm trying to pass the index from a ngFor to a my ts file without any success. I actually don't know how to do that. Can someone tell me how to pass the index value from the html to the ts file? I thought using a @Input would be te solution but nothing happen... Thanks.

My HTML:

<div *ngFor="let question of questions | async; index as i">{{question.libelle}}
     <div class="row text-left options">
        <div class="col-md-6" *ngFor="let reponse of reponses | async">
          <div class="option">
            <label class="" [attr.for]="reponse.id">
                <input type="checkbox" [(ngModel)]="reponse.Selected"/>
                {{reponse.libelle}}
            </label>
          </div>
        </div>
      </div>
      {{i}}
    </div>

My TS:

@Injectable()


@Component({
  selector: 'app-java',
  templateUrl: './java.component.html',
  styleUrls: ['./java.component.sass']
})
export class JavaComponent implements OnInit {
  @Input()  i : any;
  questions :any = [];
  reponses :any = [];
  constructor(private questionnaireService: QuestionnaireService) { }

  ngOnInit() {
    this.questions = this.questionnaireService.getQuestion();
    this.reponses = this.questionnaireService.getReponse(this.i);
  }  

}

Upvotes: 0

Views: 5703

Answers (3)

Feng Zhang
Feng Zhang

Reputation: 1948

normally <div *ngFor="... let ii==index"> will be enough to pass the ii, however, in my case there is a *ngIf in sub , so that messed up the count and made it undefined. I endup make the *ngIf on the top level above *ngFor.

Upvotes: 0

Sunil
Sunil

Reputation: 11243

You can achieve these with 3 steps

  1. Keep the currentIndex in ts file

  2. Set the currentIndex from the html

  3. Call getter method from the *ngFor

in ts

@Injectable()
@Component({
  selector: 'app-java',
  templateUrl: './java.component.html',
  styleUrls: ['./java.component.sass']
})
export class JavaComponent implements OnInit {
  @Input()  i : any;
  questions :any = [];
  reponses :any = [];
  constructor(private questionnaireService: QuestionnaireService) { }

  ngOnInit() {
    this.questions = this.questionnaireService.getQuestion();
  }  

   //Track the current Index
   public currentIndex;

   //Current Index Setter
   setCurrentIndex(index){
       this.currentIndex = index;
   }

  //Getter for response which will use currentIndex
  get responses(){
    return this.questionnaireService.getReponses(this.currentIndex)
  }

}

in html

   <div *ngFor="let question of questions | async; index as i">{{question.libelle}}
         <div class="row text-left options" #>

            {{setCurrentIndex(i)}} <-- Set the current Index -->

            <div class="col-md-6" *ngFor="let reponse of responses | async">
              <div class="option">
                <label class="" [attr.for]="reponse.id">
                    <input type="checkbox" [(ngModel)]="reponse.Selected"/>
                    {{reponse.libelle}}
                </label>
              </div>
            </div>
          </div>
          {{i}}
 </div>

Note : since you are using async pipe make sure all your results are Observable.

Upvotes: 0

bryan60
bryan60

Reputation: 29305

you seem to have a basic misunderstanding of the index variable context and how observables will work. What could help here and clear things up is dividing your component into two components, one for managing and displaying the overall list and one for managing and displaying the child lists

The parent (app-java):

HTML:

<div *ngFor="let question of questions | async; index as i">{{question.libelle}}
 <div class="row text-left options">
    <app-java-child [i]="i"></app-java-child>
  </div>
  {{i}}
</div>

TS:

@Component({
  selector: 'app-java',
  templateUrl: './java.component.html',
  styleUrls: ['./java.component.sass']
})
export class JavaComponent implements OnInit {
  questions :any = [];
  constructor(private questionnaireService: QuestionnaireService) { }

  ngOnInit() {
    this.questions = this.questionnaireService.getQuestion();
  }  

}

and the child:

HTML:

<div class="col-md-6" *ngFor="let reponse of reponses | async">
   <div class="option">
     <label class="" [attr.for]="reponse.id">
            <input type="checkbox" [(ngModel)]="reponse.Selected"/>
            {{reponse.libelle}}
     </label>
   </div>
</div>

TS:

@Component({
  selector: 'app-java-child',
  templateUrl: './java-child.component.html',
  styleUrls: ['./java-child.component.sass']
})
export class JavaChildComponent implements OnInit {
  @Input()  i : any;
  reponses :any = [];
  constructor(private questionnaireService: QuestionnaireService) { }

  ngOnInit() {
    this.reponses = this.questionnaireService.getReponse(this.i);
  }  

}

This way you take the index from the initial ngFor and feed it to the child as input so the children can be in charge of building their own response arrays.

Upvotes: 1

Related Questions