2

私はサンプルアプリケーションを書いており、私はユーザーリストコンポーネントを持っています:

@Component({
  selector: 'user-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.css'],
})
export class ListComponent implements OnInit {
  users: Array = [];
  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 = new EventEmitter();


  constructor(private http: Http) {
  }
  getUsers(): Observable {
    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がどのように通知されるかはわかりませんが、ユーザーリストに登録している場合は、イベントエミッタを使用して信号を送信するのは不思議です。


  • 簡単なヒント:'プライベート'コンストラクタでは、クラスのサービスパラメータをprivate変数にします。新しいパラメータに割り当てる必要はありません。 - Toshkata Tonev

2 답변


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

これは私のライブラリ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'からインポートしてRxCacheを使用してください。

@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>

関連する質問

最近の質問