Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Input variable not taking value from @Input property at template. Angular 5

I was trying some angular 5 with prime-ng experiments and I've found some dificulties(relative to angular 5), I made a component with the next template:

<p>Chemi-tabla works! Y ahora un mensage de nuestros patrocinadores: {{this.nombre}}</p>
<p-dataTable [value]="_postsArray" [loading]="loading"
   loadingIcon="fa-spinner" [rows]="10" [paginator]="true" 
   [multiSortMeta]="multiSortMeta" selectionMode="Single" [(selection)]="selectedUserInfo">
    <p-header>Cabecera de la Chemi Tabla.</p-header>
    <p-footer>Lo de abajo de la chemi tabla, vamos lo que va arrastrando.</p-footer>
    <p-column selectionMode="single"></p-column>
    <p-column field="userId" header="Usuario ID" sortable="true" [filter]="true" filterPlaceholder="Search"></p-column>
    <p-column field="id" header="IDE" sortable="true" [filter]="true" [filter]="true" filterPlaceholder="Search"></p-column>
    <p-column field="title" header="Título" sortable="true" [filter]="true" filterMatchMode="contains"></p-column>
    <p-column field="body" header="Body" sortable="true" [filter]="true" filterMatchMode="contains"></p-column>
</p-dataTable>

But the line :

<p>Chemi-tabla works! And now a message: {{this.nombre}}</p>

is not printing anithing in {{this.nombre}} and if I debug the code in the component the value it has is undefined.

My index html is next one:

<chemi-tabla [nombre]="Hello World">
Loading chemi's table  </chemi-tabla>

And the component.ts file is the next one:

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import {UserService} from './shared/user/user.service';
import {IPosts} from './shared/interfaces';
import {DataTableModule,SharedModule} from 'primeng/primeng';
import { HttpClientModule } from '@angular/common/http';

@Component({
  selector: 'chemi-tabla',
  templateUrl: './chemi-tabla.component.html',
  providers: [UserService],
  styleUrls: ['./chemi-tabla.component.css']
})

export class ChemiTablaComponent implements OnInit {
  _postsArray: IPosts[];
  msgs : CustomMessage[];
  selectedUserInfo : IPosts;
  @Input() nombre: string;
  constructor(private apiSerivce: UserService) {
    console.log("Constructor chemi tabla component.");

  }
  getPosts(): void {
    this.apiSerivce.getPosts()
    .subscribe(
      resultArray => this._postsArray = resultArray,
      error => console.log('Error :: ' + error)
    )
  }
  ngOnInit(): void {
    console.log(this.nombre);
    this.getPosts();
  }
}
class CustomMessage{
  severity:string;
  summary:string;
  detail:string;
  constructor(private severity_a: string, private summary_a: string, detail_a:string) {
    this.severity = severity_a;
    this.summary = summary_a;
    this.detail = detail_a;
  }
}

Finally this is the module.ts I'm using:

import { HttpModule } from '@angular/http';//para promesas subscribe y demás
import { BrowserModule } from '@angular/platform-browser';//necesariko para pintar en pantalla
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Routes, RouterModule } from '@angular/router';//necesario para redirecciones*1
import {UserService} from './shared/user/user.service';//servicio que me trae datos
import {IPosts} from './shared/interfaces';//tipos de datos
import {MessageService} from 'primeng/components/common/messageservice';//no se usa
import {DataTableModule,SharedModule} from 'primeng/primeng';//necesaroi para la tabla
import { ChemiTablaComponent } from './chemi-tabla.component';//mi componente

export const ROUTES: Routes = [
  { path: '', component: ChemiTablaComponent }//*1 podríamos decirle a un modulo que en tal direccion vaya a tal componente.... 
];
@NgModule({
  declarations: [ ChemiTablaComponent ],
  imports: [
    BrowserModule,
    CommonModule,
    DataTableModule,
    SharedModule,
    RouterModule.forChild(ROUTES),
    HttpModule
  ],
  providers: [ UserService ],
  bootstrap: [ ChemiTablaComponent ]
})
export class ChemisModule {
 public nombre : string;
 }

Everything is compiling and the p-datatable is working properly but I've no been able to make the {{nombre}} variable to appear I'm missing something and I bet it's a very stupid issue but I can't see what it is.

like image 703
Jose Miguel Avatar asked Dec 20 '17 11:12

Jose Miguel


People also ask

How do I pass a template reference variable in component?

To get started using template reference variables, simply create a new Angular component or visit an existing one. To create a template reference variable, locate the HTML element that you want to reference and then tag it like so: #myVarName .

How does @input work in Angular?

Use the @Input() decorator in a child component or directive to let Angular know that a property in that component can receive its value from its parent component. It helps to remember that the data flow is from the perspective of the child component.


2 Answers

There are three things wrong with your code.

  1. You cannot access your variable with this from your template. In your markup, you should write just {{nombre}}
  2. You don't need a public nombre : string; in your ChemisModule
  3. Also, if you want to pass an object through your props you should do it as follow <chemi-tabla [nombre]="'Hello World'"> or <chemi-tabla nombre="Hello World"> If you use brackets [], you have to put an object between quotes.

Edit

Also, I just realized you are trying to pass an attribute to your bootstrapped component. Check this question

As, it is stated in the link, you cannot pass an Input to your root component. You probably don't need to do so as well. You can just define it within your root component.

like image 81
Bunyamin Coskuner Avatar answered Oct 10 '22 04:10

Bunyamin Coskuner


My pal "Bunyamin Coskuner" answerd right before me that the problem was that my component was bootstrapped. The question he's linking above gives the solution I used this constructor on component.ts file:

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

....

constructor(private apiSerivce: UserService, private elementRef:ElementRef) {
    console.log("Constructor chemi tabla component.");    
    let nombreAttribute = this.elementRef.nativeElement.getAttribute('nombre');
    this.nombre = nombreAttribute;
    console.log(this.nombre);
  }

And now it's working. I'm explaining the needed changes I had to make in the code I post in my question.

I had to use the ElementRef module( from @angular/core) to get the value of the attribute 'nombre'like this : this.elementRef.nativeElement.getAttribute('nombre'); from the self reference we pass to the constructor "constructor(private apiSerivce: UserService, private elementRef:ElementRef)" and this way i can get properly the propertys values.

As I've understood that's because it is bootstraped module, still have to learn more about this, but that's the solution I needed today.

So vote above me to Bunyamin Coskuner, He's the one who rocks

like image 44
Jose Miguel Avatar answered Oct 10 '22 03:10

Jose Miguel