1. 程式人生 > >(五)在webpart中實現SharePoint Online的增刪查改(CRUD)操作

(五)在webpart中實現SharePoint Online的增刪查改(CRUD)操作

        在上一篇部落格(四)修改webpart並在SharePoint Online中除錯中,我們在SharePoint Online線上工作臺中使用”this.context.pageContext.web.title“獲取到了當前站點的名稱,下面將介紹如何實現增刪查改操作。微軟提供了一個library pnp-js-core,封裝了REST API,可以使用這個庫來與SharePoint Online互動。

        首先開啟powershell進入webpart專案目錄,使用如下npm命令安裝pnp-js-core庫。 

npm i --save @pnp/sp @pnp/common @pnp/odata @pnp/logging

        安裝完成之後可以在專案的node_modules中看到新新增的庫檔案如下:


        新增完成之後,我們需要在webpart中實現以下四個操作:

  • 讀取當前站點下的列表
  • 在指定列表中建立一個item
  • 修改item
  • 刪除item

        使用Code開啟專案,在HelloWorldWebPart.ts檔案的import程式碼區域新增如下程式碼,引入一個物件:sp

        sp物件是對SharePoint REST API的封裝,我們需要使用sp物件與SharePoint Online互動。接下來我們參照上一篇部落格內容在webpart的屬性編輯器中新增一個名字為“列表名稱”的文字框,用於指定需要訪問的列表。還是需要三步,第一步確保import中匯入一個文字框控制元件:


        第二步在介面中定義列表名稱屬性:


        第三步修改getPropertyPaneConfiguration()方法在webpart屬性編輯器中顯示這個文字框控制元件:


        然後新增如下get函式,禁用響應式的屬性編輯功能:


        disableReactivePropertyChanges是webpart基類BaseClientSideWebPart的一個屬性,預設是false,也就是使用響應式方式,當用戶修改webpart屬性編輯器中的webpart屬性的時候,webpart會即時根據屬性的值來展示webpart,上一篇部落格中我們為webpart添加了一個背景顏色的屬性,當選擇下拉選單中的顏色的時候,webpart的背景顏色會立即改變。現在將這個屬性值設定為true,webpart屬性編輯器會自動新增一個“應用”的按鈕,對webpart屬性所做的修改,不會立即改變webpart,而是要點選這個按鈕,才會改變webpart。

        添加了列表名稱這個屬性之後,webpart的屬性編輯器是這樣子的,注意下方自動添加了一個“應用”按鈕:


        添加了這個webpart屬性之後,讓我們新增CRUD操作需要的UI,也就是修改render()方法,新增一些頁面元素,例如文字框和按鈕等待,用於實現CRUD功能。render()方法修改如下:

export default class HelloWorldWebPartWebPart extends BaseClientSideWebPart<IHelloWorldWebPartProps> {

  public render(): void {
    this.domElement.innerHTML = `
      <div class="${ styles.helloWorld }">
        <div class="${ styles.container }">
          <div class="${ styles.row }" style="background-color:${this.properties.webpartcolor}">
            <div class="${ styles.column }">
              <span class="${ styles.title }">Welcome to SharePoint!</span>
              <p class="${ styles.subTitle }">Customize SharePoint experiences using Web Parts.</p>
              <p class="${ styles.description }">${escape(this.properties.description)}</p>
              <p class="${ styles.description }">當前站點名字:${escape(this.context.pageContext.web.title)}</p>
              <div class="${ styles.row }">
                <button class="${styles.button}" id="showListButton"><span>顯示list</span></button>
              </div>
              <div class="${ styles.row }">
                <button class="${styles.button}" id="showItemButton"><span>顯示item</span></button>
              </div>
              <div class="${ styles.row }">
                <span class="${styles.title}">輸入標題:</span>
                <input type="text" id="titleTxtCreate"/>
                <button class="${styles.button}" id="createButton"><span>新建item</span></button>
              </div>
              <div class="${ styles.row }">
                <span class="${styles.title}">輸入ID:</span>
                <input type="text" id="idTxtUpdate"/>
                <button class="${styles.button}" id="updateButton"><span>更新item</span></button>
              </div> 
              <div class="${ styles.row }">
                <span class="${styles.title}">輸入ID:</span>
                <input type="text" id="idTxtDelete"/>
                <button class="${styles.button}" id="deleteButton"><span>刪除item</span></button>
              </div>
              <div class="${ styles.row }">
                <span class="${styles.title}">當前狀態:</span>
                <span id="message" class="${styles.title}"></span>
              </div>
              <p id="lists"></p>
              <p id="items"></p>
            </div>
          </div>
        </div>
      </div>`;

      this.bindButtonEvent();
  }

        一共添加了5個按鈕,第一個“顯示List”按鈕用於顯示當前站點下的列表,第二個“顯示Item”按鈕會根據webpart屬性編輯器中指定的列表名稱,列出列表中的item,其他的按鈕是對item的操作,包括新建/更新/刪除。新增UI之後,webpart變成了下面的樣子:


        除了新增新的UI,在render()方法的最後還添加了一個函式this.bindButtonEvent(),這個方法會在新新增的按鈕上繫結onclick事件,函式實現如下:

private bindButtonEvent(){
    const webpart:HelloWorldWebPartWebPart = this;
    this.domElement.querySelector("#showListButton").addEventListener('click', ()=> {webpart.showAllList();});
    this.domElement.querySelector("#showItemButton").addEventListener('click', ()=> {webpart.showItems();});
    this.domElement.querySelector("#createButton").addEventListener('click', ()=> {webpart.createNewItem();});
    this.domElement.querySelector("#updateButton").addEventListener('click', ()=> {webpart.updateItem();});
    this.domElement.querySelector("#deleteButton").addEventListener('click', ()=> {webpart.deleteItem();});
  }

        在這個方法裡,使用this.domElement.querySelector()方法,根據button的id來獲取頁面上的按鈕,語法與jQuery一樣,然後在button上繫結方法,下面我們依次看一下這幾個方法,首先是showAllList()方法:

  private showAllList():void {
      const listDom : Element = this.domElement.querySelector("#lists");
      sp.web.lists.get().then(lists=>{
        listDom.innerHTML += `<ul>${lists.map(l=>`<li>${l.Title}</li>`).join("")}</ul>`;
      });
  }

        這個方法首先使用querySelector查詢ID為lists的頁面元素,然後使用sp.web.lists獲取列表,最後將list列表顯示在webpart上。

        第二個方法是showItems(),程式碼如下所示:

private showItems():void{
    const itemsDom : Element = this.domElement.querySelector("#items");
    if(this.properties.listName != ""){
      sp.web.lists.getByTitle(this.properties.listName).items.get().then(items=>{
        itemsDom.innerHTML += `<ul>${items.map(i=>`<li>${i.Title}</li>`).join("")}</ul>`;
      });
    } 
    else{
      itemsDom.innerHTML += "請指定列表";
    }
  }

        首先通過this.properties.listName讀取webpart屬性編輯器中的指定的列表名稱,然後根據列表名稱,獲取列表,然後再獲取列表的items並顯示在webpart上。

        第三個方法是createNewItem(),程式碼如下:

private createNewItem():void{
    const messageDom = this.domElement.querySelector("#message");
    messageDom.innerHTML = "正在建立item...";
    const createTitleDom : HTMLInputElement = <HTMLInputElement>this.domElement.querySelector("#titleTxtCreate");
    console.log(createTitleDom.value);
    let newItemTitle:string = createTitleDom.value;    
    sp.web.lists.getByTitle(this.properties.listName).items.add({
      Title: newItemTitle
    }).then(result =>{
      result.item.select("id").get().then(d => {messageDom.innerHTML = "item建立成功! item id: " + d.Id});
    }).catch(e =>{
      messageDom.innerHTML = "建立失敗! 錯誤: " + e.message;
    });
  }

        這個方法需要讀取UI中的文字框的值,所以在使用querySelector查詢文字框textbox的時候,需要將其轉換為一個HTMLInputElement物件才可以使用文字框的value屬性讀取資料。讀取到了資料之後,可以使用console.log方法將資料輸出到瀏覽器的控制檯來檢視。新增一個item使用items集合的add方法,在這個方法的引數中指定item的屬性,這裡我們只指定了標題,返回值是一個Promise物件,如果新增成功,執行then方法,成功的返回值result是ItemAddResult介面,其定義為:


        所以我們可以在then方法中讀取到item的ID屬性值。如果新增失敗,會執行catch方法,顯示錯誤資訊。

        與新增item的方法類似,更新一個item和刪除一個item的方法如下:

private updateItem():void{
    const messageDom = this.domElement.querySelector("#message");
    messageDom.innerHTML = "正在更新item...";
    const updateIdDom : HTMLInputElement = <HTMLInputElement>this.domElement.querySelector("#idTxtUpdate");
    console.log(updateIdDom.value);
    let updateItemId:string = updateIdDom.value;
    sp.web.lists.getByTitle(this.properties.listName).items.getById(parseInt(updateItemId)).update({
      Title: `標題 ${new Date()}`
    }).then(result => { 
      result.item.get().then(d => {messageDom.innerHTML = "item更新成功! item title: " + d.Title});
     }).catch(e =>{
        messageDom.innerHTML = "更新失敗! 錯誤: " + e.message;
    });
  
  }

  private deleteItem():void{
    const messageDom = this.domElement.querySelector("#message");
    messageDom.innerHTML = "正在刪除item...";
    const deleteIdDom : HTMLInputElement = <HTMLInputElement>this.domElement.querySelector("#idTxtDelete");
    console.log(deleteIdDom.value);
    let deleteItemId:string = deleteIdDom.value;
    sp.web.lists.getByTitle(this.properties.listName).items.getById(parseInt(deleteItemId)).delete().then(result=>{
      messageDom.innerHTML = "刪除成功!";
    }).catch(e=>{
      messageDom.innerHTML = "刪除失敗! 錯誤: " + e.message;
    });
  }

         為了演示方便,在更新一個item的時候只要指定item的id即可,item的標題會自動更新為“標題”+當前時間。

        儲存檔案,確保啟動了gulp serve,開啟線上的workbench工作臺,重新新增webpart,點選“顯示list”按鈕,會發現webpart列出了當前站點下的列表:


       其中倒數第二個是我建立的一個custom list,也就是自定義列表,表的結構如下:


        下面演示一下如何在這個列表上操作item。首先在webpart屬性編輯器中的列表名稱中填上“自定義列表”,然後點選“應用”按鈕:

            點選webpart上的“顯示item”按鈕,webpart會呼叫showItems()方法列出“自定義列表”中的所有item:

        接下來可以建立一個item,輸入標題,然後點選“新建item”按鈕:

       可以看到新的item被成功創建出來,並且顯示新建item的id:

        同樣可以嘗試更新item以及刪除item的功能,這裡不在贅述,本文完整程式碼已經上傳到碼雲,下載地址:

        https://gitee.com/shrenk/SPFx-webpartcrud.git