Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing a value in two different components at the same time Angular 2

Tags:

angular

I am practicing with @Input and @Output and here is the issue.

In my home component I have the following:

<!-- Main Content -->
<div class="container">
    
    <div *ngIf="registered">
        <login></login>
    </div>
    
    <div *ngIf="!registered">
        <register></register>
    </div>
    

</div>

registered is located in the HomeComponent.ts

@Component({
    selector:'home',
    templateUrl:'./home.html',
})

export class HomeComponent {

    registered:Boolean = true;

}

My goal is to change the value registered in the home component depending on what is pressed.

If register is pressed in the navigation bar, the form will change to the register form because the value in the home component has been changed. However, if login is pressed it goes back.

I made this a little more complicated but this is for learning purposes.

In the directory user I have three modules, Login, Register and UserService. UserService imports the components from LoginandRegisterand exports them. I importUserServiceintoNavigationBar` module.

In the home.html page where I want to change the forms I just call <nav-bar></nav-bar>

@NgModule({

    imports:[
        SmartAdminModule,
        UserModule //has Login and Register components
    ],

    declarations: [NavigationBarComponent],
    exports: [NavigationBarComponent]
})
export class NavBarModule {

}

I am trying to figure out a way to use either @Output or @Input to solve this issue.

This is also on GitHub HERE Any advice with be greatly appreciated.

----------------After some advice from this post this is how I did it but is still not working------------------

I made a UserService

        @Injectable()
export class UserService {

    public registered: Boolean;

    @Output() FormUpdate = new EventEmitter();

    public SetUserToRegistered(){
        this.registered = true;
        this.FormUpdate.emit(this.registered);
        
    }

    public SetUserToUnregistered(){
        this.registered = false;
        this.FormUpdate.emit(this.registered);
       
    }

}

Then I injected it into the home.module.ts

@NgModule({

    imports:[
        SmartAdminModule,
        UserModule,
        NavBarModule
    ],

    exports:[HomeComponent],

    declarations: [HomeComponent],

    providers: [UserService]

})
export class HomeModule {


}

HomeComponent:

 @Component({
    selector:'home',
    templateUrl:'./home.html',
})

export class HomeComponent {

    registered: Boolean;

    constructor(private userService: UserService) {

        this.registered = this.userService.registered;
    }

    handleFormUpdate(formUpdate){
        //what to do here
    }
}

Then I had a aha moment and thought I would make the Login and Register buttons and inject the userService in there and then that button would be pressed it would change the value of this.registered = this.userService.registered; in the HomeComponent

NavBar.html

<div>
                <button (click)="showRegister()">Register</button>
                <button (click)="showLogin()">Login</button>
            </div>

NavBarComponent:

@Component({
    selector:'nav-bar',
    templateUrl:'./navigationBar.html',
})

export class NavigationBarComponent{

    constructor (private userService: UserService) { }


    showLogin(){
        this.userService.registered = true;
    }

    showRegister(){
        this.userService.registered = false;
    }


}

home.html

<div class="container">
    
    <div *ngIf="registered">
        <login (formUpdate)="handleFormUpdate($event)"></login>
    </div>
    
    <div *ngIf="!registered">
        <register (formUpdate)="handleFormUpdate($event)"></register>
    </div>
    
</div>

However nothing is happening.

The project is updated on GitHub.

like image 287
Mike3355 Avatar asked Jan 20 '17 20:01

Mike3355


1 Answers

The UserService you have set up is spot on and the best way to manage this variable, I would even go as far as to put the methods that change registered from true to false in the service. That way you know exactly where it is controlled and if you use the flag elsewhere you are not changing that variable on random components.

@Component({
    selector:'nav-bar',
    templateUrl:'./navigationBar.html',
})
export class NavigationBarComponent{

    constructor (private userService: UserService) { }

    showLogin(){
        this.userService.SetUserToRegistered();
    }

    showRegister(){
        this.userService.SetUserToUnregistered();
    }
}

Perhaps the methods could be named different and you can work them in better as you expand your application but it feels like a better approach.

Now you need an observable to monitor that variable, which I wrote in the second part of my answer.

You could even use some rxjs and set the variable up in the service as an observable so that the home component can subscribe to it.

export class HomeComponent implements OnInit {

    public registered: boolean = true;

    public ngOnInit(): void {
        this.userService.RegisteredObservable().subscribe((registered) => {
           this.registered = registered;
        });
    }
}

Then the service could look something like this

import { Injectable } from "@angular/core";
import { BehaviourSubject } from "rxjs/BehaviourSubject";
import { Observable } from "rxjs/Observable";

@Injectable()
export class UserService {

    private registered: BehaviorSubject<boolean>;

    constructor() {
        this.registered = new BehaviourSubject<boolean>();
    }

    public RegisteredObservable(): Observable<boolean> {

         return this.registered;
    }

    public ChangeRegistered() {
         //do stuff

         this.registered.next(newRegisteredValue);
    }
}
like image 95
Oliver Cooke Avatar answered Nov 15 '22 09:11

Oliver Cooke