---
# System prepended metadata

title: 錯誤控制與刪除
tags: [CTBC-Lab4]

---

# 錯誤控制與刪除
###### 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");
    }
}
```