Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setter/getter not called from model

I have a problem where the two way binding is not working correctly and I assume that the getter and setter methods are the problem.

As you can see in the example am using the data property member.selectedConfig twice. I aspect, that when the component is loaded the value of both of them should be "HelloWorld" but none of them is.

When I start changing the value of the textbox manually also the displayed text of the other binding will change but the set function is not called.

The value of member.name is always displayed correctly.

When the getter and setter functions from the class BasicSystemMember is removed. The binding also works perfectly. But I need to have a setter function.

<li *ngFor="let member of activeSystemMembersList">
  <div class="">{{member.name}}</div>
  <div class="">{{member.selectedConfig}}</div>
  <input type="text" class="text-input" [(ngModel)]="member.selectedConfig" />
</li>
export class BasicSystemMember implements SystemMember{
  name: string;
  private _selectedConfig: string;

  constructor(){
    this._selectedConfig = "HelloWorld"
  }

  set selectedConfig(newName) {
    this._selectedConfig = newName
  };

  get selectedConfig() {
    return this._selectedConfig
  };
 }
export class SystemMembersComponent implements OnInit {
  activeSystemMembersList: SystemMember[];

  ngOnInit(){
    this.activeSystemMemberService.getActiveSystemMembers().subscribe(
      activeSystemMembersList => this.activeSystemMembersList = activeSystemMembersList)    
  }
}
export class ActiveSystemMemberService {    
  list: SystemMember[];    

  constructor() {
    this.list = []
  }
  getActiveSystemMembers(): Observable<SystemMember[]> {
    return of(this.list)
  } 
}
like image 976
Niecore Avatar asked Mar 06 '23 20:03

Niecore


1 Answers

This issue is most often caused when creating the items, in your case, your members. If you are creating the items as part of an Http request, something like this:

getMembers(): Observable<BasicSystemMember[]> {
    return this.http.get<BasicSystemMember[]>(this.Url);

Then you are not actually creating BasicSystemMember objects in your array. Rather, the Http request is creating elements that "look" like BasicSystemMember objects but they will only have the properties as provided by the Http request (not methods or getter/setters).

For a single item, you could do something like this:

Object.assign(new BasicSystemMember(), member);

Something like this would work ... but could probably be much more efficiently coded (its late here LOL).

getMembers(): Observable<BasicSystemMember[]> {
    return this.http.get<BasicSystemMember[]>(this.Url).pipe(
        map(data => {
           const newList: BasicSystemMember[] = [];
           data.forEach(item => 
                newList.push(Object.assign(new BasicSystemMember(), item)));
           return newList;
        })
     );
}

NOTE: I did not test or syntax check this.

This code maps the result from the Http response. It creates an appropriately typed array. Then foreach's through each element of the array using Object.assign to create an instance of the appropriate class and copy the item's data into it. Then it pushes it onto the array.

like image 154
DeborahK Avatar answered Mar 16 '23 23:03

DeborahK