در این آموزش میخواهیم فرم شیرپوینت سفارشی با استفاده از SPFx (بدون فریم ورک جاوا اسکریپت) ایجاد کنیم.
پیشنیازهای سیستم:
محیط را نصب و راه اندازی کنید و سپس پروژه خود را ایجاد کنید.
md TestForm
cd TestForm
yo @microsoft/SharePoint
gulp trust-dev-cert
gulp serve
https://<<Sharepoint site URL>>/_layouts/15/workbench.aspx
با این کار نمونهای از SharePoint workbench مانند نمونه بالا باز میشود و میتوانید webpart خود را در آنجا اضافه کنید تا مستقیماً با لیستها و کتابخانههای شیرپوینت در ارتباط باشد. اما بر خلاف local workbench که هر بار که کد صفحه تغییر می کند به طور خودکار رفرش می شود (به خاطر داشته باشید که gulp serve باید در حال اجرا باشد)، SharePoint workbench باید به صورت دستی رفرش شود تا تغییرات مشاهده شوند.
تست نیازمندیهای Webpart:
سفارشی کردن webpart :
npm install sp-pnp-js –save
npm install –save @types/jquery@3 -D
هنگامی که پروژه برای توزیع ساخته می شود، این دایرکتوریها و فایلها به طور خودکار در lib تحت hierarchy مشابه کپی می شوند.
از قسمت config، config.json را باز کنید و موارد زیر را در externals attribute اضافه کنید:
"externals": {
"jquery": {
"path": "https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js",
"globalName": "jquery"
},
"bootstrap": {
"path": "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js",
"globalName": "bootstrap",
"globalDependencies": ["jquery"]
},
"appjs": {
"path": "lib/webparts/testForm/scripts/app.js",
"globalName": "appjs"
},
"sppeoplepicker": {
"path": "lib/webparts/testForm/scripts/sp.peoplepicker.js",
"globalName": "sppeoplepicker"
},
"jqueryui": {
"path": "lib/webparts/testForm/scripts/jquery-ui.js",
"globalName": "jqueryui"
}
}
import { SPComponentLoader } from '@microsoft/sp-loader';
import pnp, { sp, Item, ItemAddResult, ItemUpdateResult, Web } from 'sp-pnp-js';
import * as $ from 'jquery';
require('bootstrap');
require('./css/jquery-ui.css');
let cssURL = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css";
SPComponentLoader.loadCss(cssURL);
SPComponentLoader.loadScript("https://ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js");
require('appjs');
require('sppeoplepicker');
require('jqueryui');
import { UrlQueryParameterCollection, Version } from '@microsoft/sp-core-library';
public render(): void {
this.domElement.innerHTML = `
<div id="container" class="container">
<div class="panel">
<div class="panel-body">
<div class="row">
<div class="col-lg-4 control-padding">
<label>Activity</label>
<input type='textbox' name='txtActivity' id='txtActivity' class="form-control" value="" placeholder="" >
</div>
<div class="col-lg-4 control-padding">
<label>Activity Performed By</label>
<div id="ppDefault"></div>
</div>
<div class="col-lg-4 control-padding">
<label>Activity Date</label>
<div class="input-group date" data-provide="datepicker">
<input type="text" class="form-control" id="txtDate" name="txtDate">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 control-padding">
<label>Category</label>
<select name="ddlCategory" id="ddlCategory" class="form-control">
</select>
</div>
<div class="col-lg-6 control-padding">
<label>Sub Category</label>
<select name="ddlSubCategory" id="ddlSubCategory" class="form-control">
</select>
</div>
</div>
<div class="row">
<div class="col col-lg-12">
<button type="button" class="btn btn-primary buttons" id="btnSubmit">Save</button>
<button type="button" class="btn btn-default buttons" id="btnCancel">Cancel</button>
</div>
</div>
</div>
</div>`;
(<any>$("#txtDate")).datepicker(
{
changeMonth: true,
changeYear: true,
dateFormat: "mm/dd/yy"
}
);
(<any>$('#ppDefault')).spPeoplePicker({
minSearchTriggerLength: 2,
maximumEntitySuggestions: 10,
principalType: 1,
principalSource: 15,
searchPrefix: '',
searchSuffix: '',
displayResultCount: 6,
maxSelectedUsers: 1
});
this.AddEventListeners();
this.getCategoryData();
}
در متد render کد زیر datepicker control را مقداردهی اولیه می کند:
(<any>$("#txtDate")).datepicker(
{
changeMonth: true,
changeYear: true,
dateFormat: "mm/dd/yy"
}
);
و کد زیر people picker را مقداردهی اولیه می کند:
(<any>$('#ppDefault')).spPeoplePicker({
minSearchTriggerLength: 2,
maximumEntitySuggestions: 10,
principalType: 1,
principalSource: 15,
searchPrefix: '',
searchSuffix: '',
displayResultCount: 6,
maxSelectedUsers: 1
});
توجه داشته باشید که من قبل از مقداردهی اولیه هر دو کنترل از <any> استفاده کرده ام، زیرا در SPFx اگر بخواهیم کنترلها را بدون <any> مقداردهی اولیه کنیم، با خطای "method not found" مواجه خواهیم شد.
private AddEventListeners(): any {
document.getElementById('btnSubmit').addEventListener('click', () => this.SubmitData());
document.getElementById('btnCancel').addEventListener('click', () => this.CancelForm());
document.getElementById('ddlSysWorked').addEventListener('change', () => this.PopulateSubCategory());
}
private _getCategoryData(): any {
return pnp.sp.web.lists.getByTitle("Category").items.select("Category").getAll().then((response) => {
return response;
});
}
private getCategoryData(): any {
this._getCategoryData()
.then((response) => {
this._renderCategoryList(response);
});
}
private _renderCategoryList(items: any): void {
let html: string = '';
html += `<option value="Select Category" selected>Select Category</option>`;
items.forEach((item: any) => {
html += `
<option value="${item.Category}">${item.Category}</option>`;
});
const listContainer1: Element = this.domElement.querySelector('#ddlCategory');
listContainer1.innerHTML = html;
}
public PopulateSubCategory() {
this.getSubCategoryData($("#ddlCategory").val().toString());
}
private _getSubCategoryData(category): any {
return pnp.sp.web.lists.getByTitle("SubCategory").items.select("SubCategory").filter("Category eq '" + category + "'").getAll().then((response) => {
return response;
});
}
private getSubCategoryData(category): any {
this._getSubCategoryData(category)
.then((response) => {
this._renderSubCategoryList(response);
});
}
private _renderSubCategoryList(items: any): void {
let html: string = '';
html += `<option value="Select Sub Category" selected>Select Sub Category</option>`;
items.forEach((item: any) => {
html += `
<option value="${item.SubCategory}">${item.SubCategory}</option>`;
});
const listContainer1: Element = this.domElement.querySelector('#ddlSubCategory');
listContainer1.innerHTML = html;
}
private CancelForm() {
window.location.href = this.GetQueryStringByParameter("Source");
}
private GetQueryStringByParameter(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
private SubmitData(){
var userinfo = (<any>$('#ppDefault')).spPeoplePicker('get');
var userId;
var userDetails = this.GetUserId(userinfo[0].email.toString());
console.log(JSON.stringify(userDetails));
userId = userDetails.d.Id;
pnp.sp.web.lists.getByTitle('RigActiveList_Job_Cards_Area').items.add({
Title: "Test",
Activity: $("#txtActivity").val().toString(),
Activity_Date: $("#txtDate").val().toString(),
Activity_ById : userId,
Category: $("#ddlCategory").val().toString(),
SubCategory: $("#ddlSubCategory").val().toString(),
});
}
private GetUserId(userName) {
var siteUrl = this.context.pageContext.web.absoluteUrl;
var call = $.ajax({
url: siteUrl + "/_api/web/siteusers/getbyloginname(@v)?@v=%27i:0%23.f|membership|" + userName + "%27",
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
async: false,
dataType: 'json'
}).responseJSON;
return call;
}
توجه داشته باشید که ما از یک روش GetUSerID جداگانه استفاده کرده ایم. sp.peoplepicker.js control یک شی userinfo را برمی گرداند و شناسه کاربر انتخاب شده را برنمیگرداند. اما برای ذخیره کاربر به عنوان یک شخص یا شی گروه در لیست شیرپوینت، به شناسه نیاز داریم. بنابراین شی userinfo را به متد GetUserId ارسال می کنیم و شناسه را برای ذخیره به لیست شیرپوینت برمی گردانیم.
این طرح نهایی فرم است:
به این ترتیب توانستیم اولین SPFx webpart خود را راهاندازی و اجرا کنیم.
چگونه امتیاز دهی به یک فایل را در SharePoint فعال کنیم؟
امیرحسین غلامیانتغییر عرض نمایش ستون ها
Fletch Skinnerتغییر عرض نمایش ستون ها
Chauffina CarrID Outcome ها در Flexi task
Fletch Skinner