SharePoint Framework (SPFx)

SharePoint Framework (SPFx) WebPart SharePoint Entegrasyonu Bölüm 2

Bir önceki makalemizde SharePoint Framework içerisinde kullanışlı olacak method ve class değinmiştik. Şimdi SharePoint ile entegrasyon sağlayan ufak bir modül yazalım.

Şöyle bir senaryomuz olsun: bulunduğu web içerisinde ve parametre olarak aldığı SharePoint listesine bağlanıp, Title fieldını çekip, WebPart içerisinde görüntüleyelim.

Model Tanımlama

Projemiz içerisine “models” diye bir klasör oluşturalım. İhtiyacınıza göre siz farklı isimlendirme yapabilirsiniz. Bazı kısımları çok karmaşıklaştırmamak adına değinmiyor olacağım. Model tanımlamak katmanlar arasında size gelecek data hakkında bilgi vermesine ve daha statik olarak ilerleneceği için OOP açısından sağlıklı olacaktır.

Şimdi adım adım işlemlerimize bir göz atalım:

“Item.ts” isminde dosya oluşturalım.

export default class Item {
    Title: string;
    Id: number;
    
    constructor(options: Item) {
        this.Title = options.Title;
        this.Id = options.Id;
    }
}

“IListService.ts” isminde dosya oluşturalım.

import Item from "./Item";
import { IWebPartContext } from "@microsoft/sp-webpart-base";

export interface IListService {
    getItems(): Promise<Array<Item>>;
    context: IWebPartContext;
    listName: string;
}

“models” ile ilgili işlemlerimiz bu kadar. İsterseniz GitHub üzerinden görüntüleyebilirsiniz.

Servis Tanımlama

Verilerimizi component e ileten bir data provider ihtiyacımız bulunmaktadır. Bunun için “services” isimli bir klasör oluşturunuz.

  • “HelloWorldService.ts” isimli dosyayı oluşturup, aşağıdaki gibi güncelleyiniz. TypeScript ile pattern örneği olarak, singleton pattern kullandım.
import Item from '../models/Item';
import { IListService } from '../models/IListService';
import {
    SPHttpClient,
    SPHttpClientResponse
} from '@microsoft/sp-http';
import { IWebPartContext } from '../../../../node_modules/@microsoft/sp-webpart-base';
import { isNull, isEmpty } from 'lodash';

export class HelloWorldService implements IListService {

    context: IWebPartContext;
    listName: string;
    private static instance: HelloWorldService;

    private constructor() {
    }

    static getInstance() {
        if (!HelloWorldService.instance) {
            HelloWorldService.instance = new HelloWorldService();
        }
        return HelloWorldService.instance;
    }

    getItems(): Promise<Array<Item>> {
        return new Promise((resolve, reject) => {
            if (isNull(this.listName) == false && isEmpty(this.listName) == false) {
                this.context.spHttpClient.get(this.context.pageContext.web.absoluteUrl + `/_api/web/lists/getbytitle('${this.listName}')/items?$select=Title,Id`, SPHttpClient.configurations.v1)
                    .then((response: SPHttpClientResponse) => {
                        return response.json();
                    }).then((result) => {
                        resolve(result.value.map((spItem) => {
                            return new Item({
                                Id: spItem.Id,
                                Title: spItem.Title
                            })
                        }));
                    });

            }
            else {
                reject("Lütfen 'listName' parametresini giriniz.");
            }
        });
    }
}

export default HelloWorldService.getInstance();

“HelloWorldServiceMock.ts” isimli dosyayı oluşturup, aşağıdaki gibi güncelleyiniz.

import Item from '../models/Item';
import { IListService } from '../models/IListService';
import { IWebPartContext } from '../../../../node_modules/@microsoft/sp-webpart-base';
import { isNull,isEmpty } from 'lodash';


export class HelloWorldServiceMock implements IListService {
    context: IWebPartContext;
    listName: string;
    private static instance: HelloWorldServiceMock;

    private constructor() {
    }

    static getInstance() {
        if (!HelloWorldServiceMock.instance) {
            HelloWorldServiceMock.instance = new HelloWorldServiceMock();
        }
        return HelloWorldServiceMock.instance;
    }

    getItems(): Promise<Array<Item>> {
        return new Promise((resolve, reject) => {
            if (isNull(this.listName) == false && isEmpty(this.listName) == false) {
                const fakeData: Array<Item> = [
                    {
                        Id: 0,
                        Title: "Title 1"
                    },
                    {
                        Id: 1,
                        Title: "Title 2"
                    },
                    {
                        Id: 2,
                        Title: "Title 3"
                    },
                    {
                        Id: 3,
                        Title: "Title 4"
                    },
                    {
                        Id: 4,
                        Title: "Title 5"
                    },
                ];

                resolve(fakeData);
            } else {
                reject("Lütfen 'listName' parametresini giriniz.");
            }

        });
    }
}

export default HelloWorldServiceMock.getInstance();

“services” ile ilgili işlemlerimiz bu kadar, isterseniz GitHub üzerinden görüntüleyebilirsiniz.

SPFx WebPart Güncelleme

Model ve servis tarafı ile ilgili kodumuzu yazdık. Şimdi bunları daha önceden öğrenmiş olduğumuz “EnvironmentType” göre servisleri yüklememiz ve “listName” isimli property güncellememiz gerekmektedir. İlk olarak “HelloWorldWebPart.ts” isimli dosyayı açıp aşağıdaki gibi güncelleyiniz. İsterseniz GitHub üzerinden görüntüleyebilirsiniz.

import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version, Environment, EnvironmentType } from '@microsoft/sp-core-library';
import {
  BaseClientSideWebPart,
  IPropertyPaneConfiguration,
  PropertyPaneTextField
} from '@microsoft/sp-webpart-base';

import * as strings from 'HelloWorldWebPartStrings';
import HelloWorld from './components/HelloWorld';
import { IHelloWorldProps } from './components/IHelloWorldProps';
import { IListService } from './models/IListService';
import HelloWorldService from './services/HelloWorldService';
import HelloWorldServiceMock from './services/HelloWorldServiceMock';

export interface IHelloWorldWebPartProps {
  listName: string;
}

export default class HelloWorldWebPart extends BaseClientSideWebPart<IHelloWorldWebPartProps> {
  private _listService: IListService;

  protected onInit(): Promise<void> {
    if (Environment.type === EnvironmentType.Local) {
      this._listService = HelloWorldServiceMock;
    } else {
      this._listService = HelloWorldService;
    }

    this._listService.context = this.context;
    this._listService.listName = this.properties.listName;

    return super.onInit();
  }

  public setReactComponent() {
    const element: React.ReactElement<IHelloWorldProps> = React.createElement(
      HelloWorld,
      {
        listService: this._listService,
      }
    );
    ReactDom.render(element, this.domElement);
  }

  public render(): void {
    this.setReactComponent();
  }

  protected onDispose(): void {
    ReactDom.unmountComponentAtNode(this.domElement);
  }

  protected get dataVersion(): Version {
    return Version.parse('1.0');
  }

  protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneHelloWorld
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('listName', {
                  label: strings.ListNameFieldLabel
                })
              ]
            }
          ]
        }
      ]
    };
  }
}

Localization Güncelleme

Yukarıdaki WebPart ımızı güncelledikten sonra “loc” klasörü içerisinde yer alan dosyaları güncellemeniz gerekmektedir.

“loc” içerisinde yer alan “mystrings.d.ts” isimli dosyayı açınız ve aşağıdaki gibi güncelleyiniz.

declare interface IHelloWorldWebPartStrings {
  PropertyPaneHelloWorld: string;
  BasicGroupName: string;
  ListNameFieldLabel: string;
}

declare module 'HelloWorldWebPartStrings' {
  const strings: IHelloWorldWebPartStrings;
  export = strings;
}

“loc” içerisinde yer alan “en-us.js” isimli dosyayı açınız ve aşağıdaki gibi güncelleyiniz.

define([], function() {
  return {
    "PropertyPaneHelloWorld": "Hello World Pane",
    "BasicGroupName": "Group Name",
    "ListNameFieldLabel": "List Name Field"
  }
});

React Component Güncelleme

İlk olarak “components” klasörü içerisinde yer alan “IHelloWorldProps.ts” dosyasını açıp aşağıdaki gibi güncelleyiniz. Burada “listService” props tanımlıyoruz ve interface olarak belirtiyoruz, environment göre mock ya da gerçek datanın servisi geliyor olacaktır.

import { IListService } from "../models/IListService";

export interface IHelloWorldProps {
  listService:IListService;
}

“components” klasörü içerisinde “IHelloWorldState.ts” isimli dosyayı oluşturunuz ve aşağıdaki gibi güncelleyiniz.

import Item from "../models/Item";

export interface IHelloWorldState {
  items: Array<Item>;
  loading:boolean;
  error?:Error;
}

Son olarak React component güncellememiz gerekmektedir. “HelloWorld.tsx” dosyasını açınız ve aşağıdaki gibi güncelleyiniz.

import * as React from 'react';
import styles from './HelloWorld.module.scss';
import { IHelloWorldProps } from './IHelloWorldProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { IHelloWorldState } from './IHelloWorldState';
import Item from '../models/Item';

export default class HelloWorld extends React.Component<IHelloWorldProps, IHelloWorldState> {

  constructor(props: IHelloWorldProps) {
    super(props);
    this.state = {
      items: new Array<Item>(),
      loading: true
    };
  }

  public getListItems() {
    this.props.listService.getItems().then((data: Array<Item>) => {
      this.setState({ items: data, loading: false });
    }).catch((err) => {
      this.setState({ error: err, loading: false });
      console.error('HelloWorld', err);
    });
  }

  public componentDidMount(): void {
    this.getListItems();
  }
 
  public render(): React.ReactElement<IHelloWorldProps> {

    var getItemRender = this.state.items.map((listItem, i) => {
      return <li key={i}>
        {listItem.Title}
      </li>;
    });

    var getRender = () => {
      if (this.state.loading == true) {
        return <div>Yükleniyor...</div>
      }
      else if (this.state.error) {
        return <div>WebPart yüklenirken hata ile karşılaşıldı, lütfen console üzerinden görüntüleyiniz.</div>
      }
      else {
        return <div>
          <h1>{this.props.listService.listName}</h1>
          <ul>
            {getItemRender}
          </ul>
        </div>
      }
    }

    return (
      <div className={styles.helloWorld}>
        {getRender()}
      </div>
    );
  }
}
Local Workbench ekran görüntüsü
SharePoint Workbench ekran görüntüsü

GitHub source code

Bir sonraki makale plugin kullanımı üzerine olacak, görüşmek üzere.

Serdar KETENCİ

Recent Posts

SharePoint TechNet/MSDN Forumları emekliye ayrılıyor

Microsoft SharePoint Technet ve MSDN forumları yerini Microsoft Q&A tartışma panolarına yerini bırakıyor. 10 Ağustos…

4 sene ago

Lokalde React ile uzak SharePoint ortamında Rest API ile çalışmak

Biliyorum, başlık çok garip, ilk bakışta anlaşılması zor. Ama şöyle tarif etmeye çalışayım. Bildiğiniz üzere…

4 sene ago

TypeScript Geliştirme Ortamı Hazırlama

Merhaba Arkadaşlar, Bu yazımızda sizlere TypeScript geliştirme ortamının (TypeScript Development Environment) nasıl hazırlanacağından bahsedeceğim. Öncelikle…

5 sene ago

TypeScript ile SystemJS kullanma

Merhabalar, bu yazımızda sizlere bir TypeScript projesinde farklı ts dosyaları içerisindeki function, class veya interface'lerin,…

5 sene ago

TypeScript – Giriş

Merhaba arkadaşlar, Yakın zamanda TypeScript öğrenmeye başladım. Hem öğrendiklerimi pekiştirmek hem de sizlerle paylaşmak adına…

5 sene ago

SharePoint için Responsive UI

Merhaba Arkadaşlar, Bu yazımızda sizlere mevcut SharePoint portalimizin, tablet, cep telefonu gibi farklı çözünürlükteki cihazlarda…

5 sene ago