el_pup_le
el_pup_le

Reputation: 12179

Input() property undefined for Angular component

Why is this property undefined?

export class DataFormComponent implements OnInit {

  distanceDropdownItems: any[];

  constructor() { }

  ngOnInit() {
    this.distanceDropdownItems = DISTANCE_DROPDOWN_ITEMS;
    console.log('FORMS dropdown items = ', this.distanceDropdownItems); < ---- defined ... [{},{},...]
  }

}

Template:

<app-input-dropdown [dropdownItems]="distanceDropdownItems"></app-input-dropdown>

Child component:

@Component({
  selector: 'app-input-dropdown',
  templateUrl: './input-dropdown.component.html',
  styleUrls: ['./input-dropdown.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class InputDropdownComponent implements OnInit {

  @Input() dropdownItems: any[];

  selectedItem: any;

  constructor(private el: ElementRef) { }

  ngOnInit() {
    console.log(this.dropdownItems);  <------- Undefined
    this.selectedItem = this.dropdownItems[0];

    const dropdownButton = this.el.nativeElement.querySelector('.dropdown-button');
    dropdownButton.classList.remove('dropdown-button');
    dropdownButton.classList.add('dropdown-input-button');

  }

}

Upvotes: 0

Views: 1306

Answers (4)

nircraft
nircraft

Reputation: 8468

You may have distanceDropdownItems undefined in parent. Check out the link below showing an example to share the data using Input decorator to child.

Share data from parent to child using Input decorator

If not, there could be another issue in the way the components are getting loaded in DOM, If child is placed in DOM before parent then ngOnInit() call happens only for the first time at the time of Init. And that would cause your input to be undefined in child. So You may try to implement ngOnChanges() in place of ngOnInit() which will help in picking up the value chnage from parent if there is a delay in parent loading and passing data to child.

Use *ngIf in your parent component to delay the initialization of the child component. You will bind the child component only if required object has a value.

Let me know if a code example would help and i can share here.

Upvotes: 0

CruelEngine
CruelEngine

Reputation: 2841

Since you are dealing with the child component and the @Input() , i suggest you to do something like this :

@Component({
  selector: 'app-input-dropdown',
  templateUrl: './input-dropdown.component.html',
  styleUrls: ['./input-dropdown.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class InputDropdownComponent implements OnInit , OnChanges{

  @Input() dropdownItems: any[] = [];

  selectedItem: any;

  constructor(private el: ElementRef) { }

  ngOnChanges(changes : SimpleChanges){
   if(changes.dropdownItems.currentValue != undefined){
     console.log(changes.dropdownItems.currentValue);
     this.dropdownItems = changes.dropdownItems.currentValue ; // your dropdownItems will have data passed y component
         console.log(this.dropdownItems);  <------- won't be Undefined
    this.selectedItem = this.dropdownItems[0];

    const dropdownButton = this.el.nativeElement.querySelector('.dropdown-button');
    dropdownButton.classList.remove('dropdown-button');
    dropdownButton.classList.add('dropdown-input-button');
   }
  }

  ngOnInit() {    
  }

}

Upvotes: 0

Sajeetharan
Sajeetharan

Reputation: 222542

You are using items instead of distanceDropdownItems as you showed in the parent component, try channging the variable name as follows,

<app-input-dropdown [dropdownItems]="distanceDropdownItems"></app-input-dropdown>

Also to avoid undefined or null errors, you could use *ngIf on the parent component to make sure dropdownItems dont throw any errors whenever you initialize the child component

<app-input-dropdown *ngIf="distanceDropdownItems"  [dropdownItems]="this.distanceDropdownItems"></app-input-dropdown>

EDIT

now after the edit it looks like you are using wrong variable on the child component, change your variable as,

@Input() items: any[];

ngOnInit() {
  console.log(this.items);
}

EDIT

With the latest edit, after you changed your input to dropdownItems, the template on the parent component should be adjusted as,

<app-input-dropdown [dropdownItems]="items"></app-input-dropdown>

Upvotes: 2

kamentk
kamentk

Reputation: 547

It does not look like you have items defined in your dropdown component. In your ngOnInit you should be logging dropdownItems instead ro rename the name of input property to items. Also in the parent HTML you should be defining the child component with [dropdownItems]=items

Upvotes: 0

Related Questions