简体   繁体   中英

Angular2 Observables best practice

lets say I have a component which has a child component. For example this simple calendar: 在此处输入图片说明

Here is its template:

<month-board [current-month]="currentMonth$"></month-board>
<button (click)="decrement()">Prev</button>
<button (click)="increment()">Next</button>

when the buttons are clicked the month-board which subscribed to currentMonth$ is subscribed is changing the displayed month.

currentMonth$ type is Observable<Moment> . My question is: is it a good practice to pass Observables to child components in Angular2? is there any better way to this?

Parent full code:

@Component({
  selector: 'month-view',
  templateUrl: 'app/components/month-view/month-view.html',
  styleUrls: ['app/components/month-view/month-view.css'],
  directives: [MonthBoard],
})

export class MonthView {
  currentMonth: Moment = moment();
  currentMonth$: Observable<Moment>;
  currentMonthObserver: Observer<Moment>;
  decrement: Function;
  increment: Function;

  constructor() {
    this.currentMonth$ = Observable.create((observer: Observer<Moment>) => {
      this.currentMonthObserver = observer;
    });


    const decrementCounter$: Observable<Function> = Observable.create((observer) => {
      this.decrement = () => {
        observer.next();
      };
    });

    const incrementCounter$: Observable<Function> = Observable.create((observer) => {
      this.increment = () => {
        observer.next();
      };
    });

    this.currentMonth$.subscribe();

    Observable
      .merge(
        decrementCounter$.map(() => - 1),
        incrementCounter$.map(() => + 1)
      )
      .startWith(0)
      .scan((currentCount: number, value: number) => currentCount + value)
      .subscribe((count: number) => {
        this.currentMonthObserver.next(this.currentMonth.clone().add(count, 'M'));
      });
  }
}

Child full code:

@Component({
  selector: 'month-board',
  templateUrl: 'app/components/month-board/month-board.html',
  styleUrls: ['app/components/month-board/month-board.css'],
  directives: [DayCell]
})
export class MonthBoard implements OnInit{
  @Input('current-month') currentMonth: Observable<Moment>;
  weeks: Moment[][];

  constructor(private calendarHelper: CalendarHelper) {
    this.weeks = this.calendarHelper.getMonthWeeks();
  }

  ngOnInit() {
    this.currentMonth.subscribe((month: Moment) => {
      this.weeks = this.calendarHelper.getMonthWeeks(month);
    });
  }
}

You can do it that way, the other way is with @input. It's very easy to pass values from parent to child with it.

https://angular.io/docs/ts/latest/api/core/Input-var.html

I don't think it's necessarily bad to pass observables that way to your child component. For example I have a service that uses an observable that my whole application uses to watch for logged in events. But for a Calendar you might find yourself wanting to pass different values in different places on the same observable. If you do that you can always make another observable. Or manipulate it in different ways for each component.

But for readability I would definitely just use @input, that way I only have to go to the parent component to figure out what I am passing around.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM