Chuck
Chuck

Reputation: 245

Angular 4 cannot read property variable from app component

Thank you for any help, I understand this may be a newby question... but I can't see what I am missing and I have no compilation problems in my TypeScript.

I'm trying to do something quite simple, I want to have a variable that tells me which of my Main Menu Items is selected.

So I binded my HTML with several variables like this: (if you know how I could bind an enum value directly I will appreciate that).

<div id ="menu_popular" class="{{menuClass}}" style=" left:90px; top:368px;">
  Menu Item
</div>

Then I want to update my code declarations by invoking a function selectMenu like this:

import {Component} from '@angular/core';
import {MainMenuItem} from './domain';

@Component ({
          selector: 'app-root',
          templateUrl: './app.component.html',
          styleUrls: ['./app.component.css']
        })
export class AppComponent
{
  title = 'Angular App';
  menuClass = 'div.menu_text';

}

let selectedItem: any = MainMenuItem.POPULAR;

const selectMenu = function (item: MainMenuItem) {
  console.log ('Switching Selected Menu from: ' + selectedItem + ' to: ' + item);
  selectedItem = item;
  console.log('Asigned');
  console.log(this.AppComponent.menuClass);
  if (item === MainMenuItem.YEIIIII)
  {
 ...
 selectMenu (MainMenuItem.YEIIIII);

But I will send me a runtime error stating Cannot read property 'AppComponent' of undefined

It seems I can't reach the AppComponent values any way I

console.log(this.AppComponent.menuClass);

or

console.log(this.menuClass);

What am I doing wrong :(

Thanks!

Upvotes: 0

Views: 802

Answers (2)

Rach Chen
Rach Chen

Reputation: 1382

Don't set the this if you want to got the component self.Your function scope is range your const , if you set arrorw function you would got windows scope(like golbal).

code

export class AppComponent implements AfterContentInit{

  constructor(
    private elementRef:ElementRef
  ) { }

  title = 'Angular App';
  menuClass = 'div.menu_text';
  public selectedItem: any = MainMenuItem.POPULAR;

  ngAfterContentInit(){
    this.selectMenu (MainMenuItem.YEIIIII);
  }

  selectMenu(item: MainMenuItem) {
    console.log('Switching Selected Menu from: ' + this.selectedItem + ' to: ' + item);
    this.selectedItem = item;
    console.log('Asigned');
    console.log(this.menuClass);
    if (item === MainMenuItem.YEIIIII) { }
  }

}

Upvotes: 1

Andresson
Andresson

Reputation: 1307

I am assuming that you have multiple menuItems that can be selected. A simple solution, is to store all menuItems in a array in your .ts file.

menuItem:string[] = ['item1', 'item2', 'etc'];
selectedItem: number = 0;
menuClass = 'div.menu_text';  

And then in your html file you can display them like so.

<div
    *ngFor="let item of menuItem; let i=index"
    (click)="selectedItem = i"
    [ngClass]="selectedItem==i ? menuClass:''">{{item}}
</div>

What the html does is it loops through the menuItem array and populates the view. In this case it would populate 3 divs. That is done by let item of menuItem. As you can see we are not just looping, we have also declared a index variable within the for-Loop. Each menuItem that is being spawned to the view does also contain a click event. OnClick we set the selectedItem to the index value. And last but not least we have the [ngClass] That is a angular directive which allows us to add class on a condition. selectedItem==i ? menuClass:''. If selectedItem is equal to the menuItem div's index we add the menuClass which is declared in the .ts else ' '.

Hope this gives you some idea of how you could do this. This is probably not the best way to solve your problem but might help you.

Upvotes: 1

Related Questions