2017-01-19 6 views
3

У меня есть компонент на моей корневой странице, которая выставляет несколько связываемых свойств и может использоваться как это:Angular2/Ionic2 :: Reload компонент

<myprogress [value]="current" [max]="maximum"></myprogress> 

В моем приложении, различные типы объектов требуют отображения прогресса. Так что я создал некоторые директивы, как показано ниже:

@Directive({ 
    selector: 'myprogress[order]' 
}) 
export class OrderProgress { 
    @Input('order') order: Order; 
    constructor(private baseComponent: Progress) {} 
    ngOnInit() { 
    this.baseComponent.value = this.order.currentStage; 
    this.baseComponent.max = this.order.totalStages; 
    } 
} 

Это позволяет мне заменить вызовы, такие как:

<myprogress [value]="order.currentStage" [max]="order.totalStages"></myprogress> 

с более читаемым:

<myprogress [order]="order"></myprogress> 

Это прекрасно работает, пока какой-то части приложение меняет сам заказ. В этом случае myprogress компоненты, которые уже были обработаны, не обновляются. И я тоже понимаю, почему. Функция ngOnInit запускается только один раз, когда компонент визуализируется, и нет способа указать директиве, что какое-то свойство заказа изменилось, и должны быть рассчитаны новые значения для value и max.

Есть ли способ решить эту проблему?

Одно из возможных решений у меня есть это:

  1. Изменить Progress компонент принимать номера, а также функцию, которая возвращает число.
  2. В OrderProgress «s ngOnInit, связываются следующим образом: this.baseComponent.value =() => this.order.currentStage

Но это требует от меня, чтобы изменить Progress компонент, а также. Есть ли способ, который не требует от меня изменения Progress или Order?

+0

Я вижу ответы с '' Subject'', если я понимаю вас ясно. Вы хотите изменить порядок родительских компонентов, отраженный в дочерней директиве. Не изменит ли значение изменения изменения порядка в дочерней директиве, когда значение порядка изменено в родительском? – raj

+0

Прошу прощения, я не совсем понял, что вы просили. Не могли бы вы немного перефразировать свой вопрос? – AweSIM

ответ

1

Похоже, вам нужно реализовать наблюдаемый над объектом заказа. Если вы делитесь этим объектом с несколькими компонентами и нуждаетесь в том, чтобы эти компоненты были осведомлены об изменениях в объекте заказа, лучше всего создать Observable. Мы используем класс BehavoirSubject из rxjs, чтобы сделать именно это.

RxJs BehaviorSubject

Вот и пример того, как можно создать BehavoirSubject:

export class TokenService { 

    public tokenSubject: BehaviorSubject<OpenIdToken> = new BehaviorSubject<OpenIdToken>(<OpenIdToken>{}); 

OpenIdToken является пользовательский класс машинопись, что я хочу поделиться через мое приложение.

Вот как вам notifiy абонентов изменений в базовый объект:

setObservableToken(token: OpenIdToken): void { 
     if (token) { 
      this.tokenSubject.next(token); 
     } 
    } 

после .next называется новый маркер значение объекта будет propigate все абонентам. Вот как вы подписались на BehaviorSubject:

export class PatientComponent implements OnInit, OnDestroy {  

    patient: Patient; 

    constructor(private _tokenService: TokenService, private _patientService: PatientService) { } 

    ngOnInit() { 
     this._tokenService.tokenSubject.subscribe(token => { 
      if (token && token.access_token && token.access_token.length>0) { 
       this._patientService.getPatient(token) 
        .subscribe(_patient => this.patient = _patient); 
      } 
     }); 
    } 

подписываться является делегатом, который будет выполнять, когда подписка транслирует изменения в знак (при вызове .next (маркер)). В этом случае, когда я получаю OpenIdToken, я хочу получить пациента с помощью токена, поэтому я вызываю другую услугу.

+0

и @victor дали технически правильные решения. Я согласен, что это можно сделать лучше с наблюдаемыми. Ваш ответ, ИМХО, лучше, поскольку вы определяете наблюдаемое внутри самого класса модели. В другом ответе наблюдаемый определяется на уровне страницы. Это решение плохо масштабируется, когда другие страницы также меняют модель 'order'. Поэтому я буду отмечать ваш ответ как правильный. – AweSIM

1

Тип заказа должен быть объектом Subject или BehaviorSubject, поэтому при обновлении заказа должен также обновляться шаблон myprogress. Вам нужно будет использовать асинхронный канал для подписки на наблюдаемый.

<myprogress [order]="order$ | async"></myprogress> 

Проверьте этот код. Вам нужно будет позвонить this.newOrder({...});, чтобы обновить заказ.

@Component({ 
    selector: 'page-home', 
    template: ` 
    <ion-header> 
     <ion-navbar> 
     <ion-title>Home</ion-title> 
     </ion-navbar> 
    </ion-header> 

    <ion-content padding> 
     <myprogress [order]="order$ | async"></myprogress> 
    </ion-content> 
` 
}) 
export class HomePage implements OnInit,OnDestroy{ 

    order$: Subject<any> = new Subject(); 

    constructor(public navCtrl: NavController){ 
    } 

    ngOnInit(){ 
    } 

    newOrder(order : any){ 
    this.order$.next(order); 
    } 

    ngOnDestroy(){ 
    this.order$.unsubscribe(); 
    } 

}