2

I am trying to get the value of a string variable explanationText from my QuizService to display in my di-quiz component template using data-binding. console.log is showing undefined for explanationText and data-binding to the template isn't displaying anything for explanationText when an answer is selected. Please see: https://stackblitz.com/edit/angular-9-quiz-app

Any idea why this is not working? Please can you help. Thank you!

In my quiz.service.ts file, I have:

@Injectable({providedIn: 'root'}) {
  export class QuizService {
  explanationText: string;
  ...

  setExplanationAndCorrectAnswerMessages() {
    this.question = this.getQuestion;
    if (this.question) {
      if (this.correctAnswers.length === 1) {
        this.explanation = ' is correct because ' + this.question.explanation + '.';
      }
      if (this.correctAnswers.length > 1) {
        this.explanation = ' are correct because ' + this.question.explanation + '.';
      }
    }

    if (this.correctAnswers && this.correctAnswers.length === 1) {
      const correctAnswersText = this.correctAnswers[0];
      this.explanationText = 'Option ' + correctAnswersText + this.explanation;
      console.log(this.explanationText);
      this.correctAnswerMessage = 'The correct answer is Option ' + this.correctAnswers[0] + '.';
      console.log(this.correctAnswerMessage);
    }
    if (this.correctAnswers && this.correctAnswers.length > 1) {
      if (this.correctAnswers[0] && this.correctAnswers[1]) {
        const correctAnswersText = this.correctAnswers[0] + ' and ' + this.correctAnswers[1];
        this.explanationText = 'Options ' + correctAnswersText + this.explanation;
        console.log(this.explanationText);
        this.correctAnswerMessage = 'The correct answers are Options ' + correctAnswersText + '.';
        console.log(this.correctAnswerMessage);
      }
      ...
    }
  }

In my di-quiz.component.ts, I have a getter/setter and constructor as follows:

get explanation(): string { return this.quizService.explanationText; };
@Input() set explanation(value: string) { this.explanationText = value; };

constructor(private quizService: QuizService,
            private timerService: TimerService,
            private route: ActivatedRoute) {
  this.explanationText = this.explanation;
  console.log("ExpTxt: " + this.explanationText);
}

and in my di-quiz.component.html, I have

<section id="question" [class.answered]="answer">
  <span *ngIf="!answer">{{ question?.questionText }}</span>
  <span *ngIf="answer">{{ explanationText }}</span>
</section>
integral100x
  • 332
  • 6
  • 20
  • 47
  • 2
    first try to initialize the explanationText in your service – OAH Apr 05 '20 at 01:36
  • In the code above `explanationText` is uninitialized. How are you initializing it in `QuizService`? – alexortizl Apr 05 '20 at 01:44
  • I am setting the explanationText in the setExplanationAndCorrectAnswerMessages() function (see above). – integral100x Apr 05 '20 at 14:17
  • I have tried the following code but still not able to get it to work: @Input() set explanationTextVal(value) { this.explanationText = value; }; ngOnChanges(changes: SimpleChanges) { if (changes.explanationTextVal && changes.explanationTextVal.currentValue !== changes.explanationTextVal.firstChange) { this.explanationText = changes.explanationTextVal.currentValue; } } – integral100x Apr 07 '20 at 22:52
  • @multiv123 You have posted an enormous stackblitz that is extremely hard to follow. There is so much wrong with the design that a simple answer here is not going to solve your problem - you need to redesign the whole project. Did you base your project on this https://github.com/marvinrusinek/codelab-quiz? – Kurt Hamilton Apr 08 '20 at 15:46
  • Yes this is my project. – integral100x Apr 08 '20 at 15:49
  • @multiv123 Can you provide more focus to your question. Can you recreate the problem you're having with a very simple stackblitz that demonstrates the specific problem you're having? – Kurt Hamilton Apr 08 '20 at 15:55
  • @Input() set explanation(value: string) { this.explanationText = value; }; why this? – Gourav Garg Apr 08 '20 at 16:27
  • I simplified it somewhat, please see https://stackblitz.com/edit/angular-ms9xaw. Still working on it – integral100x Apr 08 '20 at 16:55

2 Answers2

2

Change above constructor like this,

constructor(
  private quizService: QuizService,
  private timerService: TimerService,
  private route: ActivatedRoute
  ) {
     this.explanation = 'Text you want';
     this.explanationText = this.explanation;
     console.log("ExpTxt: " + this.quizService.explanationText);
}
Sanka Sanjeewa
  • 1,993
  • 14
  • 16
2

I check your stackblitz code and found the issue. Its because you are registering your QuizService in DependencyInjectionQuizComponent and QuestionComponent, which creates multiple instace.

So when question component fires setExplanationAndCorrectAnswerMessages it update explanationText in different instance but your DIQuizComponent expect from different instance.

To fix this you have to remove QuizService from QuestionComponent providers.

I have forked and updated the code. Here is the link

Gourav Garg
  • 2,856
  • 11
  • 24