How to add custom component item to list


#1

I created a new blank project for testing purposes, with a custom component. It works fine if i use the component in the html of the homepage. But what i want to do, is use the component in a list. This is where i am stuck. Adding items (strings for instance) in the list data is working fine and showing up. But how do i get the rendered html of the component in that list? Need a push in the right direction.

home.html

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Blank
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
<button ion-button color="light" (tap)="tapEvent($event)">Light</button>
<ion-item *ngFor="let item of items">
      {{item}}
</ion-item>
<test-one></test-one>
</ion-content>

home.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
    
    items: string[] = [];

  constructor(public navCtrl: NavController) {
  }
  
  tapEvent(event)
  {
      console.log(event);
      this.items.push("bier!");
  }

}

test-one.html

<!-- Generated template for the TestOneComponent component -->
<div (tap)="tapEvent($event)">
  {{text}}
</div>

test-one.ts

import { Component, ElementRef, Renderer } from '@angular/core';

/**
 * Generated class for the TestOneComponent component.
 *
 * See https://angular.io/api/core/Component for more info on Angular
 * Components.
 */
@Component({
  selector: 'test-one',
  templateUrl: 'test-one.html'
})
export class TestOneComponent {

  text: string;

  constructor(private element : ElementRef, private renderer : Renderer) {
    console.log('Hello TestOneComponent Component');
    this.text = 'TestOneComponent';
  }
  
  tapEvent(event)
  {
      console.log("TestOneComponent tapEvent");
  }
  
  // Manipulation test
  ngAfterViewInit()
  {
      console.log(this.element);
      this.renderer.setElementStyle(this.element.nativeElement, 'color', '#f00');
  }

}

#2

Pay close attention to the “Item Placement” section of the Item docs.


#3

@netexpo If you want to show the TestOneComponent in the list, you could change:

<ion-item *ngFor="let item of items">
      {{item}}
</ion-item>

to

<ion-item *ngFor="let item of items">
      <test-one></test-one>
</ion-item>

Also, if you want to pass the text of item to test-one (otherwise the for-loop seems a bit meaningless), you could change the component to have an @Input() to receive it:

import { Component, ElementRef, Input, Renderer } from '@angular/core';

/**
 * Generated class for the TestOneComponent component.
 *
 * See https://angular.io/api/core/Component for more info on Angular
 * Components.
 */
@Component({
  selector: 'test-one',
  templateUrl: 'test-one.html'
})
export class TestOneComponent {

  @Input() text: string;

  constructor(private element : ElementRef, private renderer : Renderer) {
    console.log('Hello TestOneComponent Component');
    //remove this: this.text = 'TestOneComponent';
  }
  
  tapEvent(event)
  {
      console.log("TestOneComponent tapEvent");
  }
  
  // Manipulation test
  ngAfterViewInit()
  {
      console.log(this.element);
      this.renderer.setElementStyle(this.element.nativeElement, 'color', '#f00');
  }

}

And then use it like:

<ion-item *ngFor="let item of items">
      <test-one [text]="item"></test-one>
</ion-item>

(remember to declare the component in an NgModule that either declares the HomePageComponent or that is imported by another NgModule that declares the home page, otherwise you would receive an error saying that the NgFactory was not found or something along these lines)

You can know more about Angular in following their official tutorial:

https://angular.io/tutorial

If you don’t know which component to instantiate beforehand, you could use a more advanced approach with ComponentFactoryResolver, to instantiate with using its reference.

Update

Like @rapropos said above, it’s important to take in account item placement. This post is about ionic3, so it would need to have item-content or some other placement, like:

<ion-item *ngFor="let item of items">
      <test-one item-content [text]="item"></test-one>
</ion-item>

(In v4 you should need to use slot)


#4

This helped me so much! Thanks.