2

I have a little problem and I am not sure what the issue is, perhaps someone here can help?

In my Angular App I have a component that contains a child directive that is attached to form inputs. This child directive takes an @Input() which is a string array called errors.

So in the parent HTML template we have something like so...

<!-- parent-component.component.html file -->
<input type="text" myDirectiveName [errors]="errors">

I want it so that when the errors sting array value changes this change is detected in the directive. I always thought that @Inputs() are treated as Observables so in the parent component I did the following (I have reduced the code for simplicity)

@Component({
  selector: 'parent-component',
  templateUrl: './parent-component.component.html',
  styleUrls: ['./parent-component.component.scss']
})
export class ParentComponent implements OnInit {
    
    // declare the errors string array
    errors = [];

    ngOnInit(): void {
        this.getErrors();
    }

    getErrors(): void {
        setInterval(() => {
          if(this.errors.length > 3) {
            this.errors.length = 0;
          } else {
            this.errors.push('This is an error');
          }
        }, 1000);
    }
}

I thought this would automatically update in my @Input but it does not, even though if I write the errors array to parent interface in the parent-component.component.html file using {{ errors | json }} I can see the array increase and shrink over time.

So, I thought I will use ngOnChanges within my Directive to capture the changes, here is some simplified code:

@Directive({
  selector: '[myDirectiveName]'
})
export class errorDirective implements OnInit, OnChanges {

@Input() errors: string[];

ngOnInit() {
// do stuff...
}

ngOnChanges(simpleChange: any) {
    console.log(simpleChange);
  }
}

Using this code I can see the changes being output as the Input is initialized but not when I change the value later in the parent. Is the problem how I am changing my errors array using setTimeout? I'm really confused why I can't capture the changes via the Directive Input()? If anyone can help me understand what I am doing wrong I would be most appreciative.

Also if my wording is confusing or wrong please add a comment and I shall reword/rework this question.

4
  • You are missing an @Input() decorator on errors in your component Commented Jul 27, 2021 at 17:14
  • 1
    You're mutating the errors array. Try to update it immutable. Commented Jul 27, 2021 at 17:23
  • why are you adding your component to a input tag? <input type="text" myDirectiveName [errors]="errors">. shouldn't it be use like a tag such as <myDirectiveName [errors]="errors"></myDirectiveName> ?? Commented Jul 27, 2021 at 17:36
  • 1
    I have just added an example for you. please take a look if it solves your problem stackblitz.com/edit/… Commented Jul 27, 2021 at 17:37

1 Answer 1

1

Errors is an array, which is an object i.e. immutable. for inputs to detect changes in ngonchanges you have to assign a new reference to array. one of the way is to create shallow copy by using spread operator where ever are are adding or removing any value from array.

this.errors.push('new error');
this.errors = [...this.errors];
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.