在Angular 2中创建用户时更新用户列表

时间:2017-01-20 18:18:39

标签: angular angular2-services

我正在编写一个示例应用程序,我有一个用户列表组件:

@Component({
  selector: 'user-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.css'],
})
export class ListComponent implements OnInit {
  users: Array<User> = [];
  private usersService: UsersService;

  constructor(private service: UsersService) {
    this.usersService = service;
  }

  loadUsers() {
    this.usersService.getUsers().subscribe(users => this.users = users);
  }

  ngOnInit() {
    this.loadUsers();
    this.usersService.userEvent.subscribe(user => this.loadUsers());
  }
}

服务是:

@Injectable()
export class UsersService {
  userEvent: EventEmitter<User> = new EventEmitter();


  constructor(private http: Http) {
  }
  getUsers(): Observable<User[]> {
    return this.http.get('/rest/users')
      .map(res => res.json());
  }

  create(user: User) {
    this.http.post("/rest/users", user).subscribe(resp => this.userEvent.emit(user));
  }
}

export class User {
  constructor(public username: string,
    public email: string, public password: string
  ) { }
}

还有一个用于创建用户的兄弟组件:

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.css']
})
export class FormComponent implements OnInit {
  private usersService: UsersService;
  constructor(private service: UsersService, private router: Router) {
    this.usersService = service;
  }

  ngOnInit() {
  }

  onSubmit(formValue: any) {
    let user = new User(formValue.username, formValue.email, formValue.password);
    this.usersService.create(user);
    this.router.navigate(['users']);
  }

}

这目前正在做我想做的事情,但我想知道在兄弟组件在服务器上创建新用户的情况下是否有更优雅的方式来更新用户列表。如果我订阅用户列表,则必须使用事件发射器发出信号似乎很奇怪,尽管我也不知道如何通知http.get有关在服务器上创建新用户的信息。

2 个答案:

答案 0 :(得分:1)

您可以使用BehaviorSubject通知订阅它的任何组件。它是一种特殊类型的可观察物。例如,在您的用户服务中,定义用户(您可以轻松地将其更改为用户列表):

import {Observable, BehaviorSubject} from 'rxjs/Rx';  // 
import {User} from "../../models/user";               // Your model

... inside your class:

private _currentUser = new BehaviorSubject<User>(new User);
getUser = this._currentUser.asObservable();
setUser(user: User) { this._currentUser.next(user) }

在组件中,您可以订阅getUser这样的主题:

this.userService.getUser.subscribe(
user => {
    this.user = user;
});

这样,多个组件可以订阅此BehaviorSubject,并且使用setUser方法的任何组件/服务中的任何触发器都可以立即更改这些订阅组件。

... you successfully added a user in your
... component, now use the trigger:

this.userService.setUser(this.user);

答案 1 :(得分:1)

这正是我的库RxCache设计要管理的事情。它会为您处理所有可观察的订阅,这样您就不必管理任何订阅或担心订阅泄漏。

https://github.com/adriandavidbrand/ngx-rxcache

在您的组件中,您可以为用户显示可观察对象和加载标志。

@Component({
  selector: 'user-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.css'],
})
export class ListComponent implements OnInit {
  users$ = this.service.users$;
  loading$ = this.service.loading$;

  constructor(private service: UsersService) {
      service.load();
  }
}

在您的HTML中,使用异步管道来管理所有订阅

<div *ngIf="loading$ | async else elseBlock">loading ...</div>
<ng-template #elseBlock>
    <div *ngIf="users$ | async as users">
        <div *ngFor="let user of users">
            Email: {{user.email}}
        </div>
    </div>
</ng-template>

在您的服务中,通过安装“ npm install ngx-rxcache --save”来使用RxCache,并从“ ngx-rxcache”导入{RxCacheService};

@Injectable()
export class UsersService {
  constructor(private http: Http, private cache: RxCacheService) { }

  private userCache = this.cache.get<User[]>({
      id: '[User] users',
      construct: () => this.http.get<User[]>('/rest/users'),
      save: user => this.http.post<User[]>("/rest/users", user)
  });

  users$ = this.userCache.value$;
  loading$ = this.userCache.loading$;
  saving$ = this.userCache.saving$;

  create(user: User, saved?: (response: any, value: any) => void) {
      this.userCache.save(user, saved);
  }

  load() {
      this.userCache.load();
  }
}

// Use interfaces over classes
export interface User {
  username: string;
  email: string;
  password: string;
}

在同级组件中

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.css']
})
export class FormComponent implements OnInit {
  constructor(private service: UsersService, private router: Router) { }

  saving$ = this.service.saving$;

  ngOnInit() {
  }

  onSubmit(formValue: any) {
    let user = { username: formValue.username, email: formValue.email, password: formValue.password };
    this.usersService.create(user, (response, value) => {
        // Don't navigate until the save has finished.
        this.router.navigate(['users']);
    });
  }

}

在您的html中,您可以像保存其他组件一样显示一条保存消息。

<div *ngIf="saving$ | async">saving ...</div>