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>
4
  • how are the components linked? parent child or router? Commented Aug 20, 2017 at 5: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 (<app-education></app-education>) @Aravind Commented Aug 20, 2017 at 5:51
  • Have a look here, use that approach: stackoverflow.com/a/45710245/1791913 , also read about component interaction/communication in angular. Commented Aug 20, 2017 at 5:55
  • [angularjs] != [angular]. Be careful with tags! ;-) Commented Aug 22, 2017 at 14:39

2 Answers 2

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

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

3 Comments

Would there be a way to do this using EventEmitter?
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.
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.
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.

Comments

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.