0

I'm storing some values in an array domain:Domain[], if I wanted to transfer the array from a parent's component to a child's component by using the child's selector inside of my parents html file then declaring the decorator @Input() domain: Domain[]; in my child's component to get the contents inside the array should I be able to use domain.id if I wanted inside a function in my child's component? I'm just having a hard time grasping this concept.

This is the stackblitz file: https://stackblitz.com/github/pennyfea/Project3-HCI

This is my parent's component where I'm storing the initial data in the array. Then I would try to pass it over to the child's component using the child's selector inside of the parent's html file. Something I've seen on a number of other questions and tutorials.

import { Component, OnInit, Input } from '@angular/core';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { Location } from '@angular/common';
import { ImageService } from './shared/image.service';
import { DomainService } from '../domain.service';
import { GraphService } from '../graph.service';
import { LibraryService } from '../library.service';
import { Domain } from '../library';
import { Library } from '../library';
import { map,mergeMap } from 'rxjs/operators';


@Component({
  selector: 'app-metric-details',
  templateUrl: './metric-details.component.html',
  styleUrls: ['./metric-details.component.css']
})
export class MetricDetailsComponent implements OnInit {

  visibleImages: any[] = [];
  activeId = 0;
  domain: Domain[];

  constructor(private imageService: ImageService, private domainService: DomainService, private libraryService:LibraryService, private graphService:GraphService, private location: Location, private route: ActivatedRoute,  private router: Router) {
    this.visibleImages = this.imageService.getImages();

}

  ngOnInit() {
      this.route.params.subscribe(params => { {this.activeId = +params['id'];
      console.log(this.activeId); //log the entire params object
    // console.log(params['id']) //log the value of id
    // const id = +this.route.snapshot.paramMap.get('id');
    // console.log(id);
      console.log(this.domainService.getDomain(this.activeId));
      // this.domainService.getDomain(this.activeId).subscribe(domain =>this.domain = domain;console.log("Added",this.domain);});
      this.domainService.getDomain(this.activeId).subscribe(domain => {this.domain = domain; console.log(this.domain);})
    }
  }
<h2>Visualized Software Metrics</h2>
<h2 *ngIf="domain?.catergory">Domain: {{ domain.catergory | uppercase }}</h2>
<h2 *ngIf="library?.name">Library: {{ library.name | uppercase }}</h2>
<div class = "row">
  <ul id = "thumbnailslist">
    <li *ngFor="let image  of visibleImages ">
      <a [routerLink] = "['/image', image.id]">
        <img src = "{{image.url}}" class = "tn">
      </a>
    </li>
  </ul>
</div>
<app-metric-view [domain] = "domain"></app-metric-view>

This is my child's component where I want to get the information from my parent's component using the input decorator, then using the information from the array say the domain.id inside a function.

<div *ngIf="image">
  <h2>{{ image.catergory | uppercase }}</h2>
<div>

  <div *ngIf = "domain.id === 1" class ="row" >
    <button (click)="prev()" class="previous round">&#8249;</button>
      <div  [ngStyle] = "{'background-image': 'url('+ testing.url +')'}" class ="img-container">
      </div>
    <button (click)="next()" class="next round">&#8250;</button>
  </div>


  <!-- <div class ="row" >
      <button (click)="prev()" class="previous round">&#8249;</button>
      <div  [ngStyle] = "{'background-image': 'url('+ testing.url +')'}" class ="img-container">
      </div>
      <button (click)="next()" class="next round">&#8250;</button>
  </div>

</div> -->

<div class = "tab-rating">
  <ngbd-rating-template></ngbd-rating-template>
  <ngbd-tabset-basic></ngbd-tabset-basic>
</div>



<!-- <div *ngIf="domain.id != 1" class ="row" >
    <button (click)="prev()" class="previous round">&#8249;</button>
    <div  [ngStyle] = "{'background-image': 'url('+ testing.url +')'}" class ="img-container">
    </div>
    <button (click)="next()" class="next round">&#8250;</button>
</div> -->
import { Component, OnInit, Input} from '@angular/core';
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { Location } from '@angular/common';
import { ImageService } from '../metric-details/shared/image.service';
import { LibraryService } from '../library.service';
import { Library } from '../library';
import { Domain } from '../library';
import { GraphService } from '../graph.service';
import { DomainService } from '../domain.service';
import { map,mergeMap } from 'rxjs/operators';

@Component({
  selector: 'app-metric-view',
  templateUrl: './metric-view.component.html',
  styleUrls: ['./metric-view.component.css']
})
export class MetricViewComponent implements OnInit {
image: any;
testing: any;
visibleImages: any[] = [];

@Input() domain: Domain[];


  constructor(private imageService: ImageService, private libraryService:LibraryService, private domainService: DomainService, private graphService:GraphService, private location: Location, private route: ActivatedRoute, private router: Router) {
    this.visibleImages = this.imageService.getImages();
   }


  ngOnInit() {
    this.testing =  this.graphService.getTestingGraphs(domain.id);
    console.log(this.testing);
    this.image = this.imageService.getImage(domain.id);
    console.log(this.image);

}

  next() {
    // const next = this.activeId + 1 >= this.image.length - 1  ? this.graph.length - 1 : this.activeId + 1;
    const next = this.activeId + 1 >= 9  ? 1 : this.activeId + 1;
    this.router.navigate(['/image/' + next]);
  }

  prev() {
    const prev = this.activeId - 1 < 1 ? 9 : this.activeId - 1;
    this.router.navigate(['/image/' + prev]);
  }

}

4
  • So, is there a problem? Is this not working? Or, are you looking for a code review? Commented Apr 6, 2018 at 18:56
  • It does not work, it tells me domain is not defined in my parent's html file as well as child's component.ts file Commented Apr 6, 2018 at 18:57
  • @DiabolicWords domain undefined Commented Apr 6, 2018 at 18:57
  • @R.Richards no there is an actual problem. Not a code review. It gives me an error of domain undefined. Commented Apr 6, 2018 at 19:22

3 Answers 3

1

Live working example. The error is when you make click on the metric-view component, you are no longer using nested components communication but using routing to pass that domain to that component.

constructor(
    private imageService: ImageService, 
    private libraryService:LibraryService, 
    private domainService: DomainService, 
    private graphService:GraphService, 
    private location: Location, 
    private route: ActivatedRoute, private router: Router) {
      this.route.params.subscribe((domain: Domain) => {
          this.domain = domain;
      });
      this.visibleImages = this.imageService.getImages();
   }

When you click on that image, that component no get render thanks to this line metric-details.component.html (by the way, you comment it out)

<app-metric-view [domain] = "domain"></app-metric-view>

It is getting render thanks to the magic of Angular rounting:

<a [routerLink] = "['/image', image.id]">
  <img src = "{{image.url}}" class = "tn">
</a>

and since image.id has the data you need to for things to work propertly, you get access to that info, in this way:

this.route.params.subscribe((domain: Domain) => {
  this.domain = domain;
});
Sign up to request clarification or add additional context in comments.

7 Comments

Could you explain more for me. Not quite sure what's the issue. Because I still get the same domain is not defined error.
Can we talk in a chat?
Ok that make sense, I don't really just want to get the id number alone. I want to keep track of the catergory/domain that was chosen. So for example in the domain array i should be able to pass to the child component. "{id: 1, catergory: "testing"}"
Thats why i'm using the input decorator, I'm not really concerned with the image.id
but you can add it to the routerLink, <a [routerLink] = "['/image', image.id, domain]"> <img src = "{{image.url}}" class = "tn"> </a>
|
0

You have a bunch of code there but practice is not to use constructor to do things, rather use OnInit to call service and get images.

Comments

0

The stackblitz sample project had two syntax problems. In app/dashboard/dashboard.component.ts your class declaration was never terminated (perhaps confusing the closing brace for ngOnInit with the closing brace for the class). Fix that up:

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {

  domain = DOMAIN;
  constructor(
    private location: Location, 
    private route: ActivatedRoute, 
    private router: Router
  ) { }

  ngOnInit() { } 
}

And then clean up similar syntax issues within metric-details.component.ts. Here's a version of your stackblitz for reference with those errors cleaned up. If it still differs from what you were trying to accomplish, having a working sample will better direct the conversation with those who are willing to help.

1 Comment

I'm sorry, I'm not sure where the syntax errors are but I did readjust the code. stackblitz.com/edit/github-vli4rr

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.