1

One specific component of my application doesn't bind any input I pass.

My component

@Component({
    selector : 'default-actions',
    templateUrl : './default.actions.template.html',
    styleUrls: [ './default.actions.style.scss' ],
    encapsulation: ViewEncapsulation.None,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class DefaultActionsComponent
{
    protected entityId;
    protected uuid = UUID.UUID();
    protected extraForms;

    @Input() protected data;
    @Input() protected structure;
    @Input() protected targetId;
    @Input() protected table;
    @Input() protected row;
    @Input() protected modal: ModalDirective;
    @Input() protected entity;
    @Input() protected entityObject: Entity;
    @Input() protected parentWrapper;
    @Input() protected foo;

    constructor(
        protected translate: TranslateService,
        protected activatedRoute: ActivatedRoute,
        protected actionService: DefaultActionsService,
        protected router: Router,
        protected entityService: EntityService,
        protected http: HttpAuthenticationService
    ) {}

    public ngOnInit() {
        console.log(this.foo);
    }

I use it here:

<default-actions
    [table]="table['defaultListingTableComponent']"
    [row]="row"
    [foo]="'bar'"
    [modal]="modal"
    [structure]="availableColumns"
    [entityObject]="entityObject"
    [targetId]="selectedRows()">
</default-actions>

I added foo input in order to do some debugging. In console the line console.log(this.foo); outputs undefined. The same happens to all other inputs.

I believe there's something wrong with the component itself, however I'm unable to find it. Other components of my application are working.

7
  • 3
    what is the reason you defined your inputs as protected? Commented Aug 26, 2019 at 19:58
  • 1
    Even that should not be a problem. Commented Aug 26, 2019 at 20:18
  • This class is used as base for others. In this case I'm using DefaultActionsComponent itself. Commented Aug 26, 2019 at 20:23
  • 1
    Can you create a stackblitz demo for this problem? Commented Aug 26, 2019 at 20:37
  • Your code works perfectly: stackblitz.com/edit/angular-xzvxqr Commented Aug 27, 2019 at 12:19

6 Answers 6

1

You should probably implement OnInit interface to make this work? Can you try?

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

1 Comment

Nothing... Still returns undefined
1

EDIT:

I just made a sample on Stackblitz : https://stackblitz.com/edit/angular-qrgy7k

Tip:

Instead of directly passing string like [foo] = "'bar'", make a variable in the parent component and then pass it as [foo] = "yourVariable"

Parent Component HTML:

<hello name="{{ name }}"></hello>
<p>
  Start editing to see some magic happen :)
</p>
<app-demo
[mydata]="datatopass"
>  
</app-demo>

Parent Component TS:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';
  datatopass = "sad";
}

Child Component HTML:

<p>
demo works!
</p>
<div>
  Data: {{ mydata }}
</div>

Child component TS:

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

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

  @Input() mydata;

  constructor() { }

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

}

ngOnInit() will run when the component is initialized and at that point, it is possible that the properties you have bind do not contain data from the parent component. Try ngOnChanges(), ngAfterViewInit()

On way to tackle is to use Observable and Subject.

8 Comments

No luck... ngOnChanges() is called sometimes but in all of them foo is undefined.
Still undefined
That is a very strange behaviour try removing protected
I turned it into public but still returns undefined
Ok, instead of passing as "'bar'" just pass "bar" i.e remove the extra single quotes
|
0

As mentioned by @Yash ngOnInit is the correct place to do that But you can add ngOnChanges and add a console.log there, it might be undefined at first but whenever input changes it goes to that so you might get the value later if it is coming at any point

ngOnChanges() {
console.log(this.foo)
}

2 Comments

No.. It remains undefined :(
can you please create a stackblitz with a similar issue
0

Have you tried using Observables instead? As far as I can see, your input might still be undefined when it is passed to that child component. @Input can be a little weird if you're not used to how it works.

2 Comments

I'm informing a defined string for foo but still returns undefined. As far as I understand it always be defined right?
Are you certain you have a value in foo when you pass it to your child? Perhaps you should remove the protected. There's no need for that in a component usually.
0

You can try implementing AfterViewChecked and see if you have value in ngAfterViewChecked like this:

@Component({
    selector : 'default-actions',
    templateUrl : './default.actions.template.html',
    styleUrls: [ './default.actions.style.scss' ],
    encapsulation: ViewEncapsulation.None,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class DefaultActionsComponent implements AfterViewChecked
{
    protected entityId;
    protected uuid = UUID.UUID();
    protected extraForms;

    @Input() protected data;
    @Input() protected structure;
    @Input() protected targetId;
    @Input() protected table;
    @Input() protected row;
    @Input() protected modal: ModalDirective;
    @Input() protected entity;
    @Input() protected entityObject: Entity;
    @Input() protected parentWrapper;
    @Input() protected foo;

    constructor(
        protected translate: TranslateService,
        protected activatedRoute: ActivatedRoute,
        protected actionService: DefaultActionsService,
        protected router: Router,
        protected entityService: EntityService,
        protected http: HttpAuthenticationService
    ) {}

    public ngOnInit() {
        console.log(this.foo);
    }

    ngAfterViewChecked() {
      console.log(this.foo);
    }

1 Comment

Still undefined =(
0

The undefined output generated because you use ChangeDetectionStrategy.onPush

OnPush works by comparing references of the inputs of the component. so in your case the object reference is always the same. so the OnPush change detector did not get triggered.

you can reference to this url for more explanations: https://blog.angular-university.io/onpush-change-detection-how-it-works/

1 Comment

I removed this line, no luck

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.