Connect the child content to the form

Are there any methods to connect a projected template (ContentChild) to the form specified on the child, such as adding formControlName after it has been rendered?

I am having difficulty in finding relevant information online, possibly due to using incorrect search terms.

Example without projection - currently functional

Below is an example of a form array linked to a control value accessor,
The component contains a form group with type

FormGroup<{ formArray: FormArray<{ formControl : FormControl }> }

however, when emitting value changes, only the array of values is sent i.e.
formValue.formArray.map(v => v.formControl)

So, formArray and formControl are simply internal names within the component.

Specific example

<fieldset [formGroup]="formGroup">
    <legend>Paving runs (minimum 1)</legend>

    <ng-container formArrayName="formArray">
        <fieldset *ngFor="let frmGrp of formGroup.controls.formArray.controls; let i = index">
            <legend>Paving run</legend>
            
            <ng-container [formGroup]="frmGrp">
                <paving-run-form
                    formControlName="formControl">
                </paving-run-form> 
            </ng-container>

            <button (click)="remove(i)">Delete run</button>
        </fieldset>
    </ng-container>
    
    <button (click)="add()">Add run</button>
</fieldset>

This structure is standard and effective, but I am now attempting to create a reusable component version.

My goal is to achieve something like this:

<generic-form-array formControlName="paved_runs" [labels]="labels">
    <ng-template editMode>
        <paving-run-form></paving-run-form>
    </ng-template>
</generic-form-array>

In this case, 'labels' would be defined as follows:

@Input() labels: GenericFormArrayOptions = {
    legendMany: "Paving runs (minimum 1)",
    legendOne: "Paving run",
    deleteOne: "Delete run",
    addOne: "Add run",
}

Projected example - my attempted solution

<fieldset [formGroup]="formGroup">
    <legend>{{ labels.legendMany }}</legend>

    <ng-container formArrayName="formArray">
        <fieldset *ngFor="let frmGrp of formGroup.controls.formArray.controls; let i = index">
            <legend>{{ labels.legendOne }}</legend>
                
                    <ng-container [formGroup]="frmGrp">
                        <!-- project the form to edit one of array elements -->
                        <ng-container
                          [ngTemplateOutlet]="editModeTpl.templateRef">
                        </ng-container>
                    </ng-container>

            <button (click)="remove(i)">{{ labels.deleteOne }}</button>
        </fieldset>
    </ng-container>
    
    <button (click)="add()">{{ labels.addOne }}</button>
</fieldset>

The following is specified within the class:

@ContentChild(EditModeDirective) editModeTpl!: EditModeDirective

Here, the content is being projected correctly, however,

<paving-run-form></paving-run-form>
is not connected to the child form. Trying
<paving-run-form formControlName="formControl"></paving-run-form>
does not work because it expects formControl to be on the parent element instead.

Is there a way to render the component first and then attach it to the child form afterwards?

Answer №1

It's quite common for me to figure out the solution right after posing the question...

Within the reusable component, I must pass the form group through the context

<ng-container
    [ngTemplateOutlet]="editModeTpl.templateRef"
    [ngTemplateOutletContext]="{formGroup: frmGrp}">
</ng-container>

And when utilizing it as a customer, I need to execute the following:

<generic-form-array formControlName="paved_runs">
    <ng-template editMode let-formGroup="formGroup">
        <paving-run-form [formControl]="formGroup.get('formControl')"></paving-run-form>
    </ng-template>
</generic-form-array>

Credit goes to @Eliseo for providing a helpful comment on a question that seems to have disappeared from view :)

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

What is the process for loading the chosen option JSON object from an array when a button is clicked?

I have a TypeScript file containing JSON objects that can be selected as options from a dropdown list. I am looking for guidance on how to load/instantiate the selected JSON object when the user clicks a button to proceed. Specifically, I would like to le ...

Tips for handling delayed HTTP API responses in Angular

While working on my project, I encountered a delay in response when using the this.ServiceHandler.getTxnInfo([], params) API. To handle this, I implemented the use of setTimeout along with async/await. Despite these modifications, my promise ended up being ...

What is the method for reaching a service in a different feature module?

Currently, I am utilizing Angular 2/4 and have organized my code into feature modules. For instance, I have a Building Module and a Client Module. https://i.stack.imgur.com/LvmkU.png The same structure applies to my Client Feature Module as well. Now, i ...

All authentication logic in Angular encapsulated within the service

I am considering moving all the business logic into the auth service and simply calling the method on the component side. Since none of my functions return anything, I wonder if it's okay or if they will hang. COMPONENT credentials: Credentials = ...

What causes the inconsistency in the form input value when it is disabled?

I have encountered an issue while working on an Angular input component in StorybookJS. The problem arises when I enter a value (e.g., hello) in the Control Panel in Storybook JS and set disabled to true. The input text becomes disabled and displays the te ...

Discovering new bugs in VSCode Playwright Tests but failing to see any progress

This morning, everything was running smoothly with debugging tests. However, after a forced reboot, I encountered an issue where it seems like the debugger is running, but nothing actually happens. This has happened before, but usually resolves itself. Unf ...

deliver a promise with a function's value

I have created a function to convert a file to base64 for displaying the file. ConvertFileToAddress(event): string { let localAddress: any; const reader = new FileReader(); reader.readAsDataURL(event.target['files'][0]); reader ...

Can an Angular 5 web application be developed without using Node.js/npm?

I want to develop an Angular 5 web application using Java, but my boss prefers not to use Node.js/npm. Is it possible to build an app without Node.js/npm and rely solely on Java? Most of the resources I've come across recommend using Node.js/npm, inc ...

The implementation of async await within a switch case statement is failing to function properly

Is it possible to wait for the resolution of a promise within a switch case statement by using the keyword await? I am facing an issue with my Angular component where the following code is causing crashes in my application. switch (this.status) { ...

Error encountered while implementing onMutate function in React Query for Optimistic Updates

export const usePostApi = () => useMutation(['key'], (data: FormData) => api.postFilesImages({ requestBody: data })); Query Definition const { mutateAsync } = usePostApi(); const {data} = await mutateAsync(formData, { onMutate: ...

What is the purpose of declaring data types such as string, number, boolean, void, and others in Angular 2

I'm curious as to why programmers declare classes in individual scope or something. For example, take a look at this code snippet: result: boolean = false public generateRand(x): void { } This is also similar to the following: result = false publi ...

Issue with Angular 7 cli failing to recognize a custom TypeScript file

While working on an Angular 7 component, I encountered an issue when trying to read a custom file. The problem arises when the server restarts, even though there are no errors in the component's TypeScript file. ERROR: app/zontify-components/zonti ...

Error: The specified path in the MEAN stack must be either a string or Buffer

I am currently utilizing Angular 5 on the front-end, Node for back-end operations, and MongoDB as the database. My current challenge involves attempting to save an image to the database, but I keep encountering an error. Determining whether the issue lies ...

Issues with CSS styling inheritance in Angular components

I'm facing an issue with a button that is part of an InfoWindow component. The button is not created in the HTML code directly but is called whenever the card component opens. I have integrated this InfoCard into two different sections of the applicat ...

Is it possible to eliminate the port number in Angular 7?

Currently, I am utilizing Angular in conjunction with an ASP.Net Web application. One interesting observation I've made is that when I use ng build, the app builds and runs on a URL without any port number. However, if I run the app using ng serve, it ...

A guide on iterating through a JSON object fetched using Http in Angular 2/Typescript

I am attempting to extract specific data from my JSON file using http. The structure of the JSON is as follows: [{"name":"Name1","perc":33},{"name":"Name2","perc":22},{"name":"Name3","perc":41}] To loop through this retrieved object, I use the following ...

Delete the text in MUI's TablePagination component that displays the number of rows per page and the total rows in the table

Currently, I am integrating MUI's tablePagination component into my React table with TypeScript. I am looking to remove/disable the circlemarked text displayed in the image (the picture is an example from MUI). https://i.stack.imgur.com/ib0t2.png Af ...

Display captions on react-player videos using an .srt file

Currently, I am working on a React/Typescript project with Next.js. A key feature of this project is a modal that utilizes 'react-player' to display videos. While the video and modal are functioning as intended, I am looking to incorporate capti ...

What is the best way to optimize a search for objects with extensive field arrays?

Recently, I've been working with an object schema that includes an array field to store ids for objects from a separate collection. This array has the potential to contain thousands of ids. Up until now, I have been excluding this field using .select( ...

Cross-origin resource sharing policy is rejecting the specified white-listed address in the CORS policy with the .WithOrigins

Despite having white-listed the origin http://localhost:4200/ in Startup.cs, Cors is still rejecting the request. This issue persists when making a GET request to my API and attempting to establish a connection through SignalR. Although I can bypass Cors ...