Search code examples
angularundefinedrouterangular-routing

Angular this.router is undefined even declared in the constructor


As you can see in my angular project I am inyecting the router in the constructor as I have done in several projects that a did a few years ago and i have forget a lot of things, the point is that is not redirecting me to /home and this.router is undefined. enter image description here

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'login',
  templateUrl: './login.component.html',
  styleUrls:['./login.component.css']
})
export class LoginComponent implements OnInit {
  
  constructor( private router: Router) { }

  ngOnInit(): void {
  }

  login(username : string, password: string): void {
    console.log(username);
    console.log(this.router);
    this.router.navigate(['/home']);
  }
}

enter image description here

I have seen a lot of post in which the error was that the router was not inyected in the constructor but in my case it is.

Also this is my app.module.ts

import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginBoxComponent } from './components/loginBox/loginbox.component';
import { HomeComponent } from './pages/home/home.component';
import { LoginComponent } from './pages/login/login.component';
import { MainComponent } from './pages/main/main.component';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
    LoginBoxComponent,
    LoginComponent,
    HomeComponent,
    MainComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    ReactiveFormsModule,
    FormsModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app-routing.module.ts

import { LoginComponent } from './pages/login/login.component';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './pages/home/home.component';
import { MainComponent } from './pages/main/main.component';

const routes : Routes = [
  {path: 'home', component: HomeComponent},
  {path: 'login', component: LoginComponent},
  {path: '**', pathMatch: 'full', redirectTo: '/login'}
]

@NgModule({
  declarations: [],
  imports: [
    RouterModule.forRoot(routes)
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule { }

and the components / pages involved login.component.html

<div class="text-center" style="width: 100%">
    <loginbox [clickLoginFunction]="login"></loginbox>
</div>

loginboc.component.html

<div class="wrapper fadeInDown">
  <div id="formContent" >

    <!--
    <div class="fadeIn first">
      <img src="http://danielzawadzki.com/codepen/01/icon.svg" id="icon" alt="User Icon" />
    </div>
    -->
    <div class="m-3">
      <h1>WigStat</h1>
      <form>
        <div class="mt-3">
          <input type="text" [(ngModel)]="emailOrUsername" id="login" class="fadeIn second" name="emailOrUsername" placeholder="username">
        </div>
        <div class="mt-3">
          <input type="password" [(ngModel)]="password" id="password" class="fadeIn third" name="password" placeholder="password">
        </div>
        <div class="mt-3">
          <input type="submit" class="fadeIn fourth mt-4 mb-4" value="Log In" (click)="loginClick()">
        </div>
      </form>
    </div>

    <!--
    <div id="formFooter">
      <a class="underlineHover" href="#">Forgot Password?</a>
    </div>
    -->

  </div>
</div>

loginboc.component.ts

import { Component, Input, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import Swal from 'sweetalert2';

@Component({
  selector: 'loginbox',
  templateUrl: './loginbox.component.html',
  styleUrls:['./loginbox.component.css']
})
export class LoginBoxComponent implements OnInit {
  
  @Input()
  clickLoginFunction!: (emailOrUsername: string, password: string) => void;
  
  emailOrUsername!: string;;
  password!: string;

  constructor() {
   }
  
  ngOnInit(): void {
  }

  loginClick(){
    console.log("Internal function call in component");
    
    if(this.emailOrUsername === undefined || this.emailOrUsername === ''){
      this.showErrorModelInRegister('No se han introducido usuario');
      return;
    } else if (this.password === undefined || this.password === ''){
      this.showErrorModelInRegister('No se ha introducido password');
      return;
    }
    this.clickLoginFunction(this.emailOrUsername, this.password);
  }

  private showErrorModelInRegister(message:string){
    Swal.fire(message);
  }
}

console log of "this" vairables enter image description here

As you can see in the log I can see that the username is perfectly received

Does anyone knows what is happening?

Thanks in advance


Solution

  • Solution: Using an @Output. I was wrong about using an @Input because the info goes from the child to the parent.

    loginbox.component.ts

    import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
    import { Router } from '@angular/router';
    import Swal from 'sweetalert2';
    
    @Component({
      selector: 'loginbox',
      templateUrl: './loginbox.component.html',
      styleUrls:['./loginbox.component.css']
    })
    export class LoginBoxComponent implements OnInit {
    
      @Output() clickLoginFunction!: EventEmitter<loginArguments>;
      
      emailOrUsername!: string;;
      password!: string;
    
      constructor() {
        this.clickLoginFunction = new EventEmitter();
      }
      
      ngOnInit(): void {
      }
    
      loginClick(){
        console.log("Internal function call in component");
        
        if(this.emailOrUsername === undefined || this.emailOrUsername === ''){
          this.showErrorModelInRegister('No se han introducido usuario');
          return;
        } else if (this.password === undefined || this.password === ''){
          this.showErrorModelInRegister('No se ha introducido password');
          return;
        }
        let loginParam:loginArguments={emailOrUsername: this.emailOrUsername, password: this.password}; 
        this.clickLoginFunction.emit(loginParam);
      }
    
      private showErrorModelInRegister(message:string){
        Swal.fire(message);
      }
    }
    
    export interface loginArguments{
      emailOrUsername:string,
      password:string
    }
    
    

    login.component.ts

    import { Component, OnInit } from '@angular/core';
    import { Router } from '@angular/router';
    import { loginArguments } from 'src/app/components/loginBox/loginbox.component';
    
    @Component({
      selector: 'login',
      templateUrl: './login.component.html',
      styleUrls:['./login.component.css']
    })
    export class LoginComponent implements OnInit {
      
      constructor( private router: Router) { 
        console.log("Contructor of login component called")
      }
    
      ngOnInit(): void {
      }
    
      login(loginParameter : loginArguments): void {
        console.log(loginParameter.emailOrUsername);
        console.log(loginParameter.password);
        this.router.navigate(['/home']);
      }
    }
    

    login.component.html

    <div class="text-center" style="width: 100%">
        <loginbox (clickLoginFunction)="login($event)"></loginbox>
    </div>
    

    Thanks @A.Chiesa!