"Encountering an issue with HTML due to the utilization of union types within

I am currently working on creating a form generator component, and I have designed the form field class as shown below:

export type FormField<T, TDropDown = any> =
  | InputFormField<T>
  | DropdownFormField<TemplateStringsArray, TDropDown>;

export interface InputFormField<T> {
  key: Extract<keyof T, string>;
  type: 'string' | 'date' | 'number';
}

export interface DropdownFormField<T, TDropDown> {
  type: 'dropdown';
  key: Extract<keyof T, string>;
  dropdownItems: Observable<TDropDown[]>;
  dropdownItemTitleKey: keyof TDropDown;
  dropdownItemValueKey: keyof TDropDown;
}

There are two types of form fields in this design. If the type of the form field is dropdown, then dropdown items must be filled, otherwise, those fields are not necessary.

In the HTML file, I have implemented this type as follows:

<div *ngFor="let item of formFields" nz-col nzXs="24" nzMd="12" nzLg="8">
  <nz-form-item>
    <nz-form-label>
       {{ item.key }}
    </nz-form-label>
    <nz-form-control>
      <ng-container [ngSwitch]="item.type">
        <nz-select
          *ngSwitchCase="'dropdown'"
          [formControlName]="item.key"
          nzShowSearch
        >
          <nz-option
            *ngFor="let option of item.dropdownItems | async"
            [nzLabel]="option[item.dropdownItemTitleKey]"
            [nzValue]="option[item.dropdownItemValueKey]"
          ></nz-option>
        </nz-select>
      </ng-container>
    </nz-form-control>
  </nz-form-item>
</div>

Even though I used *ngSwitchCase="'dropdown'" to ensure that the item is a dropdown item, I am still encountering this error:

Property 'dropdownItems' does not exist on type 'SarmadInputFormField<T>'

What is the proper way to define a form field class and use it inside a component's HTML file?

Answer №1

At this moment, Angular's template system does not have the capability to downcast types. This means that even if you utilize the *ngSwitchCase directive, Angular may struggle to identify the correct subtype within a union type.

In a TypeScript file (.ts), you could employ the as keyword for downcasting. However, this functionality is not accessible within the template syntax.

To address this issue, one workaround is using the $any() function, which is provided by Angular specifically for scenarios where the template's type does not perfectly align with the actual data type.

To implement this solution, modify your code as shown below:

*ngFor="let option of $any(item.dropdownItems | async)"

To learn more about the $any() function, refer to the documentation available here.

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

Retrieve the value of a child variable within a parent button's action event

Is there a way to access the value of a child variable from a parent button click? child component @Component({ selector: 'app-child-panel', templateUrl: './child-panel.component.html', styleUrls: ['./child-panel.component.sc ...

What is the most effective method for designing a scalable menu?

What is the most effective way to create a menu similar to the examples in the attached photos? I attempted to achieve this using the following code: const [firstParentActive, setFirstParentActive] = useState(false) // my approach was to use useState for ...

When {} = {} is utilized in an Angular constructor, what is its function?

While going through an Angular dynamic forms tutorial, I came across this code snippet and got confused by the {} = {} in the constructor. Here is the complete snippet: export class QuestionBase<T> { value: T; key: string; label: string; re ...

One component in Angular 4 facing difficulty in invoking a function from another component

I am currently working on incorporating a side navigation for a datatable in Angular 4. Here is the code snippet I have for this implementation: <mat-sidenav-container class="example-container"> <mat-sidenav #sidenav mode="over" position=" ...

What steps should be taken to guarantee that the view is created only after receiving values from the route params subscription?

How can I ensure that the View is only rendered after the subscription has received values? When clicking on the Edit button in MyComponent_1, Angular navigates to MyComponent_2. In MyComponent_2, the view contains a form whose values are dependent on rout ...

Configuring the CKEditor edit functionality in Angular 2

If you're looking to configure your CKEditor in Angular2, you can refer to the documentation provided by CKEditor here. Here is an example of how I am using it in my HTML: <ckeditor [(ngModel)]="ckeditorContent" [config]="{toolbar : 'Bas ...

Dynamically apply classes in Angular using ngClass

Help needed with setting a class dynamically. Any guidance is appreciated. Below is the class in my SCSS file: .form-validation.invalid { border: 2px solid red } In my ts file, there's a variable named isEmailValid. When this variable is set to ...

Resetting clears the date default value

When the page is loaded, the date input field is automatically set to the current date. However, if the form is reset, instead of restoring the default date, the date field is cleared, as shown in the images below: Page load Form reset // app.component. ...

Changing the left border color dynamically based on the value of an object within a loop

My objective is to achieve a design where the left border of the cards appears as shown in the image below: https://i.sstatic.net/nsVeJ.png The loop structure is as follows: <ion-card *ngFor="let office of searchItems" class="custom" ...

Is there a way for me to receive a success message when I successfully set data in Firebase?

I want to retrieve the orderId after successfully adding an order to the Realtime database using angularfirestore. What should I use after set() method to return the orderId? The structure of my order object is as follows: const orderObj: Order = { pay ...

Troubleshooting: Resolving JSX props issue in Vue template

Ever since integrating the FullCalendar library into my Vue project, I've been encountering an error every time I try to use my custom component in a Vue template. My setup includes Vue 3, Vite, VSCode, eslint, and prettier. This issue seems to be m ...

Surprising outcome caused by introducing a service dependency within another service in Angular 6

In my current project, I am facing an issue with ngrx-store and Angular 6. Unfortunately, I cannot replicate the problem on the stackblitz, so I will explain it here. I have a Service1 being used in the component, as well as a Service2 that is used within ...

Using ngFor and click function in Ionic and Angular

Recently, I delved into the world of Ionic and started working on an app that features a unique 'dictionary' functionality. The app allows users to press a button to hear either an English or German translation of a Dutch word through an audio fi ...

Click on the HTML page to load an Array of Arrays containing strings

Earlier, I posted a topic about an issue with Observable loading on an HTML page: Observable need a click to load on html page. Unfortunately, I am still facing the same display problem where I have to click on the input field to display the content of a ...

The navigation bar text overflows when the sidebar is collapsed into icons

My sidebar contains icons and a menu name. When the screen size is smaller than a certain amount, the sidebar collapses to show only the icon and hides the menu name. Here is the structure of the navbar: <nav id="sidebar" [ngClass]="{active: barActive} ...

Proper format for implementing recursive API call in React using Redux-Thunk

Our goal is to create a recursive API call based on the number of records returned in the response. For instance, if the response contains 10 records out of a total of 20, we should make another API call for the next 10 records. What is the best approach ...

Angular 2 Service's filtering functionality can be enhanced with an Array parameter

I developed a function to retrieve filtered results from a JSON dataset. getItem(id: string): Observable<any[]> { return this.http.get('path/to/my.json') .map((response) => { let results: any = response.json( ...

Having trouble with your Router Guard?

Currently, I find myself in a predicament with a CanActivate router guard. The use of these guards is resulting in an undesired reload of the entire page. After implementing two different versions of the guard, I have encountered a behavior that I cannot ...

The inability to destructure the 'store' property from the 'useReduxContext(...)' because of its null value

I am currently using NextJs 13 along with redux toolkit. Whenever I run the npm run build command, I encounter this error: "Cannot destructure property 'store' of 'useReduxContext(...)' as it is null." I suspect that the issue lies wi ...

Securing Django URLs with bearer tokens generated by Angular Azure AD

I am facing a specific scenario where my application is developed with Django and Angular handling the UI and backend, respectively. The Angular interface utilizes Azure AD for user authentication, generating a bearer token upon login. On the other hand, ...