0

I' developing some simple Quitz Application with Angular 5.1.0 and having issues to understand class methods calling when instance was passed as an argument through binding in component template. Let me be more specific. I have Question typescript class.

export class Question {
    constructor(
        public Id: number,
        public Title: string,
        public Text: string,
        public OriginalUrl: string,
        public Answers: Answer[]
    ){}

    public isAnsweredCorrectly():boolean {  

        for(let answer of this.Answers){
            if(
                (!answer.IsCorrect && answer.IsSelected) || 
                (answer.IsCorrect && !answer.IsSelected)) {

                return false;
            }
        }

        return true;
    }
}

It has isAnsweredCorrectly() method that calculates if the question was answered correctly. Then I have a question-list angular component that will highlight question item accordingly in a list. The component template looks like:

<ul class="list-group h-100"> 

    <a class="list-group-item list-group-item-action" 
       *ngFor="let q of questions; let i = index;"
       [ngClass]="getClasses(q)"
       (click)="selectQuestion(q)">
       Question {{i+1}}
    </a>

</ul>

and the typescript code behind file is:

export class QuestionListComponent implements OnInit {

  @Input() questions:Question[];
  @Input() currentQuestion:Question;

  ...

  getClasses(question:Question):any{    
    return {
      'list-group-item-primary': question == this.currentQuestion,
      'list-group-item-success': question.isAnsweredCorrectly(),
      'list-group-item-danger': !question.isAnsweredCorrectly()
    };
  }
}

The issue is with this [ngClass]="getClasses(q)" binding. When I'm not using any new keywords to create the instance of a Question and just pass it through binding I get question.isAnsweredCorrectly is not a function error. Why though? How do I call isAnsweredCorrectly() of a Question in getClasses component method?

QuestionListComponent.html:3 ERROR TypeError: question.isAnsweredCorrectly is not a function
    at QuestionListComponent.getClasses (question-list.component.ts:33)
    at Object.eval [as updateDirectives] (QuestionListComponent.html:5)

// Updates:

@Input() questions:Question[]; array is populated using HttpClient of HttpClientModule. I get the Exam instance with a collection of questions through my ExamService that looks like this:

getExam(id:string):Observable<Exam>{
    const url = this.apiUrl + 'api/exams/' + id;

    return this.http.get<Exam>(url);
}

The Exam class looks like:

export class Exam {
    constructor(
        public Id: number, 
        public Title: string, 
        public Questions:Question[]){
    }
}
Dmytro
  • 16,668
  • 27
  • 80
  • 130
  • 1
    Perhaps you need to show how the questions array *is* populated. If you never use `new` then it is likely you never actually get objects with the correct prototype (and thus never get the function you want) – BradleyDotNET Feb 19 '18 at 16:16
  • This may sound stupid but do you have another Question class somewhere in the project. Maybe you are using the wrong class. – Developer Thing Feb 19 '18 at 16:30
  • @BradleyDotNET, I've updated the question. – Dmytro Feb 19 '18 at 16:34
  • @SemirDeljić, I've double checked, there's no other Question class. – Dmytro Feb 19 '18 at 16:35
  • Did you try it without all those public parameters in the constructor? The serializer almost certainly needs a default one, or at least one with all optional parameters. – BradleyDotNET Feb 19 '18 at 16:37
  • 2
    You will have to map parsed json response to new instances. Please take a look at the paulpdaniels answer: https://stackoverflow.com/questions/37310511/how-to-map-a-response-from-http-get-to-a-new-instance-of-a-typed-object-in-angul – Developer Thing Feb 19 '18 at 16:51

0 Answers0