Strategies for adding elements to a FormArray in Angular 4

I am currently working on a dynamic Angular form that displays like this.

 <form [formGroup]="myForm">
      <div *ngFor="let Repo of Repos;">
           <fieldset>
                <legend>{{Repo.name}}</legend>
                    <div class="checkbox checkbox-success">
                       <input
                            [id] = "Repo.id"
                            type="checkbox"   (change)="onChange(Repo.User,Repo.Commits,Repo.Requests,Repo.Contributors, Repo.Languages,Repo.Branches,Repo.Langs,$event.target.checked)">
                              <label [for] = "Repo.id">
                                 Select This Repository
                              </label>
                     </div>
            </fieldset>
       </div>
 </form>

Below is the TypeScript file provided:

export class AddUserComponent implements OnInit {
      githubUserResponse;
      githubReposResponse;
      myForm = new FormGroup({});
    ngOnInit(){
       this.myForm = new FormGroup({
            'userRepoData' : new FormGroup({
              'githubusers': new FormGroup({
                'username': new FormControl(null),
                'html_url': new FormControl(null),
                'name': new FormControl(null),
                'company': new FormControl(null),
                'location': new FormControl(null),
                'user_created_at': new FormControl(null),
                'user_updated_at': new FormControl(null),
                'public_repos': new FormControl(null),
                'public_gists': new FormControl(null),
                'githubrepos': new FormArray([]),
              }),
            }),
          });
    }
onChange(repo, commits, requests, contributors, branches, langs,  isChecked: boolean){
        if (!isChecked) {
         console.log('aayaa');
         (<FormArray>this.myForm.get('userRepoData.githubusers.githubrepos')).push(
           new FormGroup({
             'owner': new FormControl(repo.owner.login),
             'name': new FormControl(repo.name),
             'html_url': new FormControl(repo.html_url),
             'clone_url': new FormControl(repo.clone_url),
             'repo_created_at': new FormControl(repo.created_at),
             'repo_updated_at': new FormControl(repo.updated_at),
             'repo_pushed_at': new FormControl(repo.pushed_at),
             'public_repos': new FormControl(repo.public_repos),
             'no_of_commits': new FormControl(commits.length),
             'no_of_branches': new FormControl(branches.length),
             'no_of_pullrequests': new FormControl(requests.length),
             'no_of_contributors': new FormControl(contributors.length),
             'repobranches': new FormArray([]), //empty
             'repocommits': new FormArray([]), //empty
             'repocontributors': new FormArray([]), //empty
             'repolangs': new FormArray([]), //empty
             'repo_p_rs': new FormArray([]) //empty
           })
         );
         console.log(this.myForm.value);
  }
}

In the above FormGroup, there are empty FormArrays:
1. repobranches
2. repocommits
3. repocontributors
4. repolang
5. repo_pr_s
that I need to populate with data.

For example, here's an array I want to push to 'repocontributors':

[
                    {
                        "login": "Saurabh0606",
                        "id": 21239899,
                        "avatar_url": "https://avatars2.githubusercontent.com/u/21239899?v=4",
                        ...
                    },
                   {
                        "login": "Saurabh0707",
                        "id": 21239898,
                        "avatar_url": "https://avatars2.githubusercontent.com/u/21239898?v=4",
                        ...
                    }
                ]   

Please guide me on how I can achieve this for other FormArrays as well.
Any help will be greatly appreciated. Thank you in advance.

Answer №1

According to Imran's suggestion, I also advise utilizing the FormBuilder:

ngOnInit() {
  this.myForm = this._fb.group({
    userRepoData: this._fb.group({
      githubusers: this._fb.group({
        username: null,
        html_url: null,
        name: null,
        company: null,
        location: null,
        user_created_at: null,
        user_updated_at: null,
        public_repos: null,
        public_gists: null,
        githubrepos: this._fb.array([
          this._fb.group({
            owner: 'repo.owner.login',
            name: 'repo.name',
            html_url: 'repo.html_url',
            clone_url: 'repo.clone_url',
            repo_created_at: 'repo.created_at',
            repo_updated_at: 'repo.updated_at',
            repo_pushed_at: 'repo.pushed_at',
            repocontributors: this._fb.array([]), //empty
            repolangs: this._fb.array([]), //empty
          })
        ]),
      })
    })
  });
}

then simply employ the push() method to add to your array:

pushToArray() {
  const repocontributors = this.myForm.get('userRepoData.githubusers.githubrepos.0.repocontributors');
  (repocontributors as FormArray).push(this._fb.group({
    login: "Saurabh0606",
    id: 21239899,
    avatar_url: "https://avatars2.githubusercontent.com/u/21239899?v=4",
    gravatar_id: "",
    url: "https://api.github.com/users/Saurabh0606",
    html_url: "https://github.com/Saurabh0606",
    followers_url: "https://api.github.com/users/Saurabh0707/followers",
    following_url: "https://api.github.com/users/Saurabh0707/following{/other_user}",
    gists_url: "https://api.github.com/users/Saurabh0707/gists{/gist_id}",
    starred_url: "https://api.github.com/users/Saurabh0707/starred{/owner}{/repo}",
    subscriptions_url: "https://api.github.com/users/Saurabh0707/subscriptions",
    organizations_url: "https://api.github.com/users/Saurabh0707/orgs",
    repos_url: "https://api.github.com/users/Saurabh0707/repos",
    events_url: "https://api.github.com/users/Saurabh0707/events{/privacy}",
    received_events_url: "https://api.github.com/users/Saurabh0707/received_events",
    type: "User",
    site_admin: false,
    contributions: 2
  }));

  (repocontributors as FormArray).push(this._fb.group({
    login: "Saurabh0707",
    id: 21239898,
    avatar_url: "https://avatars2.githubusercontent.com/u/21239898?v=4",
    gravatar_id: "",
    url: "https://api.github.com/users/Saurabh0707",
    html_url: "https://github.com/Saurabh0707",
    followers_url: "https://api.github.com/users/Saurabh0707/followers",
    following_url: "https://api.github.com/users/Saurabh0707/following{/other_user}",
    gists_url: "https://api.github.com/users/Saurabh0707/gists{/gist_id}",
    starred_url: "https://api.github.com/users/Saurabh0707/starred{/owner}{/repo}",
    subscriptions_url: "https://api.github.com/users/Saurabh0707/subscriptions",
    organizations_url: "https://api.github.com/users/Saurabh0707/orgs",
    repos_url: "https://api.github.com/users/Saurabh0707/repos",
    events_url: "https://api.github.com/users/Saurabh0707/events{/privacy}",
    received_events_url: "https://api.github.com/users/Saurabh0707/received_events",
    type: "User",
    site_admin: false,
    contributions: 2
  }));
}

STACKBLITZ: https://stackblitz.com/edit/angular-ntx3sp?file=app%2Fapp.component.ts

Simply click on PUSH TO FORM ARRAY BUTTON.

This is how it appears before pushing: https://i.sstatic.net/l3jfw.png

and hereafter:

https://i.sstatic.net/caVN7.png

Answer №2

When dealing with an array like githubrepos, you will need to access a specific element within that array. Assuming we want to work with repobranches at index 0, you can create a new FormGroup and populate it with the desired values (such as variable.login)

var reposControl = (<FormArray>this.myForm.get('userRepoData.githubusers.githubrepos')).at(0);
var repoBranches = <FormArray>reposControl.get('repobranches');

repoBranches.push(new FormGroup({
  "login": new FormControl(variable.login),
  ...
}))

Answer №3

Start by creating your own form building tool, then insert the existing array value into the 'repocontributors' key of your form data.

this.userForm = this._formBuilder.group({
   ...................
   ................
  'repocontributors': [yourArray]
});

Take a look at this example to see how to construct a form builder using reactive forms. Avoid using onChange() and make sure to use submit instead

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

Angular - Implementing *ngFor for nested table rows

I am currently working with an object that has a specific data structure: - title - id - [artists] - { artist obj / document , - [albums] - { album obj / document }, - { - album obj / document ...

Using Angular to transmit data to a transcluded component

Is it possible to have a video-uploader component where users can upload one or multiple videos, with the ability to choose from three different view options: Seperate - In progress videos and uploaded videos are displayed in separate tables. Combine ...

What is the best way to locate this particular element on the webpage?

After using the right-click and selecting inspect element, I located the code of the desired element on the webpage: <input type="text" ng-if="!editing" ng-model="item.Price" ng-click="inputFocus()" ts="" required="" placeholder="قیمت :" class="ng- ...

Displaying dynamic key-value pairs in each row of an Angular mat-table

I need help displaying a key-value pair data in JSON format dynamically within a table using Angular mat-table. The keys will vary, so there is no set list of keys that will be included in the JSON. This is an example of the data: var data = { "cars" : 2 ...

An effective approach to automatically close an Expansion Panel in an Angular Mat when another one is opened

I am attempting to implement functionality where one expansion panel closes when another is opened. By default, the multi attribute is set to "false" and it works perfectly when using multiple expansion panels within an accordion. However, in this case, I ...

Issue encountered during the upgrade to Angular version 12: The specified root path is undefined and does not correspond to any file in the program

During the process of upgrading my Angular 11 app to version 12, I encountered an error after running ng update @angular/core@12 @angular/cli@12 and then executing yarn start. The error that appeared can be found here: [Error After Run Angular in version 1 ...

Properly implement Angular/Typescript to populate an array with chosen objects

Currently, I have an Angular application that is fetching JSON resources from a Spring Boot REST API. These resources consist of simple player objects with attributes like id, name, position, and value. On the UI, each object is displayed along with a "BUY ...

Solving Checkbox Change Event Issue in Angular

I'm having difficulty testing the checkbox-change event for a particular component. Here is the code for the component that needs to be tested: import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: &a ...

Undefined error encountered in the Google Places library

I'm new to working with the Ionic framework and was experimenting with implementing an autocomplete search feature using the Google Maps API. After going through several resources, I included the following code: <script type="text/javascript" src ...

Leverage the power of Angular 2 components within your Asp.net MVC

I am currently working on an Asp Mvc project which utilizes Angular 1.4 for the frontend. While my project is not designed to be a single page application, I am interested in incorporating Angular 2 without transitioning the entire project into a SPA. Aft ...

Exploring the Relationship Between Redux and ImmutableJS in Managing Nested State and Understanding the Computational Complexity of Immutable

Trying to grasp the concept of Immutability for my debut Redux (NGRX/Store) endeavor has been quite the challenge. Avoiding state mutation has been a struggle, especially while dealing with Object.assign({}) and state mutation errors. Thankfully, I stumble ...

Receiving an error while passing properties to a React component: "Property 'firstName' is not found on type 'Readonly<{}>'."

As a beginner in React, I need some patience I'm attempting to create a simple component where users can input their first and last names, update the values, and see them displayed after clicking a button. However, I keep encountering TypeScript comp ...

What would be a colloquial method to retrieve the ultimate result from the iterator function?

I've got a rather complex function that describes an iterative process. It goes something like this (I have lots of code not relevant to the question): function* functionName( config: Config, poolSize: number ): Generator<[State, Step], boo ...

Ensuring the image is properly sized to fit the screen and enabling the default zoom functionality

I am looking to achieve a specific behavior with an image, where it fits the viewport while maintaining its aspect ratio and allowing for zooming similar to how Chrome or Firefox handle local images. Here are the details of my project: The image I have is ...

The Angular overlay is concealed beneath the pinned header

I am seeking a solution to have a mat-spinner displayed on top of my app while it is in the loading state. Currently, I am using an overlay component with Overlay from @angular/cdk/overlay. The issue arises when part of the spinner that should be overlai ...

Is there a method to define an 'internal' property within a TypeScript type?

I created a custom 'library' in Angular and TypeScript. This library is distributed as a *.ts package within other Angular workspaces. Within this library, I have an exported class that contains various properties. One specific property in thi ...

What is the best way to dynamically change the main content based on the sidebar option chosen in a React application?

Currently, I am in the process of creating the layout for the page similar to the image provided. When a user selects option A from the sidebar, my goal is to display the corresponding content on the same page without navigating to a new one. This projec ...

Create a TypeScript function that can be called and has an extended prototype definition

I am seeking to create a callable function foo() (without using the new operator) that will also include a property foo.bar(). The JavaScript implementation would be as follows: function foo() { // ... } foo.prototype.bar = function bar() { // .. ...

Create a function that takes advantage of a Promise to resolve its actions

In the asynchronous function provided below: export default async function getUserNames(id: string[]): Promise<string[]> { let userNames: string[] = []; // Additional actions such as service calls are performed here... return userNames; ...

An effective method for targeting a specific button within a CSS file

I have multiple button tags in my code, but I need to style a specific one using CSS. How can I target this particular button and apply styles only to it while leaving the others unchanged? Do I need to assign the button to a variable and reference that va ...