【问题标题】:How to select a component and deselect the others in an angular ng-For?如何在角度 ng-For 中选择一个组件并取消选择其他组件?
【发布时间】:2021-05-29 16:12:48
【问题描述】:

我正在使用 Angular 开发一个测验应用程序。我的考试进行中组件由一个问题组件和 4 个答案组件组成。用户一次只能选择一个答案。我试图实现的行为是当我选择一个答案时,我想为其背景着色并取消其他答案的背景颜色,因此取消选择它们。如何做到这一点?

答案组件

import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
import { Answer } from 'src/app/_models/answer';

@Component({
  selector: 'app-answer',
  templateUrl: './answer.component.html',
  styleUrls: ['./answer.component.css']
})
export class AnswerComponent implements OnInit {
  @Input() answer: Answer
  @Output() onAnswerChosen = new EventEmitter<Answer>();
  isAnswerChosen: boolean = false;

  constructor() { }

  ngOnInit(): void {
  }


  onClick() {
    this.chooseAnswer();
    this.changeAnswerColor();
  }

  public chooseAnswer(): void {
    this.onAnswerChosen.emit(this.answer);
  }

  changeAnswerColor() {
    this.isAnswerChosen = !this.isAnswerChosen;
  }
}
<div 
    (click)="onClick()" 
    class="container"
    [ngStyle] = "{
        'backgroundColor': isAnswerChosen ? 'red' : 'green'
    }"
>
    <h4 *ngIf="answer">{{answer.id}} - {{answer.text}}</h4>
</div>

进行中的考试组件

import { formatDate } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Answer } from 'src/app/_models/answer';
import { IndividualSession } from 'src/app/_models/individual-session';
import { Question } from 'src/app/_models/question';
import { User } from 'src/app/_models/user';
import { AccountService } from 'src/app/_services/account.service';
import { AnswersService } from 'src/app/_services/answers.service';
import { IndividualSessionService } from 'src/app/_services/individual-session.service';
import { NavbarService } from 'src/app/_services/navbar.service';
import { QuestionsService } from 'src/app/_services/questions.service';
import { UsersService } from 'src/app/_services/users.service';

@Component({
  selector: 'app-exam-in-progress',
  templateUrl: './exam-in-progress.component.html',
  styleUrls: ['./exam-in-progress.component.css']
})

export class ExamInProgressComponent implements OnInit {
  individualSession: IndividualSession;
  user: User;
  currentUser$: Observable<User>;
  questions: Question[];
  currentQuestion: Question;
  answers: Answer[];
  currentAnswers: Answer[];
  chosenAnswer: Answer;

  constructor(public navService: NavbarService, 
    public individualSessionService: IndividualSessionService,
    public userService: UsersService,
    public accountService: AccountService,
    private questionService: QuestionsService,
    private answerService: AnswersService) { }

  ngOnInit(): void {
    this.navService.hide();

    this.startNewSession();
  }

  private startNewSession() {
    this.getCurrentUserData();

    if (localStorage.getItem('currentIndividualSession') === null) {
      this.individualSession = <IndividualSession>{
        ability: 0.5,
        standardError: 1,
        startTime: formatDate(new Date(), 'yyyy-MM-dd hh:mm:ss', 'en-us'),
        examineeId: 1,
        sessionId: 1
      };

      localStorage.setItem('currentIndividualSession', JSON.stringify(this.individualSession));
    }

    let json = localStorage.getItem('currentIndividualSession');
    this.individualSession = JSON.parse(json);
    this.loadData();
  }

  //=========================================================== events

  onNextClick() {
    this.currentQuestion = this.questions[1];
    this.currentAnswers = this.answers.filter(answer => answer.questionId === 3);
    this.shuffle(this.currentAnswers);

    if(this.isChosenAnswerCorrect()) {
      console.log('correct');
    } else {
      console.log('incorrect');
    }
  }

  //===========================================================

  private getCurrentUserData() {
    this.currentUser$ = this.accountService.currentUser$;
    this.currentUser$.subscribe(currUser => {
      if(!!currUser) {
        this.loadUser(currUser.email);
      }
    })
  }



  loadUser(email: string) {
    this.userService.getUser(email).subscribe(user => {
      this.user = user;
    })
  }

  loadData() {
    this.questionService.getQuestionsFromQuestionnaire(1).subscribe(questions => {
      this.questions = questions;
      this.currentQuestion = questions[0];
      this.loadAnswers();
    });
  }

  loadAnswers() {
    this.answerService.getAnswers().subscribe(answers => {
      this.answers = answers;
      this.currentAnswers = this.answers.filter(answer => answer.questionId === this.currentQuestion.id);
      this.shuffle(this.currentAnswers);
    });
  }

  shuffle(array: Answer[]) {
    var currentIndex = array.length, temporaryValue: Answer, randomIndex: number;
  
    while (0 !== currentIndex) {
  
      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex -= 1;
  
      temporaryValue = array[currentIndex];
      array[currentIndex] = array[randomIndex];
      array[randomIndex] = temporaryValue;
    }
  
    return array;
  }

  getChosenAnswerData(answer: Answer) {
    this.chosenAnswer = answer;
  }

  isChosenAnswerCorrect() {
    return this.chosenAnswer.isCorrect;
  }


}
<p *ngIf="user && currentUser$ | async">{{user.firstName}} {{user.lastName}}</p>
<app-question [question]="currentQuestion"></app-question>
<div class="answers">
    <app-answer (onAnswerChosen)="getChosenAnswerData($event)" *ngFor="let answer of currentAnswers" [answer]="answer"></app-answer>
</div>
<app-timer></app-timer>
<button type="button" (click)="onNextClick()">next</button>

【问题讨论】:

  • 请提供最少的代码并尝试发布您迄今为止尝试过的内容,以便更好地理解您的问题..
  • 抱歉,刚刚做了

标签: angular frontend


【解决方案1】:

您需要在父组件类而不是子组件中添加样式。

尝试为Answer类添加id,您可以在它的帮助下进行比较,这将使生活更轻松。

<div class="answers">
    <app-answer [ngStyle] = "{'backgroundColor': isAnswerChosen.id == answer.id ? 'red' : 'green'
    }" (onAnswerChosen)="getChosenAnswerData($event)" *ngFor="let answer of currentAnswers" [answer]="answer"></app-answer>
</div>

别忘了在 Template 中实例化你的 isAnswerChosen 对象。

chosenAnswer: Answer = new Answer(); 

chosenAnswer = {} as Answer;  // or if it's interface

编码愉快.. :)

【讨论】:

  • 似乎没有改变颜色,我不明白为什么。另外,我认为您的意思是 selectedAnswer.id == answer.id。把ngStyle放在那里对吗?
  • 好的,只需将答案组件放入 div 并对其应用 ngStyle,现在它可以正常工作了。谢谢!
【解决方案2】:

创建一个类 -

 .red { background-color:red;}

为所有 4 个答案组件创建参考变量,并在点击函数中发送所有 4 个参考变量,第五个变量将是当前点击的元素-

<answer1 #ans1 (click)="changeBackgroundColor(ans1,ans2,ans3,ans4, ans1)"></answer1>
<answer2 #ans2 (click)="changeBackgroundColor(ans1,ans2,ans3,ans4, ans2)"></answer2>
<answer3 #ans3 (click)="changeBackgroundColor(ans1,ans2,ans3,ans4, ans3)"></answer3>
<answer4 #ans4 (click)="changeBackgroundColor(ans1,ans2,ans3,ans4, ans4)"></answer4>

在点击功能中,首先从所有 4 个答案组件中删除类红色,然后应用于所选的一个

changeBackgroundColor(ans1,ans2,ans3,ans4, clicked) {
  ans1.classList.remove('red');
  ans2.classList.remove('red');
  ans3.classList.remove('red');
  ans4.classList.remove('red');

  clicked.classList.add('red');
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    • 2015-12-02
    • 1970-01-01
    相关资源
    最近更新 更多