0

I have the following parent component:

export class CheckoutComponent implements OnInit {

    public customer: Customer;
    public items: Array<Item>;

    constructor(private sharingDataService: SharingDataService) { }

    ngOnInit(): void {
        this.sharingDataService.setCustomer(this.initializeCustomer());
        this.sharingDataService.setItems(this.initiatlizeItems());
        this.customer = this.sharingDataService.getCustomer();
        this.items = this.sharingDataService.getItems();
    }
    ......
}

with the following html:

<div>
    <app-shipping-option></app-shipping-option>
    <app-review></app-review>
</div>

the first child "app-shipping-option" :

export class ShippingOptionComponent implements OnInit {

    public options: Array<Option> = [];

    constructor(private sharingDataService: SharingDataService) { }

    ngOnInit(): void {
        this.initializeOptions();
    }

    private initializeOptions(): void {
        let option1: Option = {
            name: 'Free',
            price: 0
        };
        let option2: Option = {
            name: 'Paid',
            price: 15
        };
        this.options.push(option1, option2);
    }

    private createCustomerForm(): void {
        this.shippingOptionForm = this.formBuilder.group({
            option: [this.options[0], Validators.required]
        });
    }

    chooseOption(option): void {
        this.sharingDataService.setShippingOption(option);
    }
}

and here the second child "review" :

export class ReviewComponent implements OnInit {

    constructor(private sharingDataService: SharingDataService) { }

    ngOnInit(): void {
        console.log(this.sharingDataService.getShippingOption())
    }
}

I want to detect change in the second child so when i change an option on the first child, the second child should print this option on console. But with the code above it print the first provided option on init. those child of cours are shown on the same page and the ngOnInit are called on page load.

here's the service used to share data between components:

@Injectable()
export class SharingDataService {

    private data: InputDetails = new InputDetails();

    constructor() { }

    setShippingOption(shippingOption): void {
        this.data.shippingOption = shippingOption;
    }

    getShippingOption(): { name: string, price: number } {
        return this.data.shippingOption;
    }
}
1
  • getShippingOption() will only return the value when its called, so, to have data always updated using it, you would need to be calling each from times to times to update the data, which is not a good solution. A better approach, which I would recommend on this case is having data as a BehaviorSubject on your SharingDataService, pushing values to it whenever values changes (using next method) and subscribe for changes inside your components. Commented Mar 29, 2019 at 15:53

2 Answers 2

1
    You can use Subject type of an observable to achieve this. 

    Here is how to use it:

    In Service File: Create the Subject

    import { Subject } from 'rxjs/internal/Subject';

    export class SharingDataService {
      public abcObservable = new Subject<object>();
    }

    In Child1: import the Service within the constructor and use the .next() to emit values whenever you see a change in options on this child

import { SharingDataService } from ....;

export class ShippingOptionComponent implements OnInit {

    public options: Array<Option> = [];

    constructor(private sharingDataService: SharingDataService) { }

    chooseOption(option): void {
        this.sharingDataService.abcObservable.next(option);
    }

}

In Child2: Subscribe to this Subject

export class ReviewComponent implements OnInit {

    constructor(private sharingDataService: SharingDataService) { }

    ngOnInit(): void {

        this.sharinDataService.abcObservable.subscribe(

      (data) =>  console.log("Call your next methods from here!"),
      (error) => console.log("When there is an error in the observable, it comes here", error),
      () => console.log("If the subject completes sending all values, it comes in here")
    );
    }
}

More details aout how to share data between different components can be read here: https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/
Sign up to request clarification or add additional context in comments.

Comments

0

You can use Subject Class from rxjs, here is an example of how you can do some kind of notification

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.