#json #angular #typescript
#json #angular #typescript
Вопрос:
Привет участникам Stackoverflow
Я хотел сделать пакетное редактирование доступным и для подузлов, но мне это не удалось.
Может кто-нибудь, пожалуйста, заглянуть в код и предложить мне изменения, чтобы пакетное редактирование было доступно как для родительского узла, так и для вложенного узла записи.
app.component.html
<div class="container-fluid">
<!-- Add Record -->
<div *ngIf="isAdd">
<form #myForm="ngForm">
<div class="form-group">
<label>First Name</label>
<input type="text" name="first_name" class="form-control" ngModel>
</div>
<div class="form-group">
<label>Last Name</label>
<input type="text" name="last_name" class="form-control" ngModel>
</div>
<div class="form-group">
<label>Email</label>
<input type="email" name="email" class="form-control" ngModel>
</div>
<div class="form-group">
<label>Gender</label>
<select name="gender" id="" ngModel class="form-control">
<option>Male</option>
<option>Female</option>
</select>
</div>
<div class="form-group">
<label>Date of Birth</label>
<input type="date" name="dob" class="form-control" ngModel>
</div>
<div class="form-group">
<label>Impact</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="impact" ngModel id="impactOption1" value="Applicable" checked>
<label class="form-check-label" for="impactOption1">
Applicable
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="impact" ngModel id="impactOption2" value="Not Applicable">
<label class="form-check-label" for="impactOption2">
Not Applicable
</label>
</div>
</div>
<div class="form-group">
<label>Score</label>
<input type="number" name="score" class="form-control" ngModel>
</div>
<div class="form-group">
<button type="button" class="btn btn-primary btn-sm" (click)="addUser(myForm.value)">Submit</button>
<button type="button" class="btn btn-secondary btn-sm ml-2" (click)="cancelAddUser()">Cancel</button>
</div>
</form>
</div>
<!-- Add Record -->
<!-- Parent Batch Edit -->
<div>
<form #myForm="ngForm">
<div class="form-group">
<select name="impact" [disabled]="!isBatchEdit" class="form-control form-control-sm" [(ngModel)]="currentImpact">
<option value="" disabled selected>Change Impact</option>
<option>Applicable</option>
<option>Not Applicable</option>
<option>FYI</option>
</select>
</div>
<button type="button" [disabled]="!isBatchEdit" (click)="batchUpdateUser(); myForm.reset()" class="btn btn-success btn-sm btn-update mr-2">
Update
</button>
<button type="button" [disabled]="!isBatchEdit" (click)="cancelBatchEdit(); myForm.reset()" class="btn btn-secondary btn-sm">Cancel</button>
</form>
</div>
<!-- Parent Batch Edit -->
<!-- Single Record Edit -->
<div *ngIf="isEdit">
<form #myForm="ngForm">
<div class="form-group">
<select name="impact" id="" class="form-control form-control-sm" [(ngModel)]="currentImpact">
<option>Applicable</option>
<option>Not Applicable</option>
<option>FYI</option>
</select>
</div>
<button type="button" (click)="updateUser()" class="btn btn-success btn-sm btn-update mr-2" *ngIf="isEdit">Update</button>
<button type="button" (click)="cancelEdit()" class="btn btn-secondary btn-sm">Cancel</button>
</form>
</div>
<!-- Single Record Edit -->
<!-- Filter -->
<div class="filter-data mt-3">
<form #form="ngForm">
<div class="form-group float-left mr-4">
<strong>Gender</strong>
<br>
<select class="form-control form-control-sm" name="gender" ngModel [ngModelOptions]="{updateOn: 'submit'}">
<option></option>
<option value="Male">Male</option>
<option value="Female">Female</option>
</select>
</div>
<div class="form-group float-left">
<strong>Impact</strong>
<br>
<select class="form-control form-control-sm" name="impact" ngModel [ngModelOptions]="{updateOn: 'submit'}">
<option></option>
<option value="Applicable">Applicable</option>
<option value="Not Applicable">Not Applicable</option>
</select>
</div>
<div class="form-group float-left mt-3 pt-1 ml-2">
<button type="submit" class="btn btn-primary btn-sm mr-2">Apply</button>
<button type="button" (click)="form.reset();" class="btn btn-secondary btn-sm">Reset</button>
</div>
</form>
</div>
<!-- Filter -->
<div class="clearfix"></div>
<!-- Parent View Table -->
<div class="viewData">
<div class="float-left">
<button class="btn btn-primary btn-sm mb-2 mt-2" (click)="showAddUser()">Add New Record</button>
</div>
<div class="float-right">
<div class="text-right total-records float-right">Total: {{totalRecords}}</div>
<button type="button" class="btn btn-sm btn-secondary float-right mr-2 mt-2 mb-2" (click)="reload()">Refresh</button>
</div>
<div class="clearfix"></div>
<table class="table table-sm table-responsive">
<thead>
<tr>
<th></th>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Gender</th>
<th>DOB</th>
<th>Impact</th>
<th>Score</th>
<th></th>
</tr>
</thead>
<tbody>
<tr class="record-row" (click)="viewUser(user)" *ngFor="let user of allUser | tableFilter: form.value | paginate: { id: 'listing_pagination', itemsPerPage: 10, currentPage: page, totalItems: totalRecords }">
<td><input *ngIf="!isEdit" [(ngModel)]="user.checked" type="checkbox" (change)="checkboxClicked()"></td>
<td>{{user.first_name}}</td>
<td>{{user.last_name}}</td>
<td>{{user.email}}</td>
<td>{{user.gender}}</td>
<td>{{user.dob}}</td>
<td>{{user.impact}}</td>
<td>
<div [ngClass]="getClass(user)">{{user.score}}</div>
</td>
<td>
<button *ngIf="!isEdit" class="btn btn-primary btn-sm" (click)="editUser(user)">Edit</button>
<button class="btn btn-primary btn-sm btn-sm ml-2" (click)="deleteUser(user)">Delete</button>
</td>
</tr>
</tbody>
</table>
<pagination-controls id="listing_pagination" directionLinks="true" (pageChange)="page = $event"></pagination-controls>
</div>
<!-- Parent View Table -->
<div class="clearfix"></div>
<!-- Record Detail View -->
<div *ngIf="isView" class="view-details">
<ul class="card p-2">
<li><strong>First Name</strong> <br />{{userObj.first_name}}</li>
<li><strong>Last Name</strong> <br />{{userObj.last_name}}</li>
<li><strong>Email</strong> <br />{{userObj.email}}</li>
<li><strong>Gender</strong> <br />{{userObj.gender}}</li>
<li><strong>IP Address</strong> <br />{{userObj.dob}}</li>
<li><strong>Impact</strong> <br />{{userObj.impact}}</li>
<li><strong>Score</strong> <br /><span [ngClass]="getClass(userObj)">{{userObj.score}}</span></li>
</ul>
<div class="clearfix"></div>
<div class="mb-3">
<form #myForm="ngForm">
<div class="form-group">
<select name="impact" [disabled]="!isSubBatchEdit" class="form-control form-control-sm" [(ngModel)]="currentImpact">
<option value="" disabled selected>Change Impact</option>
<option>Applicable</option>
<option>Not Applicable</option>
<option>FYI</option>
</select>
</div>
<button type="button" [disabled]="!isSubBatchEdit" (click)="subBatchUpdateUser(); myForm.reset()" class="btn btn-success btn-sm btn-update mr-2">
Update
</button>
<button type="button" [disabled]="!isSubBatchEdit" (click)="subCancelBatchEdit(); myForm.reset()" class="btn btn-secondary btn-sm">Cancel</button>
</form>
</div>
<div class="clearfix"></div>
<table class="table table-responsive table-sm">
<thead>
<tr>
<th></th>
<th>CO Score</th>
<th>Distribution List</th>
<th>Impact</th>
<th>Comments</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let assignee of userObj.assigned_to">
<td><input *ngIf="!isEdit" [(ngModel)]="assignee.checked" type="checkbox" (change)="subCheckboxClicked()"></td>
<td><div [ngClass]="getClass(assignee)">{{assignee.co_score}}</div></td>
<td>{{assignee.dl}}</td>
<td>{{assignee.sub_impact}}</td>
<td>{{assignee.comments}}</td>
</tr>
</tbody>
</table>
<div class="clearfix"></div>
<div class="viewChart">
<div class="skills">
<ul class="labels">
<li>Applicable</li>
<li>Not Applicable</li>
<li>FYI</li>
</ul>
<ul class="lines">
<li class="line l--0"><span class="line__label">0</span></li>
<li class="line l--1"><span class="line__label">1</span></li>
<li class="line l--2"><span class="line__label">2</span></li>
<li class="line l--3"><span class="line__label">3</span></li>
<li class="line l--4"><span class="line__label">4</span></li>
<li class="line l--5"><span class="line__label">5</span></li>
<li class="line l--6"><span class="line__label">6</span></li>
<li class="line l--7"><span class="line__label">7</span></li>
<li class="line l--8"><span class="line__label">8</span></li>
<li class="line l--9"><span class="line__label">9</span></li>
</ul>
<div class="charts">
<div class="chart chart--dev">
<ul class="charts--horiz">
<li class="chart__bar" [style.width]="impactCount.applicable * 10 '%'">{{impactCount.applicable}}</li>
<li class="chart__bar" [style.width]="impactCount.notapplicable * 10 '%'">{{impactCount.notapplicable}}</li>
<li class="chart__bar" [style.width]="impactCount.fyi * 10 '%'">{{impactCount.fyi}}</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Record Detail View -->
</div>
приложение.component.ts
import { Component } from '@angular/core';
import { CommonService } from './common.service';
import { NgForm } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'db-poc1';
allUser: any;
isEdit = false;
isView = false;
isBatchEdit = false;
isSubBatchEdit = false;
isAdd = false;
totalRecords: any;
page: Number = 1;
currentImpact: string = '';
batchUpdateUsers = [];
subBatchUpdateUsers = [];
userObj = {
id: '', first_name: '', last_name: '', email: '', gender: '', dob: '', impact: '', score: ''
}
impactCount = {
applicable: 0, notapplicable: 0, fyi: 0
}
constructor(private commonService: CommonService) {}
ngOnInit() {
this.getLatestUser();
}
reload() {
window.location.reload();
}
checkboxClicked() {
this.batchUpdateUsers = this.allUser.filter((row: any) => row.checked);
this.isView = true;
this.isBatchEdit = this.batchUpdateUsers.length > 0;
this.currentImpact = this.userObj.impact;
}
subCheckboxClicked() {
this.subBatchUpdateUsers = this.allUser.filter((row: any) => row.checked);
this.isView = true;
this.isSubBatchEdit = this.subBatchUpdateUsers.length > 0;
this.currentImpact = this.userObj.impact;
}
addUser(formObj: any) {
this.commonService.createUser(formObj).subscribe((response) => {
this.getLatestUser();
});
this.isAdd = false;
}
showAddUser() {
this.isAdd = true;
}
cancelAddUser() {
this.isAdd = false;
}
getLatestUser() {
this.commonService.getAllUser().subscribe((response) => {
this.allUser = response;
this.totalRecords = this.allUser.length;
this.getApplicableCounts();
this.allUser.forEach((row: any) => row.checked = false);
});
}
getApplicableCounts() {
this.impactCount = {applicable:0, notapplicable:0, fyi: 0}
this.allUser.forEach((row: any) => {
// this.allUser.forEach(row => {
// if (row.impact === 'Applicable') {
// this.impactCount.applicable ;
// } else if (row.impact === 'Not Applicable') {
// this.impactCount.notapplicable ;
// } else if (row.impact === 'FYI') {
// this.impactCount.fyi ;
// }
// });
row.assigned_to.forEach((sub: any) => {
if (sub.sub_impact === 'Applicable') {
this.impactCount.applicable ;
} else if (sub.sub_impact === 'Not Applicable') {
this.impactCount.notapplicable ;
} else if (sub.sub_impact === 'FYI') {
this.impactCount.fyi ;
}
});
});
}
editUser(user: any) {
this.isEdit = true;
this.userObj = user;
this.allUser.forEach(user => user.checked = false);
this.currentImpact = user.impact;
}
deleteUser(user: any) {
this.commonService.deleteUser(user).subscribe(() => {
this.getLatestUser();
});
}
updateUser() {
this.isEdit = !this.isEdit;
this.userObj.impact = this.currentImpact;
this.commonService.updateUser(this.userObj).subscribe(() => {
this.getLatestUser();
});
this.getApplicableCounts();
}
cancelEdit() {
this.isEdit = false;
this.isView = false;
}
viewUser(user: any) {
this.isView = true;
this.userObj = user;
}
cancelBatchEdit() {
this.isBatchEdit = false;
this.allUser.forEach((user: any) => {user.checked = false});
}
getClass(user) {
if(user.score <= 30 || user.co_score <= 30)
return 'beginner';
else if (user.score <= 75 || user.co_score <= 75)
return 'intermediate';
else if (user.score <= 100 || user.co_score <= 100)
return 'expert';
else return 'other';
}
batchUpdateUser() {
this.isBatchEdit = false;
const batchUpdateUserList = [];
this.allUser.forEach((user: any) => {
if (user.checked) {
user.impact = this.currentImpact
batchUpdateUserList.push(user);
user.checked = false;
this.commonService.updateUser(user).subscribe(() => {
this.getLatestUser();
});
user.score = "Updated";
}
});
this.commonService.updateUser(this.userObj).subscribe(() => {
this.getLatestUser();
});
this.getApplicableCounts();
}
subBatchUpdateUser() {
this.isSubBatchEdit = false;
const subBatchUpdateUserList = [];
this.allUser.forEach((user: any) => {
if (user.sub_impact.checked) {
user.sub_impact.impact = this.currentImpact
subBatchUpdateUserList.push(user);
user.sub_impact.checked = false;
this.commonService.updateUser(user).subscribe(() => {
this.getLatestUser();
});
user.score = "Updated";
}
});
this.commonService.updateUser(this.userObj).subscribe(() => {
this.getLatestUser();
});
this.getApplicableCounts();
}
subCancelBatchEdit() {
this.isSubBatchEdit = false;
this.allUser.forEach((user: any) => {user.checked = false});
}
}
db.json
{
"users": [
{
"id": 1,
"first_name": "Male",
"last_name": "Record",
"email": "male.record@gmail.com",
"gender": "Male",
"dob": "01-01-1987",
"impact": "Not Applicable",
"score": "Updated",
"checked": false,
"assigned_to": [
{
"co_score": 54,
"dl": "CAT1",
"sub_impact": "Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
},
{
"co_score": 20,
"dl": "CAT2",
"sub_impact": "Not Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
},
{
"co_score": 99,
"dl": "CAT1",
"sub_impact": "Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
}
]
},
{
"id": 2,
"first_name": "Female",
"last_name": "Record",
"email": "female.record@gmail.com",
"gender": "Female",
"dob": "31-12-1987",
"impact": "Applicable",
"checked": false,
"score": "Updated",
"assigned_to": [
{
"co_score": 54,
"dl": "CAT1",
"sub_impact": "Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
},
{
"co_score": 20,
"dl": "CAT2",
"sub_impact": "Not Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
}
]
},
{
"id": 3,
"first_name": "Male",
"last_name": "Record Another",
"email": "male.recordanother@gmail.com",
"gender": "Male",
"dob": "31-10-2017",
"impact": "Applicable",
"checked": false,
"score": 25,
"assigned_to": [
{
"co_score": 100,
"dl": "CAT3",
"sub_impact": "Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
},
{
"co_score": 2,
"dl": "CAT2",
"sub_impact": "Not Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
},
{
"co_score": 48,
"dl": "CAT2",
"sub_impact": "Not Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
}
]
},
{
"first_name": "Male",
"last_name": "One More Record",
"email": "male.onemorerecord@gmail.com",
"gender": "Male",
"dob": "08-08-1984",
"impact": "Applicable",
"id": 6,
"checked": false,
"score": "Updated",
"assigned_to": [
{
"co_score": 4,
"dl": "CAT1",
"sub_impact": "Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
},
{
"co_score": 85,
"dl": "CAT3",
"sub_impact": "Not Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
}
]
},
{
"first_name": "Female",
"last_name": "Another Record",
"email": "female.anotherrecord@gmail.com",
"gender": "Female",
"dob": "2000-07-15",
"impact": "Applicable",
"id": 7,
"checked": false,
"score": 85,
"assigned_to": [
{
"co_score": 34,
"dl": "CAT3",
"sub_impact": "Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
},
{
"co_score": 55,
"dl": "CAT2",
"sub_impact": "Not Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
}
]
},
{
"id": 8,
"first_name": "New",
"last_name": "Record",
"email": "new.record@gmail.com",
"gender": "Male",
"dob": "2020-12-17",
"impact": "Not Applicable",
"score": 60,
"checked": false,
"assigned_to": [
{
"co_score": 94,
"dl": "CAT1",
"sub_impact": "Not Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
},
{
"co_score": 85,
"dl": "CAT3",
"sub_impact": "Applicable",
"checked": false,
"comments": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
}
]
}
]
}
Комментарии:
1. angular-ivy-3iaw11.stackblitz.io
2. мне неясно, что именно вы хотите пакетно редактировать
3. @Moshezauros у меня есть пакетный выбор и обновление для родительского узла, но я хотел сделать то же самое и для вложенных узлов .. итак, будет 2 пакетные операции, одна для родительской, которая будет работать отдельно (которая работает нормально), и одна для вложенных / дочерних записей, чтобы пользователь мог обновлять своитакже влияет.
Ответ №1:
Есть много способов реализовать это, один из способов — что-то вроде:
в вашем шаблоне:
<tr *ngFor="let assignee of userObj.assigned_to">
<td><input type="checkbox" [(ngModel)]="assignee.checked"></td>
<td>{{assignee.sub_impact}}</td>
</tr>
и в вашем компоненте:
updateUser() {
this.isView = !this.isView;
this.isEdit = !this.isEdit;
this.userObj.impact = this.currentImpact;
debugger;
const checkedItems = this.userObj.assigned_to.filter(a => a.checked);
checkedItems.forEach(a => {
a.sub_impact = this.currentImpact;
delete a.checked;
});
console.log("update");
//this.commonService.updateUser().subscribe(response => {
this.getCounts();
//});
}
обратите внимание, что если вы хотите разные значения между user obj и assigned_to, вам придется создать новый выпадающий список
вот рабочий stackblitz
Комментарии:
1. @Moshezaurous это не обновление вложенных записей, а работа для родительских
2. @KunalVijan проверьте stackblitz, который я только что добавил, если это не то, что вам нужно, тогда вам нужно объяснить еще раз
3. спасибо, что изучили это. Мне нужно обновить влияние для вложенных записей так же, как оно обновляется для родительского. При выборе любой / множественной записи отображается выбор с применимым параметром n not applicable, то же самое, что я хочу для дочерней записи, поскольку пользователь выберет параметр show, чтобы изменить влияние на applicable или not applicable n post на service. Надеюсь, теперь все ясно
4. Я не понимаю, чем это отличается от того, что происходит в опубликованном мной stackblitz
5. в том, который вы опубликовали, не отображается элемент управления select, если мы установим флажок дочернего элемента. возможно, вы пропустили его сохранение, не могли бы вы проверить его еще раз? angular-ivy-h7jkgj.stackblitz.io У меня нет никакой возможности изменить влияние для вложенных записей