happyZZR1400
happyZZR1400

Reputation: 2405

mapping in typescript and angular1

I'm programming with angular 1.6 and typescript. In my project i need to load list of users from the server and display the list with checkboxes near each person:

 <div class="container">
  <h2>Hello {{ $ctrl.name }}</h2>
  <ul ng-repeat="user in $ctrl.users"  class="list-group">
    <li class="list-group-item">
      <input type="checkbox" ng-model="user.selected">
      {{user.name}}
    </li>
  </ul>
  <button class="btn btn-primary" ng-click="$ctrl.showSelected()">save</button>
</div>

After user selects some persons and clicks the button below he should get alert with list of selected persons.

Here is Person object that comes from server

export class Person {
    public name:string; 
}

And my Service looks this way:

getUsers() : ng.IHttpPromise<Person[]> {
 return this.$http.get('users.json').then((res:ng.IHttpPromiseCallbackArg<Person[]>)=>{
  return res.data
 })
}

Since in my ui the person elements must have "selected" property - i thinking about create uiPerson class which will derive from Person:

import { UsersService } from './service'
import { Person } from './Person'
  class uiPerson extends Person{
  public selected:false;
}
export const AppComponent = {
  template: `
  <div class="container">
  <h2>Hello {{ $ctrl.name }}</h2>
  <ul ng-repeat="user in $ctrl.users"  class="list-group">
    <li class="list-group-item">
      <input type="checkbox" ng-model="user.selected">
      {{user.name}}
    </li>
  </ul>
  <button class="btn btn-primary" ng-    click="$ctrl.showSelected()">save</button>
</div>
`,
 controller: class AppComponent {
 static $inject =["usersService"]
 constructor(private usersService: UsersService) {  }

 $onInit() {
   this.name ='Users';
   this.usersService.getUsers().then(users=>{
     this.users= users as uiPerson[];//<-- HERE IS QUESTION
   }) 
  }
   showSelected() {
     alert(this.users.filter(u=>u.selected).map(u=>u.name).join(','))
   }
}
 };

I'm new with typescript - am i right about mapping with "this.users= users as uiPerson[]" syntax? Is there some more correct way to do it?

here is the plnkr

Thanks

Upvotes: 0

Views: 79

Answers (2)

MS_AU
MS_AU

Reputation: 412

My advice here would be to avoid introducing the uiPerson class - it is adding complexity and polluting your domain model. Is 'selected' truly an attribute of a Person?

What would happen if you were required to present the same Person is two lists?

public selectedList1: boolean;
public selectedList2: boolean;

Instead - I would look to store the 'selected' state in your Controller, exposing a simple 'isSelected' function:

controller: class AppComponent {
    static $inject =["usersService"]
    constructor(private usersService: UsersService) {  }

public selectedUsers: Person[] = [];

$onInit() {
    this.name ='Users';
    this.usersService.getUsers().then(users=>{
        this.users= users; <-- No uiPerson
    }) 
}

showSelected() {
    alert(this.selectedUsers.map(u=>u.name).join(','))
}

isSelected(person: Person): boolean {
    return selectedUsers.indexOf(person) !== -1;
}

Template:

<input type="checkbox" ng-checked="$ctrl.isSelected(user)">

Plnkr

Upvotes: 1

Eric Simonton
Eric Simonton

Reputation: 6029

This looks reasonable to me. I would personally make a couple adjustments:

  • Make Person and UiPerson interfaces instead of classes, unless you plan to use them in different ways in the future (such as constructing them with new)
  • Consider whether it makes sense for selected to be optional, since at first your array of UiPerson objects will not have it defined. That may also allow you to skip the type cast.

Here is a revised plunkr with those changes, and I also took the liberty to make it closer to my personal style, in case you like what you see.

Upvotes: 2

Related Questions