-->

angular4 local variable issue for *ngFor

2020-08-04 04:54发布

问题:

I have a requirement where I have load multiple items using item list. Whenever you upload a file, upload file input has to hide and details of that file has to show like filename and other button.

I implemented the scenario by using a localvariable, it works fine with one item, but when we have multiple items, its not working. Assume if I have 3 itemList, if we click on 1st item fileupload button and upload a file, it loads filename and validate button, but if we do same process for 2nd item (after 1st process), after fileupload, 1st filename will be modified.

View:

<div id="userItemList" *ngFor="let item of itemList; let i=index">
    <div>
        <span>{{item.Id}}</span>
        <span>{{item.Name}}</span>
        <span>{{item.Count}}</span>
    </div>
    <div>
        <input type="file" name="UploadFile" id="fileInput" #fileInput (change)="txtUploadFile($event,i)">
        <div class="validate-file-div" #validateContent style="display:none">
            <div class="file-name" #fileName></div>
            <span id="validate-csv-button" data-program-id="0" class="button">Validate</span>
        </div>
    </div>
</div>

My component look like:

import { Component, OnInit, ViewChild } from '@angular/core';

@Component({
  selector: 'app-programs-manager',
  templateUrl: './ProgramsManager.component.html',
  styleUrls: ['./ProgramsManager.component.css'],
})

export class ProgramsManagerComponent implements OnInit {

    itemList = [{"Id":1,"Name":"Item1","Count":2},{"Id":2,"Name":"Item2","Count":2},{"Id":3,"Name":"Item3","Count":3}];
    @ViewChild("fileInput") fileInput;
    @ViewChild("validateContent") validateContent;
    @ViewChild("fileName") fileName;

    constructor() { }

    ngOnInit() {
    }

    txtUploadFile(event,index) {
        this.fileInput.nativeElement.style.display = "none";
        this.validateContent.nativeElement.style.display = "block";
        this.fileInput.nativeElement.innerHTML = event.target.files[0].name;
    }
}

I feel local variable is giving problem,but don't know how to fix it. can anyone help me. Thanks in advance

回答1:

All you need to do is use @ViewChildren instead of @ViewChild

@ViewChildren("fileInput") fileInput : QueryList<any>;
@ViewChildren("validateContent") validateContent : QueryList<any>;
@ViewChildren("fileName") fileName : QueryList<any>;

And change function txtUploadFile to

txtUploadFile(event,index) {
    var fileInputs = this.fileInput.toArray();
    var validateContents = this.validateContent.toArray();

    fileInputs[index].nativeElement.style.display = "none";
    validateContents[index].nativeElement.style.display = "block";
    fileInputs[index].nativeElement.innerHTML = event.target.files[0].name;
}

Here is the link of working example :

https://stackblitz.com/edit/angular-view-children


Extra Notes :

@ViewChild:

You can use ViewChild to get the first element or the directive matching the selector from the view DOM. If the view DOM changes, and a new child matches the selector, the property will be updated.

@ViewChildren:

You can use ViewChildren to get the QueryList of elements or directives from the view DOM. Any time a child element is added, removed, or moved, the query list will be updated, and the changes observable of the query list will emit a new value.



回答2:

Eliseo is right you should get index value instead of 0. That's why. To show and hide a div, you must create a class variable like showInfo = null by default and set it with the file array value.

Change the value when the use click on the download button using <button (click)="showInfo=item[index]"/> Then in your HTML use

<a [class.hidden]="!showInfo">Download {{item.name}} </a> 

which display the info if existing