5

I have two Angular components

results.table and results.query

I want to hide the table inside the results.table.component when the user clicks on the reset button within the results.query.component

Maybe I am doing this wrong with event emitter, or maybe there is a better way to do this

results.table HTML

<div *ngIf='results?.length>0'>
  <table *ngIf="showResults" class='table'>
    <tr>
      <th>Result Name</th>
      <th>Location</th>
    </tr>
    <tbody>
    <ng-template ngFor let-results [ngForOf]='items' let-i="index">
      <tr>
        <td>
          <span>{{result?.description}}</span>
        </td>
        <td>
          <span>{{result?.location}}</span>
        </td>
      </tr>
    </ng-template>
    </tbody>
  </table>
</div>

results.table TS

showResults: boolean = true;

showResults(event) {
    console.log('this is not getting called')
    if (event) {
      this.showResults = false;
    }
}

results.query HTML

<div class="panel-body">
      <form (submit)="onSubmitClicked()">
        <div class="row">
          <div class="form-group col-md-12 col-xs-12">

            <div class="col-xs-12 col-sm-3 col-md-3 col-lg-3">
              <label class="col-md-12 col-xs-12 control-label  no-margin no-padding">Location: </label>
              <pg-radio-toggle-select class="col-md-12 col-xs-12 no-margin no-padding" name="locationChangeInput" [(ngModel)]="Location"
                (selectedChanged)="onFilteringLocation($event)" [options]='locationOptions'>
              </pg-radio-toggle-select>
            </div>

            <pg-inputfield name="description" class="col-xs-12 col-sm-3 col-md-3 col-lg-3" [(ngModel)]="paramsModel.description"
                           displaytext="Name:"></pg-inputfield>
          </div>
        </div>

        <div>
          <button type="reset" class="btnReset" (click)="reset()">Reset</button>
          <button type="submit" name="btnSearch">Search</button>
        </div>
      </form>
    </div>

results.query TS

import {Component, OnInit, EventEmitter, Output} from '@angular/core';
import * as _ from 'lodash';
import { LocationService } from '../location-service.service';

@Component({
  selector: 'result-query',
  templateUrl: './result-query.component.html',
  styleUrls: ['./result-query.component.less'],
})
export class ResultQueryComponent implements OnInit {
  @Output() showResults:  EventEmitter<boolean> = new EventEmitter<boolean>();

  constructor(
      private LocationService: LocationService,
  ) {
    this.reset();
  }

  ngOnInit() {
    this.reset();
  }

  onSubmitClicked() {
    console.log('test')
  }

  reset(): void {
    console.log('I am the reset king');
    this.showResults = false;
    this.showResults.emit(true);
    this.onSubmitClicked();
  }
}
5
  • Can you please post your results.table component's full html? I mean we want to know how results.table component's html and results.query are related? i.e. how those two components are rendered? i.e. parent/child or something else. As per your code, we will be able to provide an answer. Commented Jun 18, 2019 at 17:06
  • @user2216584 I have added the full results.table Thanks for your help Commented Jun 18, 2019 at 19:18
  • results.table html code is fine. I would request to show us the code which relates results.table html and results.query html. I meant the template which puts these two htmls together. By seeing your results.query TS, it appears that you are having a parent/child relationship between your HTML. Giving us the code which show these two HTML together will give us the insight to provide you a better solution. Commented Jun 18, 2019 at 19:23
  • @user2216584 updated now! Thanks again Commented Jun 18, 2019 at 19:55
  • I am sorry but you are still not sharing the template which shows us the relationship between your results.table and results.query components. Let me try one more time - You have <result-query> selector from ResultQueryComponent, similarly, you would have a selector from your ResultTableComponent. How these two selectors are presented in your page? is it something like this - <result-table><result-query></result-query></result-table>? By seeing your shared code, it is really hard to know how these two components are related/rendered. Commented Jun 18, 2019 at 20:51

2 Answers 2

3

If two components does have a parent child relationship, you can use @Input() @Output() decorators.

4 Ways to share data between angular components

Component Interaction

Input Output Example

Parent Component

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { Stephen } from '../stephen.model';

@Component({
    selector: 'app-parent',
    template: `

        Hello, Mr. (or Ms.): {{ selectedName }}

`,
styleUrls: ['./parent.component.css'],
    encapsulation: ViewEncapsulation.None
})

export class ParentComponent implements OnInit {
    stephen: Stephen;
    selectedName: string;

    constructor() {
        this.stephen = new Stephen();
        this.selectedName = this.stephen.firstName;
    }

    ngOnInit() {
    }

    updateName(selectedName: string): void {
    console.log('in parent');
    this.selectedName = selectedName;
    }

}

Child Component

import { Component, OnInit, ViewEncapsulation, Input, Output, EventEmitter } from '@angular/core';
import { Stephen } from '../../stephen.model';
@Component({
    selector: 'app-child',
    template: `
        {{ stephen.firstName }}
        {{ stephen.lastName }}
        {{ stephen.fullName }}
        `,
    styleUrls: ['./child.component.css'],
    encapsulation: ViewEncapsulation.None
})
export class ChildComponent implements OnInit {
    @Input() stephen: Stephen;
    @Output() onNameSelected: EventEmitter;
    constructor() {
        this.onNameSelected = new EventEmitter();
    }
    ngOnInit() {
    }
    clicked(name: string): void {
        this.onNameSelected.emit(name);
    }
}

Important - second solution

But in your case these 2 components don't seem to have a parent child relationship. If you want to share data between two components, you can create a share-able service. This service will contain and EventEmitter to which a component that needs latest change will subscribe in ngOnInit method and the component which will have latest data will call a function from this share-able service to emit that event.

share-able service

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

@Injectable({
  providedIn: 'root'
})
export class MessengerService {

  @Output() change: EventEmitter<any> = new EventEmitter();

  sendData(data: any): any {
    this.change.emit(data);
  }

}

The component that want to know about this change will subscribe to this event in it the ngOnInit like this.

messengerService.change.subscribe(emitedValue => {
   this.value = emitedValue;
});

The component that has the new change will call the sendData method is messenge / share-able service to post new data to the event subscribers whenever it is required.

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

Comments

0

I dont know if you forgot to write it in your question, but you should have a results.query Tag in your results.Table HTML, and call the output through it. Considering your selector is app-results-query, it would be like this:

results.table HTML

<app-results-query (showResults)="changeShowResults($event)"></app-results-query>
<table *ngIf="showResults">
    //table stuff
</table>

results.table TS

showResults: boolean = true;

changeShowResults(event: boolean) {
    console.log('this is not getting called')
    if (event) {
      this.showResults = false;
    }
}

3 Comments

I already have the results binding to the HTML, I have updated the code in the description
For as I can see, your result table component doest not have any relation with the result query component. If you emit the showResults event in results.query, that wont change anything in results.table. To do what you want to do here, results.query have to be a child of result.table, like in the example code I typed above.
Here is a good simple example to understand the use of output events: dzone.com/articles/…

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.