# 錯誤控制與刪除
###### tags: `CTBC-Lab4`
```html
<form #updateForm="ngForm" (ngSubmit)="onStoreUpdate(updateForm.value)">
<p>修改分行資訊</p>
<input type="text" name="id" [(ngModel)]="store.id" #newId="ngModel" readonly class="form-control-plaintext"/>
<input type="text" name="name" [(ngModel)]="store.name" #newName="ngModel" required placeholder="分行名稱" class="form-control"/>
<input type="text" name="site" id="site" [(ngModel)]="store.site" #newSite required placeholder="分行區域" class="form-control"/>
<button [disabled]="!updateForm.valid || !updateForm.touched" type="submit" class="btn btn-outline-success">
送出修改
</button>
</form>
```
```typescript
onStoreUpdate(updateForm:{newId:number;newName:string,newSite:string}){)
```
```html
<nav class="navbar navbar-expand-md navbar-light bg-light">
<a class="navbar-brand" href="#">Brand</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
</ul>
</div>
</nav>
```
---
ERROR Error: NG01352: If ngModel is used within a form tag, either the name attribute must be set or the form
control must be defined as 'standalone' in ngModelOptions.
```htmlembedded=
<p>分行列表</p>
<button type="button" class="btn btn-primary" (click)="onGetStore()" #list>查詢所有分行</button>
<button type="button" class="btn btn-outline-secondary">
<a href="../store-list/store-add" style="text-decoration: none;">新增分行</a>
</button>
<!-- <form #updateForm="ngForm" (ngSubmit)="onStoreUpdate(updateForm.value)"> -->
<table class="table">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Name</th>
<th scope="col">site</th>
<th scope="col">edit</th>
<th scope="col">delete</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let store of stores;">
<th scope="row">
{{store.id}}
<!-- <input type="text" name="id" id="id" [(ngModel)]="store.id" #newId disabled/> -->
</th>
<td>
{{store.name}}
<!-- <input type="text" name="name" id="name" [(ngModel)]="store.name" #newName/> -->
</td>
<td>
{{store.site}}
<!-- <input type="text" name="site" id="site" [(ngModel)]="store.site" #newSite/> -->
</td>
<td>
<button (click)="store.showForm=true" class="btn btn-outline-danger">修改</button>
<div *ngIf="store.showForm">
<form #updateForm="ngForm" (ngSubmit)="onStoreUpdate(updateForm.value)">
<p>修改分行資訊</p>
<input type="text" name="newId" id ="newId" [(ngModel)]="store.id" readonly class="form-control-plaintext"/>
<input type="text" name="newName" id ="newName" [(ngModel)]="store.name" required placeholder="分行名稱" class="form-control"/>
<!-- <label for="exampleDataList" class="form-label">分行區域</label> -->
<!-- <input class="form-control" list="datalistOptions" id="exampleDataList" placeholder="分行區域">
<datalist id="datalistOptions">
<option [value]="category.name" *ngFor="let category of categorys;">
<option value="New York">
<option value="Seattle">
<option value="Los Angeles">
<option value="Chicago">
</datalist> -->
<select class="form-select" aria-label="Default select example" name="newSite" id="newSite" [(ngModel)]="store.category.name" >
<option selected>{{store.site}}</option>
<option [value]="category.id" *ngFor="let category of categorys;" [ngModel]="store.category.name">{{category.name}}</option>
</select>
<!-- <input type="text" name="newSite" id="newSite" [(ngModel)]="store.site" #newSite required placeholder="分行區域" class="form-control"/> -->
<!-- v1 -->
<input type="text" name="newStoreSiteId" id="newStoreSiteId" [(ngModel)]="store.category.id" required placeholder="分行區域代碼" class="form-control"/>
<input type="text" name="newStoreSiteName" id="newStoreSiteName" [(ngModel)]="store.category.name" required placeholder="分行區域名稱" class="form-control"/>
<input type="text" name="newStoreSiteManager" id="newStoreSiteManager" [(ngModel)]="store.category.manager" required placeholder="分行區域主管" class="form-control"/>
<!-- v2 -->
<!-- <input type="text" name="newStoreSiteId" id="newStoreSiteId" [value]="store.category.id" #newStoreSiteId required placeholder="分行區域代碼" class="form-control"/>
<input type="text" name="newStoreSiteName" id="newStoreSiteName" [value]="store.category.name" #newStoreSiteName required placeholder="分行區域名稱" class="form-control"/>
<input type="text" name="newStoreSiteManager" id="newStoreSiteManager" [value]="store.category.manager" #newStoreSiteManager required placeholder="分行區域主管" class="form-control"/> -->
<button [disabled]="!updateForm.valid || !updateForm.touched" type="submit" class="btn btn-outline-success">
送出修改
</button>
</form>
</div>
<!-- <button type="submit" class="btn btn-outline-danger">
<a [routerLink]="['/store-list/store-update',store.id]">修改</a>
</button> -->
<!-- <button type="button" class="btn btn-outline-secondary">
<a href="../store-list/store-update">修改</a>
</button> -->
</td>
<td>
<button type="button" class="btn btn-outline-danger" (click)="onStoreDelete(store.id)">刪除</button>
</td>
</tr>
</tbody>
</table>
<!-- </form> -->
```
```
// 下拉式選單
// ------------------------------------------------------------------------------
select() {
const URLGet = "http://localhost:8080/api/grade/all"
this.http.get<Grade[]>(URLGet).subscribe(
(datagradeArray) => {
this.gradeArray = datagradeArray;
console.log("dataGradeArray\n",datagradeArray)
})
}
selectedGrade = {
gradeId: 0,
gradeName: '',
gradeHowMany: 0,
}
// 宣告陣列
gradeArray!:Grade[];
selectedOption: number = 0;
// 函式
onSelectedOptionChange() {
console.log("selectedOption : ",this.selectedOption);
const indexOfGrade = this.gradeArray.map(function(e){return e.gradeId;}).indexOf(Number(this.selectedOption));
console.log("拿到的index : ",indexOfGrade);
this.selectedGrade.gradeId = this.gradeArray[indexOfGrade].gradeId;
this.selectedGrade.gradeName = this.gradeArray[indexOfGrade].gradeName;
this.selectedGrade.gradeHowMany = this.gradeArray[indexOfGrade].gradeHowMany;
}
```
student-only.component.ts
```typescript
// 下拉式選單
// ------------------------------------------------------------------------------
// 宣告空陣列
gradeArray!:Grade[];
selectedOption: number = 0;
// 查詢Grade函式
select() {
const URLGet = "http://localhost:8080/api/grade/all"
this.http.get<Grade[]>(URLGet).subscribe(
(datagradeArray) => {
this.gradeArray = datagradeArray;
console.log("dataGradeArray\n",datagradeArray)
})
}
// 建立Instance
selectedGrade = {
gradeId: 0,
gradeName: '',
gradeHowMany: 0,
}
// 函式
onSelectedOptionChange() {
console.log("selectedOption : ",this.selectedOption);
const indexOfGrade = this.gradeArray.map(function(e){return e.gradeId;}).indexOf(Number(this.selectedOption));
console.log("拿到的index : ",indexOfGrade);
this.selectedGrade.gradeId = this.gradeArray[indexOfGrade].gradeId;
this.selectedGrade.gradeName = this.gradeArray[indexOfGrade].gradeName;
this.selectedGrade.gradeHowMany = this.gradeArray[indexOfGrade].gradeHowMany;
}
```
## 錯誤控制
### Java
#### constant
```java
package com.ctbcbank.boot.Lab4.constant;
//錯誤的種類
public interface Error {
enum ErrCode {
duplicate("0001", "duplicate"),
nullerr("0002", "nullerr");
// NotEmptyException
public String errorCode;
public String msg;
ErrCode(String errorCode, String msg) {
this.errorCode = errorCode;
this.msg = msg;
}
}
}
```
#### exception
##### DemoExpetion
```java
package com.ctbcbank.boot.Lab4.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
import lombok.Getter;
import lombok.Setter;
//錯誤控制的介面
@ResponseStatus(HttpStatus.BAD_REQUEST)
public class DemoException extends RuntimeException{
@Getter
@Setter
private String errorCode;
@Getter
@Setter
private String errorMessage;
public DemoException(String errorCode, String errorMessage) {
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}
}
```
##### DemoResponse
```java
package com.ctbcbank.boot.Lab4.exception;
import lombok.Getter;
import lombok.Setter;
public class DemoResponse {
@Getter
@Setter
private String code;
@Getter
@Setter
private String message;
// 建構子
public DemoResponse(String code, String message) {
this.code = code;
this.message = message;
}
}
```
##### GlobalExceptionHandler
```java
package com.ctbcbank.boot.Lab4.exception;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler{
// 在這邊接住錯誤
// 改寫成json
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<Object> handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
String message = ex.getMessage();
return handleExceptionInternal(ex, message, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
}
// 通常不會用Object
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
Map<String, Object> body = new LinkedHashMap<>();
body.put("timestamp", LocalDateTime.now());
body.put("message", ex.getMessage());
if (ex instanceof DemoException ) {
DemoException demoException = (DemoException)ex;
System.out.println("=== ErrorCode : " + demoException.getErrorCode());
System.out.println("=== msg : " + demoException.getErrorMessage());
body.put("ErrorCode", demoException.getErrorCode());
body.put("msg", demoException.getErrorMessage());
}
//
//String message = ex.getMessage();
// (Exception, Object, HttpHeaders, HttpStatus, WebRequest)
return handleExceptionInternal(ex, body, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
}
}
```
##### ResourceNotFoundException
```java
package com.ctbcbank.boot.Lab4.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.BAD_REQUEST)
public class ResourceNotFoundException extends RuntimeException{
String errMsg;
public ResourceNotFoundException (String errMsString) {
this.errMsg = errMsString;
}
@Override
public String getMessage() {
return errMsg;
}
}
```
### Angular
```typescript
// 刪除
deleteGrade(gradeId:number) {
const URLDelete = 'http://localhost:8080/api/grade/' + gradeId;
this.http.delete(URLDelete).subscribe(
//
(data) =>{
console.log('刪除成功, 被刪除的資料是:', data);
this.onGetAllGrade();
},
(error) => {
console.error('Delete failed');
console.error(error);
alert(error.error.message);
});
}
```
---
## 刪除
```java
// 刪除一筆
@Override
public void deleteGrade(Long gradeId) throws Exception{
GradeBean targetGrade = gradeBeanRepository.findById(gradeId).get();
int itemList = targetGrade.getStudentsList().size();
System.out.println("** need to be delete " + targetGrade.toString());
if (itemList == 0) {
gradeBeanRepository.deleteById(gradeId);
} else {
throw new Exception("Grade is not empty, there are " +Integer.toString(itemList)+" element(s) in it");
}
}
```