How should one correctly set up a property using the @Input decorator in Angular 2?

I have developed a custom component in Angular to manage my material autocomplete functionality for selecting an Action. I am passing the Action[] from the parent component to this component. The autocomplete feature is working correctly, but I am encountering an issue with my display name function. When trying to access this.actions inside the displayName function, I am receiving an error message "TypeError: Cannot read property 'filter' of undefined". After investigating further, I realized that this is because the this.actions array is empty within the displayName function. It seems like the actions property is not updating when the component loads the inputted value, causing it to remain stuck with the initial value. Despite this, the autocomplete component is functioning properly with the actions property. Is there a proper way to initialize the actions property so that it works effectively with my displayName() method?

import {Component, Input} from '@angular/core';
import {ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
import {Action} from '../../../../Interfaces/action';
import {Observable} from 'rxjs';
import {map, startWith} from 'rxjs/operators';

@Component({
  selector: 'app-input-action-typeahead',
  templateUrl: './input-action-typeahead.component.html',
  styleUrls: ['./input-action-typeahead.component.scss'],
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: InputActionTypeaheadComponent,
    multi: true
  }]
})
export class InputActionTypeaheadComponent implements ControlValueAccessor {

  @Input() actions: Action[] = [];
  filteredActions: Observable<Action[]>;
  actionCtrl = new FormControl();

  constructor() {
    this.filteredActions = this.actionCtrl.valueChanges.pipe(
      startWith(''),
      map(value => typeof value === 'string' ? value : value.name),
      map(action => action ? this._filter(action) : this.actions.slice())
    );
  }

  private _filter(value: string): Action[] {
    const filterValue = value.toLowerCase();
    return this.actions.filter(action => action.name.toLowerCase().indexOf(filterValue) !== -1);
  }

  registerOnChange(fn: any): void {
    this.actionCtrl.valueChanges.subscribe(fn);
  }

  registerOnTouched(fn: any): void {
  }

  writeValue(obj: Action): void {
  }

  displayName(id: number): string {
    if (!id) {
      return '';
    }
    return this.actions.filter(action => action.id === id)[0].name;
  }

  clear(): void {
    this.actionCtrl.setValue('');
  }

}

Answer №1

It seems like there might be an issue with accessing the actions variable value before it has been set. There are a couple of solutions to this problem:

Solution 1

Make sure to check if the actions variable has a value before attempting to read it.

 displayName(id: number): string {
    if(!!id && !!this.actions){
        return this.actions.filter(action => action.id === id)[0].name;
    }

    return '';
  }

Solution 2

Whenever change detection is triggered, your function displayName will be invoked, causing a slight performance overhead. To optimize this, you can calculate the display name in the actions setter instead of as a function that runs each time the mouse is moved. This approach involves more code but improves efficiency.

_actions: [];
get actions(): []{
    return this._actions;
}
set actions(value: []) {
     this._actions= value;
     this.updateDisplayName();
}

updateDisplayName(actions: []): void{
        // perform the necessary computations using the actions variable to determine the display name.
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Inheritance from WebElement in WebdriverIO: A Beginner's Guide

I am seeking a solution to extend the functionality of the WebElement object returned by webdriverio, without resorting to monkey-patching and with TypeScript type support for autocompletion. Is it possible to achieve this in any way? class CustomCheckb ...

Learn how to securely download files from an Azure Storage Container using Reactjs

I'm currently working on applications using reactjs/typescript. My goal is to download files from azure storage v2, following a specific path. The path includes the container named 'enrichment' and several nested folders. My objective is to ...

Angular sub-route is failing to activate

My current setup involves Angular routing along with the use of ngx-translate-router, and I've encountered an unusual issue with child routes. It's unclear whether this problem is connected to the translated router module I'm utilizing, but ...

What is the best way to retrieve an object when a value is not found? Consider implementing a looping mechanism with a specific condition in React and TypeScript to successfully

Greetings, I am faced with an array of objects structured as follows: const arr_obj = [ { id: '1', jobs: [ { completed: false, id: '11', run: { ...

What is the process for validating multiple check boxes using the reactive forms module?

I thought this would be a simple task, but I'm having trouble figuring it out. There are three checkboxes and I need to ensure that the user selects only one. The validator should check if any of the other two checkboxes have been selected and preven ...

Gatsby, in combination with TSC, does not properly transpile the rest operator

I'm attempting to integrate TypeScript with Gatsby following the guidelines provided here. However, I am encountering an issue where the tsc command is failing to transpile the spread (...) operator and producing the error shown below: WAIT Compili ...

Every time I try to install a particular version of angular using angular cli, it seems to result in the incorrect version

_ _ ____ _ ___ / \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _| / △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | | / ___ \| | | | (_| | |_| | | (_| | | | ...

Strategies for handling HTML content in the getProduct API call using Angular resolve

Components and Services Setup export class ProductComponent implements OnInit { constructor( private route: ActivatedRoute, private router: Router, ) { } ngOnInit() { this.route.data .subscrib ...

Mastering the Art of Typing a Function in TypeScript

I have a list of objects with an action field for each one, and I'm looking to simplify this field as follows: { id: '2', label: '', text: () => translate('MapAnnotation.Circle'), ic ...

PDFJS integration in Ionic 2

Looking for guidance on integrating pdfjs into an ionic2 project. Any suggestions on how to import and use it would be greatly appreciated. Thank you! I'm familiar with using pdfjs, but I'm having trouble figuring out how to bring it into my ion ...

Leveraging the npm package ssh2 in an Angular2 application operating within the Electron framework

My goal is to develop an Angular2 service utilizing the npm package ssh2 - https://www.npmjs.com/package/ssh2. After installing and configuring it, the code for my service can be found below. This code is based on the first example displayed on the ssh2 n ...

What is the process for implementing a type hint for a custom Chai assertion?

As part of my typescript project, I decided to create a custom assertion for the chai assertion library. Here is how I implemented it: // ./tests/assertions/assertTimestamp.ts import moment = require("moment"); import {Moment} from "moment"; const {Asser ...

Ionic 2 encountered an error: A non-empty string argument was anticipated

My goal is to show markers on a map using the stored postcode in JSON format. I have successfully accessed the lat and long values from the JSON data to display markers on the map. However, when I attempt to use the postcode, it fails and returns an erro ...

A different approach to handling multiple constructors in Angular 4

Angular 4 does not support having multiple constructors, so I need to find a cleaner way to instantiate my object. This is what my model looks like: export class SrcFilter { constructor(public firstList?: Array<String>, public secondList?: Arra ...

The validator function in FormArray is missing and causing a TypeError

I seem to be encountering an error specifically when the control is placed within a formArray. The issue arises with a mat-select element used for selecting days of the week, leading to the following error message: What might I be doing incorrectly to tri ...

Tips for troubleshooting a Typescript application built with Angular 2

What is the best approach for debugging an Angular 2 Typescript application using Visual Studio Code or other developer tools? ...

Enhancing Visuals with src="imageUrl within Html"

Is there a way to customize the appearance of images that are fetched from an API imageUrl? I would like to create some space between the columns but when the images are displayed on a medium to small screen, they appear too close together with no spacing. ...

When attempting to redirect to the home page in Angular 6, the page successfully redirects but fails to load properly

I am new to using angular. Recently, I converted a large project from html/css/php/js to twig/slim, and switched the hosting platform from apache2/sql to s3 buckets/lambda apis. While I have successfully converted smaller projects to angular without any i ...

Is there a way to verify the content inside the :before selector using Jasmine within an Angular 6 application?

Looking to test whether the content of a label changes based on the checkbox being checked using Jasmine in an Angular 6 project. Is this feasible? Code snippet: HTML <input id="myCheck" class="checkbox" type="checkbox" /> <label for="myCheck" ...

Angular shows nested values without considering dynamic keys

I need assistance with displaying user data retrieved from Firebase database. The JSON response I receive from Firebase starts with a dynamic value like "SivqCsErHQZNvGMe7p6r5nGknFy2". How can I skip this dynamic value and only show key/value pairs below? ...