英文:
Angular Table Content Not Displaying Properl API
问题
The API返回一个对象数组,我可以提取并循环遍历它,然后将其转化为行。但问题是,它只在一行中显示一个元素,并生成两个Rows的条目。但是,当我点击选择文件选项(有一个我们可以选择文件的列)并提供文件路径时,另一行的数据也会显示,还有一个文件扩展名列,它是一个下拉列表,数据也来自API。当我向文件添加路径时,这个功能可以正常工作。我认为这里存在一些渲染问题。这是我的HTML表格代码:
<div class="card">
<hr>
<div class="card-header">
<h2>Bank Statements of {{this.selectedOptionProduct}}</h2>
</div>
<div class="card-body">
<div class="loading-spinner" *ngIf="productSelectedForLoading && loading">
<div class="spinner"></div>
</div>
<table class="table">
<thead>
<tr>
<th>Product Name</th>
<th>File Uploads</th>
<th>Status</th>
<th>File Extension</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of tableData">
<td>{{ row.file_type_id }}</td>
<td>
<input type="file" #fileInput [value]="row.file_type_id" (change)="onFileSelected($event, row)">
<button (click)="uploadFile(row)">Upload</button>
<button (click)="resetFileInput(fileInput)">Reset</button>
</td>
<td>{{ row.status }}</td>
<td>
<select (change)="onOptionSelectedExtention($event.target)">
<option>Select one</option>
<option *ngFor="let extention of row.file_extensions" mat-menu-item [value]="extention">{{extention}}</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
</div>
这是我的组件.ts文件中的函数部分:
tableData: any[] = [];
selectedExtention: String;
loading: boolean = true;
async getTableData(selectedProduct: any) {
try {
const url = `API?product_id=${selectedProduct}`;
const response = await axios.get(url);
const data = response.data;
this.tableData = data;
this.loading = false;
console.log(this.tableData);
} catch (error) {
console.error('Error:', error);
}
}
resetFileInput(fileInput: HTMLInputElement) {
fileInput.value = ''; // 重置文件输入字段的值
}
onFileSelected(event: any, row: any) {
row.selectedFile = event.target.files[0];
console.log(row.selectedFile['name']);
}
uploadFile(row: any) {
const file = row.selectedFile;
console.log(file);
if (file) {
const formData = new FormData();
formData.append('file', file);
// 发送HTTP请求上传文件
this.http.post('your-upload-api-url', formData)
.subscribe(
response => {
// 处理成功响应,例如更新状态
row.status = 'Uploaded';
},
error => {
// 处理错误响应,例如显示错误消息
console.log("hello");
}
);
}
}
onOptionSelectedExtention(selectedOption: any) {
this.selectedExtention = selectedOption.value;
console.log(this.selectedExtention);
}
希望这对你有所帮助。
英文:
The API Returns an array of objects so that i could extract it and loop it through and make ROWS out of it . but the problem is it displays only one element in the row and makes 2 entries of Rows . but When i click on the choose files options (there is a column in which we can choose files) and give a file path . the data of the other row displays also there is a file extension column which is a drop down . the data from this drop down also comes from an API .this functionality works when i add a path to the file . i think there is some rendering issue . This is my HTML code for the table
<div class="card" >
<hr>
<div class="card-header">
<h2>Bank Statements of {{this.selectedOptionProduct}}</h2>
</div>
<div class="card-body">
<div class="loading-spinner" *ngIf="productSelectedForLoading && loading">
<div class="spinner"></div>
</div>
<table class="table" >
<thead>
<tr>
<th>Product Name</th>
<th>File Uploads</th>
<th>Status</th>
<th> File extenstion </th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of tableData " >
<td>{{ row.file_type_id }}</td>
<td>
<input type="file" #fileInput [value]="row.file_type_id" (change)="onFileSelected($event, row)">
<button (click)="uploadFile(row)">Upload</button>
<button (click)="resetFileInput(fileInput)">Reset</button>
</td>
<td>{{ row.status }}</td>
<td>
<select (change)="onOptionSelectedExtention($event.target)" >
<option>Select one </option>
<option *ngFor="let extention of row.file_extensions" mat-menu-item [value]="extention" >{{extention}}</option>
</select>
</td>
</tr>
</tbody>
</table>
This is my component.ts file for those functions
tableData: any[] = [
];
selectedExtention : String
loading: boolean = true;
onOptionSelectedExtention(selectedOption : any){
this.selectedExtention=selectedOption.value
console.log(this.selectedExtention)
}
async getTableData(selectedProduct: any) {
try {
const url = `API?product_id=${selectedProduct}`;
const response = await axios.get(url);
const data = response.data;
this.tableData = data;
this.loading = false;
console.log(this.tableData);
// Flatten the tableData array
this.flattenedTableData = this.tableData.reduce((accumulator, row) => {
return accumulator.concat(row.items);
}, []);
console.log(this.flattenedTableData);
// Use the variable as needed
console.log(data);
} catch (error) {
// Handle any errors
console.error('Error:', error);
}
}
resetFileInput(fileInput: HTMLInputElement) {
fileInput.value = ''; // Reset the value of the file input field
}
onFileSelected(event: any, row: any) {
row.selectedFile = event.target.files[0];
console.log(row.selectedFile['name'])
}
uploadFile(row: any) {
const file = row.selectedFile;
console.log(file);
if (file) {
const formData = new FormData();
formData.append('file', file);
// Make an HTTP request to upload the file
this.http.post('your-upload-api-url', formData)
.subscribe(
response => {
// Handle success response, e.g., update status
row.status = 'Uploaded';
},
error => {
// Handle error response, e.g., display an error message
console.log("hello")
}
);
}
}
And this only happens when i have two objects in that array from the API . how to fix it . here are some of the SS for visual representation. This picture is when i don't hit choose the file option as you could see this does not render the second row items neither the file extension
edit :
This is after hitting choose files and it re rendered
答案1
得分: 0
问题在于您使用属性绑定而不是将字符串值直接分配给输入。因此,第一行正确渲染,但当渲染第二行时,会发生冲突,因为该属性已经绑定到第一行的输入。这导致以下 DOM 异常:
"ERROR DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string."
您可以通过简单地删除 [value] 属性上的括号来解决这个问题。这将分配一个字符串值,而不是绑定属性。
例如:
<td>
<input type="file" #fileInput value="row.file_type_id" (change)="onFileSelected($event, row)">
<button (click)="uploadFile(row)">Upload</button>
<button (click)="resetFileInput(fileInput)">Reset</button>
</td>
英文:
The problem is that you are using property binding rather than just assigning a a string value to your input. Therefor, the first row renders correctly, but when the second row is rendered, there is a conflict as the property is already bound to the first row's input. This results in the following DOM exception:
"ERROR DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string."
You can resolve this by simply removing brackets on your [value] property. This will assign a string value rather that binding the property.
Ex.
<td>
<input type="file" #fileInput value="row.file_type_id" (change)="onFileSelected($event, row)">
<button (click)="uploadFile(row)">Upload</button>
<button (click)="resetFileInput(fileInput)">Reset</button>
</td>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论