这是我第一次尝试使用 office ui fabric react JS 在 SharePoint Online 中开发 Web 部件应用程序。对于一个测试(CRUD 应用程序)项目,我开发了一个在线图书库应用程序。我一直在努力从共享点列表中保存/获取日期值,但由于某种原因出现错误,如下所示:
我的 tsx 文件代码如下:
import * as React from 'react';
import styles from './HelloWorld.module.scss';
import { IHelloWorldProps } from './IHelloWorldProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { BookLibListItem } from './BookLibListItem';
import { IBookLibCollection } from './IBookLibCollection';
import { ISPHttpClientOptions, SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
import {
TextField,
autobind,
PrimaryButton,
DetailsList,
DetailsListLayoutMode,
CheckboxVisibility,
SelectionMode,
Dropdown,
DatePicker,
IDatePickerStrings,
IDropdown,
IDropdownOption,
ITextFieldStyles,
IDropdownStyles,
DetailsRowCheck,
Selection,
DayOfWeek
} from 'office-ui-fabric-react';
const DayPickerStrings: IDatePickerStrings = {
months: [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
],
shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
shortDays: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
goToToday: 'Go to today',
prevMonthAriaLabel: 'Go to previous month',
nextMonthAriaLabel: 'Go to next month',
prevYearAriaLabel: 'Go to previous year',
nextYearAriaLabel: 'Go to next year',
closeButtonAriaLabel: 'Close date picker'
};
/*
export interface IDatePickerBasicExampleState {
firstDayOfWeek?: DayOfWeek;
}
*/
// Configure the columns for the DetailsList component
let _bookListColumns = [
{
key: 'ID',
name: 'ID',
fieldName: 'ID',
minWidth: 50,
maxWidth: 100,
isResizable: true
},
{
key: 'Title',
name: 'Title',
fieldName: 'Title',
minWidth: 50,
maxWidth: 100,
isResizable: true
},
{
key: 'Author',
name: 'Author',
fieldName: 'Author',
minWidth: 50,
maxWidth: 100,
isResizable: true
},
{
key: 'Publisher',
name: 'Publisher',
fieldName: 'Publisher',
minWidth: 50,
maxWidth: 100,
isResizable: true
},
{
key: 'DateOfPublish',
name: 'DateOfPublish',
fieldName: 'DateOfPublish',
minWidth: 50,
maxWidth: 100,
isResizable: true
},
{
key: 'ISBN',
name: 'ISBN',
fieldName: 'ISBN',
minWidth: 50,
maxWidth: 150,
isResizable: true
}
];
const textFieldStyles: Partial<ITextFieldStyles> = { fieldGroup: { width: 300 } };
const narrowTextFieldStyles: Partial<ITextFieldStyles> = { fieldGroup: { width: 100 } };
const narrowDropdownStyles: Partial<IDropdownStyles> = { dropdown: { width: 300 } };
function SetDate(props) {
//const firstDayOfWeek = React.useState(DayOfWeek.Sunday);
return (<DatePicker
{...props.value && moment(props.value).isValid() ? { value: moment(props.value).toDate() } : {}}
className={css(styles.dateFormField, 'dateFormField')}
placeholder="Select a date..."
isRequired={props.Required}
ariaLabel={props.Title}
parseDateFromString={(dateStr?: string) => { return moment(dateStr, 'L').toDate(); }}
formatDate={(date: Date) => (typeof date.toLocaleDateString === 'function') ? date.toLocaleDateString(locale as any) : ""}
strings={DayPickerStrings}
allowTextInput={true}
onSelectDate={(date) => {
if (date) props.valueChanged(date.toISOString());
else props.valueChanged('');
}}
/>);
;
}
function GetDate(props){
const value = (props.value && moment(props.value).isValid()) ? moment(props.value,"YYYY-MM-DD").format('L') : '';
return <FieldDateRenderer text={value} />;
}
export default class HelloWorld extends React.Component<IHelloWorldProps, IBookLibCollection, React.FC> {
private _selection: Selection;
//firstDayOfWeek = React.useState(DayOfWeek.Sunday);
private _onItemsSelectionChanged = () => {
this.setState({
BookListItem: (this._selection.getSelection()[0] as BookLibListItem)
});
}
private _getListItems(): Promise<BookLibListItem[]> {
const url: string = this.props.siteUrl + "/_api/web/lists/getbytitle('Book%20Library')/items";
return this.props.context.spHttpClient.get(url,SPHttpClient.configurations.v1)
.then(response => {
console.log(response);
return response.json();
})
.then(json => {
return json.value;
}) as Promise<BookLibListItem[]>;
}
public bindDetailsList(message: string) : void {
this._getListItems().then(listItems => {
console.log(listItems);
this.setState({ BookListItems: listItems,status: message});
});
}
public componentDidMount(): void {
this.bindDetailsList("All Records have been loaded Successfully");
}
@autobind
public btnAdd_click(): void {
const url: string = this.props.siteUrl + "/_api/web/lists/getbytitle('Book%20Library')/items";
const spHttpClientOptions: ISPHttpClientOptions = {
"body": JSON.stringify(this.state.BookListItem)
};
this.props.context.spHttpClient.post(url, SPHttpClient.configurations.v1, spHttpClientOptions)
.then((response: SPHttpClientResponse) => {
if (response.status === 201) {
this.bindDetailsList("Record added and All Records were loaded Successfully");
} else {
let errormessage: string = "An error has occured i.e. " + response.status + " - " + response.statusText;
this.setState({status: errormessage});
}
});
}
@autobind
public btnUpdate_click(): void {
let id: number = this.state.BookListItem.Id;
const url: string = this.props.siteUrl + "/_api/web/lists/getbytitle('Book%20Library')/items(" + id + ")";
const headers: any = {
"X-HTTP-Method": "MERGE",
"IF-MATCH": "*",
};
const spHttpClientOptions: ISPHttpClientOptions = {
"headers": headers,
"body": JSON.stringify(this.state.BookListItem)
};
this.props.context.spHttpClient.post(url, SPHttpClient.configurations.v1, spHttpClientOptions)
.then((response: SPHttpClientResponse) => {
if (response.status === 204) {
this.bindDetailsList("Record Updated and All Records were loaded Successfully");
} else {
let errormessage: string = "An error has occured i.e. " + response.status + " - " + response.statusText;
this.setState({status: errormessage});
}
});
}
@autobind
public btnDelete_click(): void {
let id: number = this.state.BookListItem.Id;
const url: string = this.props.siteUrl + "/_api/web/lists/getbytitle('Book%20Library')/items(" + id + ")";
const headers: any = { "X-HTTP-Method": "DELETE", "IF-MATCH": "*" };
const spHttpClientOptions: ISPHttpClientOptions = {
"headers": headers
};
this.props.context.spHttpClient.post(url, SPHttpClient.configurations.v1, spHttpClientOptions)
.then((response: SPHttpClientResponse) => {
if (response.status === 204) {
alert("record got deleted successfully....");
this.bindDetailsList("Record deleted and All Records were loaded Successfully");
} else {
let errormessage: string = "An error has occured i.e. " + response.status + " - " + response.statusText;
this.setState({status: errormessage});
}
});
}
constructor(props: IHelloWorldProps, state: IBookLibCollection){
super(props);
this.state = {
status: 'Ready',
BookListItems: [],
BookListItem:{
Id: 0,
Title: "",
Author: "",
Publisher: "",
DateOfPublish: new Date,
ISBN: 0
},
};
this._selection = new Selection({
onSelectionChanged: this._onItemsSelectionChanged,
});
}
public render(): React.ReactElement<IHelloWorldProps> {
const dropdownRef = React.createRef<IDropdown>();
return (
<div className={ styles.helloWorld }>
<TextField
label="ID"
required={ false }
value={ (this.state.BookListItem.Id).toString()}
styles={textFieldStyles}
onChanged={e => {this.state.BookListItem.Id=e;}}
/>
<TextField
label="Title"
required={ true }
value={ (this.state.BookListItem.Title)}
styles={textFieldStyles}
onChanged={e => {this.state.BookListItem.Title=e;}}
/>
<TextField
label="Author"
required={ true }
value={ (this.state.BookListItem.Author)}
styles={textFieldStyles}
onChanged={e => {this.state.BookListItem.Author=e;}}
/>
<TextField
label="Publisher"
required={ true }
value={ (this.state.BookListItem.Publisher)}
styles={textFieldStyles}
onChanged={e => {this.state.BookListItem.Publisher=e;}}
/>
<SetDate
value={this.state.BookListItem.DateOfPublish}
Required={true}
Title="DateOfPublish"
//firstDayOfWeek={firstDayOfWeek}
/>
<TextField
label="ISBN"
required={ true }
value={ (this.state.BookListItem.ISBN.toString())}
styles={textFieldStyles}
onChanged={e => {this.state.BookListItem.ISBN=e;}}
/>
<p className={styles.title}>
<PrimaryButton
text='Add'
title='Add'
onClick={this.btnAdd_click}
/>
<PrimaryButton
text='Update'
onClick={this.btnUpdate_click}
/>
<PrimaryButton
text='Delete'
onClick={this.btnDelete_click}
/>
</p>
<div id="divStatus">
{this.state.status}
</div>
<div>
<DetailsList
items={ this.state.BookListItems}
columns={ _bookListColumns }
setKey='Id'
checkboxVisibility={ CheckboxVisibility.onHover}
selectionMode={ SelectionMode.single}
layoutMode={ DetailsListLayoutMode.fixedColumns }
compact={ true }
selection={this._selection}
/>
</div>
</div>
);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
我使用以下接口作为 SharePoint 中列表的数据模型:
export interface BookLibListItem {
Id: number;
Title: string;
Author: string;
Publisher: string;
DateOfPublish: Date;
ISBN: number;
}
感谢有关此问题的任何建议。