2

I'm building an Angular 4 application and I have 2 separate pages, a Detail page and an Edit page, each with their own component.

When the user edits the model on the Edit page, I redirect them back to the Details page like this:

// This is within my RetailerEditComponent
save(): void {
    this.retailerService.updateRetailer(this.retailer)
        .then(() => this.router.navigate(['/admin/retailer']));
}

In the admin/retailer page, I have a RetailerDetailComponent that looks like this:

export class RetailerDetailComponent {
    retailer: Retailer;

    public hasBeenUpdated: boolean = false;

    constructor(
        private retailerService: RetailerService,
    ) {
        console.log("in RetailerDetailComponent");
    } 
}

How can I set the bool hasBeenUpdated to true from my other page?

Update:

I like the idea of the EventEmitter, but running into problems.

My RetailerService:

export class RetailerService {
    public OnRetailerUpdated = new EventEmitter();;

    updateRetailer(retailer: Retailer): Promise<Retailer> {
        this.OnRetailerUpdated.next(true);
        return new Promise((resolve, reject) => {
            apigClient.retailerVPut({}, retailer, {})
                .then(function (result) {                            
                      resolve(result.data[0])
                 }).catch(function (result) {
                      reject(result)
                 });
                }
            })

        });
    }

}

And in my RetailerDetailComponent:

export class RetailerDetailComponent implements LoggedInCallback { retailer: Retailer;

public showError: boolean;

constructor(
    private retailerService: RetailerService) {

}
ngOnInit(): void {
    this.retailerService 
        .OnRetailerUpdated 
        .subscribe(value => {  
            this.showError = true;
            console.log('Event thingy worked')
        });
}

But the console message doesn't show up

1
  • Please see the update, the boolean was missing in the even emitter: new EventEmitter< boolean >(); Commented Jul 28, 2017 at 10:39

3 Answers 3

2

You have a few options here:

The first one would be to create a map of retailers inside your service which indicates which retailers are updated and set the value while you're invoking the updateRetailer method.

public retailersUpdateStates: { [id: string]: Retailer } = {};

and a method for checking the state:

public hasBeenUpdated(retailer: Retailer) {
    return !!this.retailersUpdateStates[retailer.id]
}

When method is invoked:

retailersUpdateStates[retailer.id] = true; 

And in your component:

public get hasBeenUpdated() {
    return this.retailersService.hasBeenUpdated(this.retailer);
}

The second one would be to add a hasBeendUpdated property to the Retailer model and update it accordingly. In your component template you can just do:

{{ retailer?.hasBeenUpdated }}

The third one is to go with a router param which are the retailers id which has beed updated. (But this seems not that fancy).

And there more methods for example using ngrx for a state management. With this "single source of truth" it would be a breeze to share states accross components, or using a rxjs subject to manage the retailers state, as descriped in @faisal's answer.

Sign up to request clarification or add additional context in comments.

2 Comments

This is a very reasonable approach. Alternatively you could pass that value around via a route parameter: angular.io/guide/router#route-definition-with-a-parameter
Yep, this would bind the state to the url, which could be good in some cases, but might create some unwanted ui effects, because the user could always go to that url and it would tell him that the component has been updated, even if it hasn't.
1

Use e.g. the RetailerService to share the common variables between components.

Comments

0

The best way is to use the subscription with EventEmitter. Example below:

  1. You can define an event emitter in your retailer service:

public OnRetailerUpdated = new EventEmitter< boolean >();

  1. Then, in your "updateRetailer" method, add this line:

this.OnRetailerUpdated.next(true);

  1. Subcribe to this event in you RetailerDetailComponent:

this.retailerService .OnRetailerUpdated .subscribe(value => { // Perform the appropriate action here });

private subscription;

ngOnInit() {  
    this.subscription = this.retailerService.OnRetailerUpdated
                            .subscribe(value => { 
                              // Perform the appropriate action here 
    }); 
};

ngOnDestroy() { 
    this.subscription.unsubscribe(); 
};

1 Comment

@RobbieMills You can put it in ngOnInit(), remember to unsubscribe as well after the view is destroyed to avoid any memory leaks or multiple subscriptions. See my updated answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.