Observing changes in a parent component variable with Angular

One feature of my form is that it consists of a parent component and a child component.

To disable a button within the form, I utilize a function called isDatasetFilesValid() which checks a specific variable (datasetList[i].fileValid). This variable is modified within the child component.

The issue arises when this modification takes place within a callback during file parsing using papaparse. Due to this being done in a callback, the parent component does not immediately register the change. This is evident as if the variable is altered outside the callback, the button becomes available.

This particular variable acts as an indicator to ensure a file has been selected.

I attempted to include "detectChanges()" in order to resolve this, but unfortunately, it did not yield the desired outcome.

Parent component:

   export class ExperimentCreateComponent implements OnInit {

     datasetList: any = [{ fileValid: false }];

     isDatasetFilesValid() {
       let index = this.datasetList.findIndex(function(item, i) {
       return item.fileValid == false;
       });
      let test = index === -1 ? true : false;
      console.log("Dataset", index + " -> " + test);
      return test;
      }
    }

Parent html:

<div class="jumbotron">
  <div class="container">
    <div class="row">
      <div class="col-sm-8 offset-sm-2">

        <form name="form" (ngSubmit)="f.form.valid" #f="ngForm" novalidate>


              <app-creation-dataset [datasetList]="datasetList"></app-creation-dataset>

                <button mat-button color="primary" type="submit" [disabled]="!isDatasetFilesValid()" (click)="createExperiment()">Submit</button>


        </form>
      </div>
    </div>
  </div>
</div>

Child Component:

export class CreationDatasetComponent implements OnInit {
  @Input() datasetList: any = [{ fileValid: false }];
  fileSelected: File;


  constructor(private papa: Papa, private cd: ChangeDetectorRef) {}

  ngOnInit() {}

  onChange(files: FileList, index: number, dom: any) {
    // Option to parse the file with papaparse
    let options = {
      header: true,
      error: (err, file) => {
        this.datasetList[index].fileValid = false;
        alert(
          "Unable to parse CSV file, please verify the file can be accessed and try again. Error reason was: " +
            err.code
        );
        return;
      },
      complete: (results, file) => {
        console.log("Parsed:", results, file);
        let filename = file.name;

        // Add the dataset to the datasetList
        this.datasetList[index].headers = results.meta.fields;
        this.datasetList[index].values = results.data;
        this.datasetList[index].filename = filename;
        this.datasetList[index].is_metadata = false;
        this.datasetList[index].fileValid = true;
        this.cd.detectChanges();
      }
    };
    this.fileSelected = files[0]; // Get the file
    // Call the function to parse the file, option is the callback
    this.papa.parse(this.fileSelected, options);
  }
}

Child HTML:

<div *ngFor="let dataset of datasetList; let index = index">
  <div id="datasetFiles">
    <h6>Select the type of dataset and browse the files:</h6>
    <div class="container">
      <div class="row justify-content-between">
        <div class="col-6 d-flex align-items-center">
          <input id="file" #file (change)="onChange(file.files, index, $event.currentTarget)" type="file">
        </div>
      </div>
    </div>
  </div>
</div>
<div>

Answer №1

If the parent detects changes when they occur outside of the callback but not inside, it could be a context issue.

Give this a try:

onChange(files: FileList, index: number, dom: any) {

    var that = this; // outer scope

    let options = {
      header: true,
      error: (err, file) => {
        this.datasetList[index].fileValid = false;
        alert(
          "Unable to parse CSV file, please verify the file can be accessed and try again. Error reason was: " +
            err.code
        );
        return;
      },
      complete: (results, file) => {
        console.log("Parsed:", results, file);
        let filename = file.name;

        this.datasetList[index].headers = results.meta.fields;
        this.datasetList[index].values = results.data;
        this.datasetList[index].filename = filename;
        this.datasetList[index].is_metadata = false;
        that.datasetList[index].fileValid = true;
        this.cd.detectChanges();
      }
    };
    this.fileSelected = files[0]; 
    this.papa.parse(this.fileSelected, options);
  }

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

Discovering the most recent messages with AJAX

I'm feeling a bit lost on this topic. I'm looking to display the most recent messages stored in the database. (If the messages are not yet visible to the user) Is there a way to achieve this without constantly sending requests to the server? (I ...

Utilizing Discord.js to Transfer Users Between Voice Channels

Does anyone know the most updated method for creating a discord js bot that can move users to different voice channels? I've been encountering errors with the solutions I found online. Currently, I'm manually setting it to a specific channel for ...

Tips for developing a strongly-typed generic function that works seamlessly with redux slices and their corresponding actions

Currently, I am working with @reduxjs/toolkit and aiming to develop a function that can easily create a slice with default reducers. Although my current implementation is functional, it lacks strong typing. Is there a way to design a function in such a man ...

Validating Laravel emails with JavaScript blur and utilizing AJAX and jQuery

Looking for a way to validate a form in Laravel without hitting the submit button? I've tried some code, but only the email format validation seems to be working. Any tips on what I should do next? I'm new to Ajax. PS: When I enter a valid email ...

Having trouble resolving modules with Angular 2 and ASP.NET 5 (unable to locate angular2/core)?

I am diving into a fresh ASP.NET5/MVC6 project and facing some challenges along the way. Struggle 1 When I opt for classic as the moduleResolution in my tsconfig.json, I encounter an error stating: Cannot locate module 'angular2/core' Strugg ...

What is preventing Apollo from achieving full transformation?

I have been struggling with an issue involving Apollo mutation for the past 2 days. Whenever I call a mutation on Angular Apollo generated code and subscribe to it, the subscription never completes. I am expecting a result from the server, but nothing is ...

Utilizing Interface Merging: Determining the Appropriate Instance Type for Field Types

I am in need of writing a definition file for an external library. I have augmented a class using interface merging and there are situations where a field of the library class is of the same type as the instance itself. Here is a snippet of demo code: // ...

Switching the dialogue with no need for a refresh

I am working on a feature for my website where I want to switch the language seamlessly without having to reload the page when a user clicks on one of three language flags (German, French, and English). When a flag is clicked, I store a cookie called lang ...

Can you elaborate on the users object found in the npm registry JSON response?

When looking at the json response of any npm package, such as jQuery for example, http://registry.npmjs.org/jquery, you may come across a dictionary called users. This dictionary contains usernames as keys and boolean values as the corresponding values. ...

When the page is reloaded, establish the default value for the dropdown in Angular 9

My HTML file includes the use of p-dropdown: <p-dropdown id="userType" name="userType" inputId="userType" formControlName="userType" [required]="true" [tabindex]="1" optionLabe ...

Minimize unnecessary rendering in React when toggling between tabs

I am currently working on a React application that utilizes material-ui to generate tabs. <div className={classes.root}> <AppBar position="static"> <Tabs value={value} onChange={handleChange}> <Tab label="Item One" /> ...

Tips for concealing content within table cells

I am facing an issue with my form that contains a table. When the user clicks on the radio button labeled "No", I want the content of the subsequent cells in that row to become visible. However, when they click on "Yes", the content should be hidden again. ...

I have a component that I utilized for subscription purposes. After subscribing to the method, I ensured to properly unsubscribe in order to prevent any memory leaks

Access code for services private postsData: Post[] = []; private updatedPosts = new Subject<Post[]>(); getPosts() { return [...this.postsData]; } getUpdatedPostsListener() { return this.updatedPosts.asObservable(); } addNe ...

Struggling to remove an image while using the onmouseover event with a button?

I am encountering an issue with hiding an image using the onmouseover event not applied directly to it, but rather to a button element. The desired functionality is for the image to appear when the mouse hovers over and disappear when it moves away. Here&a ...

Experiencing peculiar behavior with the delete keyword in JavaScript

Okay, so here's the deal... var obj = people[0]; obj.oAuthID = null; delete obj.oAuthID; This code snippet returns... { "uuid": "39b2b45f-1dde-4c9a-8765-1bc76f55848f", "oAuthID": null, "date": "2013-10-21T16:48:47.079Z", "updated": "2013-10 ...

What could be causing the Express server to return an error despite everything being in order?

I am new to exploring express.js and attempting to create a basic sign-in example server. I have set up a database object with a users array containing objects, each with email and password properties. Despite using body-parser to convert the body into a j ...

Having trouble getting the if statement to run with JavaScript Closures?

Check out this code snippet: let url = URL; let imageURL = ''; $.getJSON("https://graph.facebook.com/?id="+encodeURIComponent(url)+"&scrape=true&method=post", function (data) { let json_data = JSON.stringify(data); json_data ...

Issue with optional generic in Typescript union not functioning as intended

I am facing a challenge with a type that requires an optional generic. In my case, if the generic G is provided, a new property of type G must be included. However, I encountered an issue while trying to implement this in a function: interface Message { ...

An unanticipated issue has arisen with the Alert Open Error. The command "browser.switchTo().alert().accept();" functions properly in Firefox, but encounters difficulties in Chrome while executing via Jenkins

Seeking assistance on how to resolve a specific error encountered in the Chrome browser while using Protractor. https://i.stack.imgur.com/7Fm4l.png The error message reads as follows: "UnexpectedAlertOpenError: unexpected alert open: {Alert text : There a ...

Configuring babel-plugin-styled-components with TypeScript in a create-react-app environment

Currently, we are working on integrating the babel-plugin-styled-components into our setup, which is based on typescript and create-react-app. Our main goal is to improve the debugging experience, but we are facing challenges in achieving this. We want to ...