Reputation: 23
I'm creating an app that allows users to add categories and reorder them. When pressing "add category" it creates a new row in the table and an input form displays to allow the user to name that category. However, I can not send the form data to the 'save' button if that input has *ngIf within it. I even tried putting the if statement on a div surrounding the input to no avail. I'm just getting that the input is undefined.
categories.component.html
<div class="container table-responsive">
<table class="table table-striped table-hover">
<thead>
<p class="ml-3 mt-2 mb-0 float-left">Section</p>
<a href="#" class="add-category mt-3 mr-3" (click)="addCatagory()">+ ADD CATEGORY</a>
<tr>
<th scope="col"></th>
<th scope="col">CATEGORY</th>
<th scope="col" class="mt-3">SEQ.</th>
<th scope="col"></th>
</tr>
</thead>
<tbody dragula="categories" [(dragulaModel)]="sortableList" id="tbody">
<tr *ngFor="let row of sortableList; index as i;">
<th scope="row" class="sort-cell">
<button class="btn bg-transparent">
<img src="/assets/images/sortable.svg" alt="">
</button>
</th>
<td>
<p *ngIf="!row.editing">
{{row.title}}
</p>
<input #box placeholder="Category Name">
</td>
<td>
<p class="seq text-white text-center">{{i + 1}}</p>
</td>
<td class="text-right">
<button class="btn bg-transparent border-0" (click)="delCatagory(row.title)">
<img *ngIf="!row.editing" src="/assets/images/delete.svg" alt="">
</button>
<a *ngIf="row.editing" href="#" class="add-category mt-3 mr-3" (click)="senddata(box.value, i)">Save</a>
</td>
</tr>
</tbody>
</table>
</div>
categories.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-categories',
templateUrl: './categories.component.html',
styleUrls: ['./categories.component.scss']
})
export class CategoriesComponent implements OnInit {
sortableList = [];
senddata(value, i): void {
var a = value;
var current = this.sortableList.length;
console.log('Value ' + a);
console.log('Current ' + current);
this.sortableList.splice(i, 1, {
id: current,
title: a,
editing: false
});
}
addCatagory(): void {
var current = this.sortableList.length;
this.sortableList.push({
id: current + 1,
title: 'Catagory ' + (current + 1),
editing: true
});
}
delCatagory(a): void {
var pos = this.sortableList
.map(function(e) {
return e.title;
})
.indexOf(a);
this.sortableList.splice(pos, 1);
}
spliceCategory(a): void {
var value = a;
var current = this.sortableList.length;
console.log('Value ' + value);
console.log('Current ' + current);
}
editCategory(a): void {
var value = a;
var current = this.sortableList.length;
this.sortableList.push({
id: current + 1,
title: 'Catagory ' + (current + 1),
editing: false
});
}
constructor() {}
ngOnInit() {}
ngAfterViewInit() {}
}
Error
ERROR TypeError: "_co.box is undefined"
View_CategoriesComponent_5ng:///AppModule
/CategoriesComponent.ngfactory.js:28:11
handleEventhttp://localhost:4200/vendor.js:41342:16
callWithDebugContexthttp://localhost:4200/vendor.js:42435:22
debugHandleEventhttp://localhost:4200/vendor.js:42138:12
dispatchEventhttp://localhost:4200/vendor.js:38801:16
renderEventHandlerClosurehttp://localhost:4200/vendor.js:39245:38
decoratePreventDefaulthttp://localhost:4200/vendor.js:51364:36
invokeTaskhttp://localhost:4200/polyfills.js:2743:17
onInvokeTaskhttp://localhost:4200/vendor.js:34899:24
invokeTaskhttp://localhost:4200/polyfills.js:2742:17
runTaskhttp://localhost:4200/polyfills.js:2510:28
invokeTaskhttp://localhost:4200/polyfills.js:2818:24
invokeTaskhttp://localhost:4200/polyfills.js:3862:9
globalZoneAwareCallbackhttp://localhost:4200/polyfills.js:3888:17
CategoriesComponent.html:35:10
Upvotes: 2
Views: 710
Reputation: 303
I had this problem and if I am not mistaken: the problem is when sending data with inputs they need to have unique IDs to be distinct one from another during the different operations.
Since the inputs are created with *ngFor, you can put a generic name in the ID attribute and append the index value of the *ngFor:
<tbody dragula="categories" [(dragulaModel)]="sortableList" id="tbody">
<tr *ngFor="let row of sortableList; index as i;">
<th scope="row" class="sort-cell">
<button class="btn bg-transparent">
<img src="/assets/images/sortable.svg" alt="">
</button>
</th>
<td>
<p *ngIf="!row.editing">
{{row.title}}
</p>
<input #box placeholder="Category Name" id="CategoryName{{i}}">
</td>
<!-- ... -->
</tr>
</tbody>
All input IDs will start with the same characters and have a unique number at the end, thus making them unique:
<input #box placeholder="Category Name" id="CategoryName0">
<input #box placeholder="Category Name" id="CategoryName1">
...
<input #box placeholder="Category Name" id="CategoryNameN">
Upvotes: 0