0

I have a data model class, let say:

class Question {
    body: string;
    
    get bodyForTableRow(): string {
        return this.body.replace("\n", " // ");
    }
}

And in the component html template I use the following declaration to evaluate the getter value:

 {{ oneQuestion.bodyForTableRow }}

But instead of value, where new lines are replace with // symbols I get an empty string.

When I use

 {{ oneQuestion.body }}

it displays the body contents.

Why does it happen? Should I always use a real fields to map them to the html-components and getters are not suitable for this case?


UPDATE

When the declaration in the template looks like that

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  <!-- other columns skipped --> 

  <ng-container matColumnDef="body">
    <th mat-header-cell *matHeaderCellDef>Question Body</th>
    <td mat-cell *matCellDef="let oneQuestion">
      {{ oneQuestion.body }}
    </td>
  </ng-container>
</table>

It displays the body content in the every table row. But when I use this code:

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  <!-- other columns skipped --> 

  <ng-container matColumnDef="body">
    <th mat-header-cell *matHeaderCellDef>Question Body</th>
    <td mat-cell *matCellDef="let oneQuestion">
      {{ oneQuestion.bodyForTableRow }}
    </td>
  </ng-container>
</table>

It shows empty rows.


UPDATE 2

Question data model class declared like that:

export class QuestionDataModel {
  body: string; // public access field for template
  
  constructor(bodyValue: string) {
    this.body = bodyValue;
  }  
  
}

Data source is declared like that:

  dataSource: QuestionDataModel[];

I populate the datasource via rest-call

const url: string = `/questions/all`;
this.http.get(url).subscribe(
  (data: QuestionDataModel[]) => {
    this.dataSource = data;
  },
  (error) => this.reportServerError(error)
);
8
  • Are you actually creating instances of Question classes? Just using type assertion will not create an instance of Question, and you won't have access to getters/setters/other methods.
    – cjd82187
    Commented Jul 23, 2020 at 20:03
  • @cjd82187 I've posted update to my question. Does it clarify it ?
    – Rafael
    Commented Jul 23, 2020 at 20:08
  • @Rafael no the update does not clarify, we'd need to see how you're fetching and creating the dataSource in this case. Seems like something suspect is happening there.
    – bryan60
    Commented Jul 23, 2020 at 20:11
  • @bryan60 I will update my question soon. Thanks.
    – Rafael
    Commented Jul 23, 2020 at 20:13
  • @bryan60 I've updated my question again.
    – Rafael
    Commented Jul 23, 2020 at 20:17

1 Answer 1

2

what you're doing should work, you've got some other issue going on like not instantiating your class correctly maybe, but you probably really want to restructure to use a setter instead...

class Question {
    private _body: string;

    set body(body: string) {
      this.bodyForTableRow = body.replace("\n", " // ");
      this._body = body;
    }
    get body() {
      return this._body;
    }
    
    bodyForTableRow: string;
}

the way angular change detection works, it evaluates functions on every change detection cycle which can be pretty frequent, so by putting that replace in a getter, you're running it on every single cycle. With this structure, you're just running and setting it when you need to.

To use this or any class, you need to use the new keyword,

this.oneQuestion = new Question();
this.oneQuestion.body = 'my string with line returns \n next line';
6
  • the point of my question is, should I have a "real" field to store a value, like you declared bodyForTableRow: string, or having a getter could be sufficient. As far as I understand having only getter, that calculates its value using body field does not work. I should save processed data to another real field and use it. Am I right?
    – Rafael
    Commented Jul 23, 2020 at 20:11
  • both ways should work, but using a "real" field is far more efficient and performs much better. You have another issue unrelated to your getter causing the problem.
    – bryan60
    Commented Jul 23, 2020 at 20:12
  • thank you, I understand, that pre-calculated field should perform better. I am just wondering why this getter does not work in my case. What is wrong with my approach. I have some experience with Java/C# and as far as I understand, if I have a class instance, I can use a getter to get a calculated value, based on this class instance. Why not in this case?
    – Rafael
    Commented Jul 23, 2020 at 20:20
  • the problem is that you're not creating class instances anywhere with the new keyword. you're just declaring types, it doesn't work that way, you need to actually create classes. TS is taking you're word for it that you're not lying to it, but you are.
    – bryan60
    Commented Jul 23, 2020 at 20:21
  • 1
    because getters are a class feature that requires you to instantiate a class. you DO NOT have an array of class instances. you have an array of objects with none of the associated class features you expect, and that you are lying to typescript about the type of,
    – bryan60
    Commented Jul 23, 2020 at 20:24

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.