2

I am using Angular 2.4.1, and my final Hello World is the next:

My index is composed by nav bar (which has display:none) and a router-outlet for presenting different views. My default view is a carousel with a link to a specific view. When I click in this link, the specific view will be loaded and (here is the problem), I would like to show the nav-bar (display:block) as well. I am stuck, and I can´t figure out how to achieve it.

My problem is being how can I reach the nav-bar (id, or even class) in my first component, from my second component.

My best approach is changing the css property of this nav-bar in the OnInit of its component. Not working... document is not recognized.

export class SociosComponent implements OnInit {
    ngOnInit(): void {
        this.document.getElementById('nav-principal').style.display = "block";
    }
}

Here are part of the code:

app.component

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
  <ul id="nav-principal" style="display:none; background-color:transparent;" class="nav nav-tabs">
    <li role="presentation" class="active"><a routerLink="/index">Index</a><li>
    <li role="presentation"><a routerLink="/socios">Socios</a><li>
  </ul>
  <router-outlet></router-outlet>
  `
})

export class AppComponent { 
}

app.rounting

// Importar componentes y módulos para el routing 
import { Routes, RouterModule } from '@angular/router';

// Componentes
import { SociosComponent } from './socios.component';
import { Index } from './index';

// Configuración de las rutas
const appRoutes: Routes = [
  { path: '', redirectTo: 'index', pathMatch: 'full' },
  { path: 'index', component: Index },
  { path: 'socios', component: SociosComponent },
];

export const routing = RouterModule.forRoot(appRoutes);

socios.component

import { Component } from '@angular/core';

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

export class SociosComponent implements OnInit {
    ngOnInit(): void {
        this.document.getElementById('nav-principal').style.display = "block";
    }
}

Thanks guys.

2 Answers 2

2

Directly modifying DOM elements like that is considered bad practice in Angular.

A proper way to do it would be to store the menu state in a service, then modify that from your component.

Menu state service:

import { Injectable } from '@angular/core';

@Injectable()
export class MenuStateService {
  isActive: boolean = false;

  enable() {
    this.isActive = true;
  }

  disable() {
    this.isActive = false;
  }
}

Import into your app component:

import { Component } from '@angular/core';
import { MenuStateService } from './menu-state.service';

@Component({
  selector: 'my-app',
  template: `
  <ul id="nav-principal" *ngIf="menuStateService.isActive" class="nav nav-tabs">
    <li role="presentation" class="active"><a routerLink="/index">Index</a><li>
    <li role="presentation"><a routerLink="/socios">Socios</a><li>
  </ul>
  <router-outlet></router-outlet>
  `
})

export class AppComponent {
    constructor(public menuStateService: MenuStateService) {}
}

Make sure to also add the service to the providers array of your app module, or you're going to have a bad time.

And then you can enable or disable the menu from any component using the methods defined in the service:

import { Component } from '@angular/core';
import { MenuStateService } from './menu-state.service';

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

export class SociosComponent implements OnInit {
    constructor(private menuStateService: MenuStateService) {}

    ngOnInit(): void {
        this.menuStateService.enable();
    }
}

It might seem like overkill now, but as your app grows you might find you need to store more information about the menu, or maybe add additional functionality. Then you'll already have a place for it.

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

3 Comments

Thanks @Brother Woodrow. I need to improve this way of thinking... Cheers.
It is considered "bad" because your code is directly tied to a specific environment which is the browser, so you can't use it in a different environment. it is not bad because it poses a security hole. Also, ngIf modifies the DOM if its expression changes, it removes or inserts the enclosed DOM objects, so if you just want to show/hide something frequently, ngIf isn't the best choice
Thanks @Biu. So, for my purpose. nav-bar which is showed at the load of the component this option is the correct way, isn´t?
2

You don't want to qualify document with this which refers to the current component class, document is in the global scope so do like the following

export class SociosComponent implements OnInit {
    ngOnInit(): void {
        (document.getElementById('nav-principal') as HTMLElement).style.display = "block";
    }
}

3 Comments

Hi @Dummy. So fast!! It works!! Thanks! :). Cheers Mate :)
Ayy. That's what's up :)
LOL... Thanks!! :)

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.