1

I have a 2 components, one is my header and one is just plain text at the moment.

On the header there is a menu to pick options. When one of the options is clicked on the header, i want to toggle a boolean in the other component and display the entire html.

How can I do this from the onClick() in the header menu?

Console says the function I'm trying to call is undefined.

//this is in one folder...

export class EducationComponent {

 showEducation: boolean = true;

 toggleEducation () {
 this.showEducation = !this.showEducation;
  }
}

 

//this is is a different folder...

<li><a (click)="toggleEducation()">Education</a></li>
Mistalis
  • 17,793
  • 13
  • 73
  • 97
timdirusso
  • 51
  • 1
  • 8
  • how are the components linked? parent child or router? – Aravind Aug 20 '17 at 05:47
  • I'm very new to this so I'll try to explain. In the app component all the imports are stated and in the app.html the selectors are placed () @Aravind – timdirusso Aug 20 '17 at 05:51
  • Have a look here, use that approach: https://stackoverflow.com/a/45710245/1791913 , also read about component interaction/communication in angular. – FAISAL Aug 20 '17 at 05:55
  • `[angularjs]` != `[angular]`. Be careful with tags! ;-) – Mistalis Aug 22 '17 at 14:39

2 Answers2

4

The purpose of a component class is to provide the properties and methods needed by the component's template. So the template will look to its associated class to find the properties and methods.

If you need to share properties or methods across several components, use an Angular service instead.

I have a blog post about Angular services here: https://blogs.msmvps.com/deborahk/build-a-simple-angular-service-to-share-data/

The code basically looks like this:

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

@Injectable() 
export class DataService {
  serviceData: string; 
}

In your case, the serviceData would be a boolean instead of a string.

One component could set the value and the other can bind to it.

I also have this code in a plunker if you want to try it out: https://plnkr.co/edit/KT4JLmpcwGBM2xdZQeI9?p=preview

DeborahK
  • 57,520
  • 12
  • 104
  • 129
  • Would there be a way to do this using EventEmitter? – timdirusso Aug 20 '17 at 06:07
  • You would not want to, at least not directly. If the relationship between the components are parent and child (like someone asked previously), then you can use `@Input` and `@Output` (which works with an EventEmitter. – DeborahK Aug 20 '17 at 06:12
  • Is there a reason not to create a simple service? If you can do a plunker demonstrating what you are trying to do I can show you how to add a service to it. – DeborahK Aug 20 '17 at 06:15
0

If the menu component is the child of the other component, you can emit an Event from it and listen to it on the other component.

Example:

foo.ts

import { Component, Output, EventEmitter } from '@angular/core'; 

@Component({
    selector: 'foo',
    template: `<button (click)="OnMyEvent()">Click to fire Event</button>`
})
export class Foo {
    @Output() myEvent = new EventEmitter();

    usefullInformation = {mymessage: 'It works'};

    OnMyEvent() {
        this.myEvent.emit(this.usefullInformation);
    }
}

bar.ts

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

@Component({
    selector: 'bar',
    template: `
        <foo (myEvent)="handleMyEvent($event)"></foo>
        <div>
            I listen to an Event!
            {{ usefullInformation | json }}
        </div>`
})
export class Bar {

    usefullInformation;

    handleMyEvent(eventObject) {
        this.usefullInformation = eventObject;
        console.log(JSON.stringify(this.usefullInformation));
    } 
}

Example Plunk: http://embed.plnkr.co/jO3Ja1qVRqssmKu8YPbF/

Hint: Angular EventEmitter events do not bubble. This is for the same reason the official guide (https://angular.io/guide/component-interaction) only handles parent<->child interaction. Coders with limited software engeneering skills might wonder about it or use workarounds like dispatchEvent(event). But the stream of information is easier to understand if it is limitied by the DOM-Structure. In a medium sized app, debugging would get hard if every component is able to "talk" to every other component. If components with no parent<->child relation need to "talk", there is always the way to wire through a common ancestor:

<c-ancestor>
    <foo></foo>
    <bar></bar>
</c-ancestor>

Or one can use more advanced architecture approaches like redux.

Koudela
  • 181
  • 6