javascript - Transform a SPFX TS without JS framework to a React TS
问题描述
I used yo @microsoft/sharepoint to created a webpart to display a list of items. The solution was created without Javascript framework.
import { Version } from '@microsoft/sp-core-library';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import {
IPropertyPaneConfiguration,
PropertyPaneTextField
} from '@microsoft/sp-property-pane';
import { escape } from '@microsoft/sp-lodash-subset';
import styles from './GetSpListItemsWebPart.module.scss';
import * as strings from 'GetSpListItemsWebPartStrings';
import {
SPHttpClient,
SPHttpClientResponse
} from '@microsoft/sp-http';
import {
Environment,
EnvironmentType
} from '@microsoft/sp-core-library';
export interface IGetSpListItemsWebPartProps {
description: string;
}
export interface ISPLists {
value: ISPList[];
}
export interface ISPList {
ID:string;
Title: string;
Summary : string;
NewsCategory: string;
Created:string;
AttachmentFiles:{
Name:string;
Url:string;
ServerRelativeUrl: string;
}
}
export default class GetSpListItemsWebPart extends BaseClientSideWebPart<IGetSpListItemsWebPartProps> {
private _getListData(): Promise<ISPLists> {
return this.context.spHttpClient.get(this.context.pageContext.web.absoluteUrl + "/_api/lists/GetByTitle('News')/items?$select=*&$expand=AttachmentFiles",SPHttpClient.configurations.v1)
.then((response: SPHttpClientResponse) => {
return response.json();
});
}
private _renderListAsync(): void {
if (Environment.type == EnvironmentType.SharePoint ||
Environment.type == EnvironmentType.ClassicSharePoint) {
this._getListData()
.then((response) => {
this._renderList(response.value);
});
}
}
public titleurl(query:string){
var path="/Lists/News/DispForm.aspx?ID=";
var currdir=this.context.pageContext.web.absoluteUrl;
var result=currdir+path+query;
return result;
}
private _renderList(items: ISPList[]): void {
let html: string = '<table border=1 width=100% style="border-collapse: collapse;">';
html += '<th>ID</th><th>Title</th> <th>Summary</th><th>Created</th><th>Attachments</th>';
items.forEach((item: ISPList) => {
html += `
<tr>
<td>${item.ID}</td>
<td><a href="${this.titleurl(item.ID)}">${item.Title}</a></td>
<td>${item.Title}</td>
<td>${item.Created}</td>
<td>
<img src="${item.AttachmentFiles[0].ServerRelativeUrl}" width="300px" height="300px" />
</td>
</tr>
`;
});
html += '</table>';
const listContainer: Element = this.domElement.querySelector('#spListContainer');
listContainer.innerHTML = html;
}
public render(): void {
this.domElement.innerHTML = `
<div class="${ styles.getSpListItems }">
<div class="${ styles.container }">
<div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${ styles.row }">
<div class="ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1">
<span class="ms-font-xl ms-fontColor-white">Welcome to SharePoint Modern Developmennt</span>
<p class="ms-font-l ms-fontColor-white">Loading from ${this.context.pageContext.web.title}</p>
<p class="ms-font-l ms-fontColor-white">Retrive Data from SharePoint List</p>
</div>
</div>
<div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}">
<div>NEWS List Items</div>
<br>
<div id="spListContainer" />
</div>
</div>`;
this._renderListAsync();
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('description', {
label: strings.DescriptionFieldLabel
})
]
}
]
}
]
};
}
}
This part was rendered successfully.
I then created a solution yo @microsoft/sharepoint using the React option. I am stuck on how to render the HTML documents. Previous it as used to this.domElement, but it says It is not in the class. I attempted to creating another class to render seems unsuccessful. How to print the results?
import * as React from 'react';
import styles from './B.module.scss';
import { IBProps } from './IBProps';
import { escape } from '@microsoft/sp-lodash-subset';
import {
SPHttpClient,
SPHttpClientResponse
} from '@microsoft/sp-http';
import {
Environment,
EnvironmentType
} from '@microsoft/sp-core-library';
import * as ReactDOM from 'react-dom';
export interface ISPLists {
value: ISPList[];
}
export interface ISPList {
ID:string;
Title: string;
Summary : string;
NewsCategory: string;
Created:string;
AttachmentFiles:{
Name:string;
Url:string;
ServerRelativeUrl: string;
}
}
export default class B extends React.Component<IBProps, {}> {
public render(): React.ReactElement<IBProps> {
return (
<div className={ styles.b }>
<div id="spListContainer"></div>
<div className={ styles.container }>
<div className={ styles.row }>
<div className={ styles.column }>
<span className={ styles.title }>Welcome to SharePoint!</span>
<p className={ styles.subTitle }>Customize SharePoint experiences using Web Parts.</p>
<p className={ styles.description }>{escape(this.props.description)}</p>
</div>
</div>
</div>
</div>
);
}
}
export class shownews extends B{
constructor(prop){
super(prop);
public _getListData(): Promise<ISPLists> {
return this.context.spHttpClient.get(this.context.pageContext.web.absoluteUrl + "/_api/lists/GetByTitle('News')/items?$select=*&$expand=AttachmentFiles",SPHttpClient.configurations.v1)
.then((response: SPHttpClientResponse) => {
return response.json();
});
}
public _renderListAsync(): void {
if (Environment.type == EnvironmentType.SharePoint ||
Environment.type == EnvironmentType.ClassicSharePoint) {
this._getListData()
.then((response) => {
this._renderList(response.value);
});
}
}
public titleurl(query:string){
var path="/Lists/News/DispForm.aspx?ID=";
var currdir=this.context.pageContext.web.absoluteUrl;
var result=currdir+path+query;
return result;
}
private _renderList(items: ISPList[]): void {
let html: string = '<table border=1 width=100% style="border-collapse: collapse;">';
html += '<th>ID</th><th>Title</th> <th>Summary</th><th>Created</th><th>Attachments</th>';
items.forEach((item: ISPList) => {
html += `
<tr>
<td>${item.ID}</td>
<td><a href="${this.titleurl(item.ID)}">${item.Title}</a></td>
<td>${item.Title}</td>
<td>${item.Created}</td>
<td>
<img src="${item.AttachmentFiles[0].ServerRelativeUrl}" width="300px" height="300px" />
</td>
</tr>
`;
});
html += '</table>';
const listContainer = React.createElement('h1',{},html);
ReactDOM.render(listContainer, document.getElementById('spListContainer'));
this._renderListAsync();
}
}
}
I do apologize If there are many tutorials on SPFX, REACT JS on CRUD operations. However, I clone it, attempted to npm install or npm i -g, none of the repositories work for me.
2020-01-28
- Rewrote the code to get json directly. The html tags won't render
import * as React from 'react';
import styles from './A.module.scss';
import { IAProps } from './IAProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { PageContext } from "@microsoft/sp-page-context";
import { HttpClient, IHttpClientOptions, HttpClientResponse, SPHttpClient, ISPHttpClientOptions, SPHttpClientResponse } from '@microsoft/sp-http';
import {
Environment,
EnvironmentType
} from '@microsoft/sp-core-library';
export interface ISPLists {
value: ISPList[];
};
export interface ISPList {
ID:string;
Title: string;
Summary : string;
NewsCategory: string;
Created:string;
AttachmentFiles:{
Name:string;
Url:string;
ServerRelativeUrl: string;
};
}
export default class A extends React.Component<IAProps, {}> {
public test:any=[];
public data:any=[];
public geturl(query:string){
var path="/Lists/News/DispForm.aspx?ID=";
var currdir=this.props.pagecontext.web.absoluteUrl;
var result=currdir+path+query;
return result;
}
private getListData(){
const opt: ISPHttpClientOptions = { headers: { 'Content-Type': 'application/json;odata=verbose' } };
return this.props.SPHttpClient.get(this.props.pagecontext.web.absoluteUrl + "/_api/lists/GetByTitle('News')/items?$select=*&$expand=AttachmentFiles",SPHttpClient.configurations.v1,opt)
.then((response: SPHttpClientResponse) => {
response.json().then((json: any) => {
for(let i=0;i<json.value.length;i++){
this.data.push(<div><tr>
<td>${json.ID}</td>
<td><a href="${this.geturl(json.ID)}">${json.Title}</a></td>
<td></td>
<td>${json.Created}</td>
<td><img src="${json.AttachmentFiles.ServerRelativeUrl}" width="300px" height="300px" /></td>
</tr></div>);
}
});
});
}
/*
private renderList(item: ISPList[]): void {
item.forEach((item: ISPList) => {
this.data.push(`<tr>
<td>${item.ID}</td>
<td><a href="${this.geturl(item.ID)}">${item.Title}</a></td>
<td></td>
<td>${item.Created}</td>
<td><img src="${item.AttachmentFiles.ServerRelativeUrl}" width="300px" height="300px" /></td>
</tr>`
);
})
console.log(this.data);
};
*/
/*
private push() {
this.test.push(1);
this.test.push(2);
this.test.push(3);
console.log(this.test);
}
*/
public render(): React.ReactElement<IAProps>{
this.getListData();
console.log(this.data);
return (
<div id="splist">
TEST
<table className={styles.container}>
<tr>
<th>ID</th><th>Title</th> <th>Summary</th><th>Created</th><th>Attachments</th>
</tr>
<tr>
<td></td>
<td><a href="${this.titleurl(item.ID)}">TITLE</a></td>
<td></td>
<td>Created</td>
<td>
</td>
</tr>
{this.data}
1234
</table>
</div>
);
}
}
2020-01-28 18:15
- This Don't Work this. If I .push (data); The Table would have ); all over the place.
this.setState({ items:"<td>{item.ID}</td>
<td>{item.Title}</td>
<td>{item.Summary}</td>
<td>{item.Created}</td>
<td>{item.AttachmentFiles[0].ServerRelativeUrl}</td>" });
This do not work
this.Title.push(<span><td>{item.Title}</td></span>);
this.Url.push(<span><td>{item.AttachmentFiles[0].ServerRelativeUrl}</td></span>);
This Works
this.ID.push(item.ID); /* this.Title.push(<span><td>{item.Title}</td></span>); this.Url.push(<span><td>{item.AttachmentFiles[0].ServerRelativeUrl}</td></span>); */ this.forceUpdate();
If I use an array and use .push to send data including HTML tags the follow screenshot shows the problem.
The Code
public renderList(item: ISPList[]): void {
item.forEach((item: ISPList) => {
this.data.push(<tr>);
this.data.push(<td>{item.ID}</td>);
this.data.push(<td>{item.Title}</td>);
this.data.push(<td>{item.AttachmentFiles[0].ServerRelativeUrl}</td>);
this.data.push(</tr>);
//some brackets...
2020-01-28 1956 Problem TR WITHIN TR Problem: If I write the HTML tags and data in one line the tags will generate it self. But in the render method, I need to add a tag to wrap it will make my output incorrect format.
//some codes before to get the JSON data
this.data.push(<tr>
<td>{item.ID}</td>
<td>{item.Title}</td>
<td>{item.AttachmentFiles[0].ServerRelativeUrl}</td></tr>);
//some more codes
public render(): React.ReactElement<IAProps>{
return (
<div id="splist">
TEST
<table className={styles.container}>
<tr>
<th>ID</th>
<th>Title</th>
<th>Attachments</th>
</tr>
{this.data}
</table>
</div>
);
}
解决方案
Firstly, you need to think about your solution in terms of components (having props or states) that you want to render. In context of your solution you can create a component lets say: 'GetandRenderListItems.tsx' and do all ' _getListData()' stuff. You can use 'componentDidMount()' life cycle hook to call _getListData() function everytime after the component is mounted. Then you need to write html template to render retrieved data (all what you have done in '_renderList()' method) have a look at below snippet to get an idea:
public render(): React.ReactElement<IyourcomponentsProps> {
return (
// your dynamic table html and you should not use inline style but define styles in
scss file and use them.
);
}
Then in your 'yourwebpart.ts' file you can render this component in render() method:
public render(): void {
const element: React.ReactElement<IyourwebpartProps > = React.createElement(
GetandRenderListItems,
{
description: this.properties.description,
// similarly assign values to other props
}
);
ReactDom.render(element, this.domElement);
}
Hopefully this will help.
Edit
you could use array.map() e.g. To render a table using your array you could write something like that.
public render () : React.ReactElement<IyourcomponentsProps> {
return(
<div className={styles.someStyle} >
<table className={styles.container}>
<tr>
<th>ID</th><th>Title</th> <th>Summary</th><th>Created</th
<th>Attachments</th>
</tr>
{ yourArray.map(function(item,key){
let url = this.titleurl(item.ID);
return (<tr className={styles.rowStyle} key={key}> //you can use key if you want to track index
<td></td> <td className={styles.someclass}><a href={url}>{item.Title}</a></td>
</tr> );
})}
</table>
</div>
);
}
推荐阅读
- mongodb - 如何使用 mongo-scala-driver 在查询中复制此 mongodb 正则表达式?
- c - 无法在 lldb 中使用断点和其他功能
- elasticsearch - Elasticsearch Range 大于或字段不存在
- r - 如何在 R 中使用“组”创建分段图表
- android - 如何对齐由 onTouchListener 移动的视图
- python - MongoDB 数据库未从 ThreadPoolExecutor 后台线程更新
- keyboard - 我的稳定器不适合我的 pcb,即使它应该是
- html - 有没有办法改变 Pandoc 在 Markdown 文档中解析 HTML 的方式?
- go - 如何通过 Go 应用在 K8s 中连接 mongodb
- amazon-web-services - AWS Route 53 表示域不存在。NS 已更改并确认。IP 有效,但域名无效